<div class="title">
I am text node
<a class="edit">Edit</a>
</div>
Chcę otrzymać opcję „Jestem węzłem tekstowym”, nie chcę usuwać tagu „edytuj” i potrzebuję rozwiązania obsługującego wiele przeglądarek.
javascript
jquery
Val
źródło
źródło
Odpowiedzi:
Pobiera element
contents
z wybranego elementu i stosuje do niego funkcję filtrującą. Funkcja filtru zwraca tylko węzły tekstowe (tj. Te znodeType == Node.TEXT_NODE
).źródło
text()
ponieważfilter
funkcja zwraca same węzły, a nie zawartość węzłów.jQuery("*").each(function() { console.log(this.nodeType); })
i otrzymałem 1 dla wszystkich typów węzłów.Możesz uzyskać wartość nodeValue pierwszego childNode za pomocą
http://jsfiddle.net/TU4FB/
źródło
null
wartość zwracaną.Jeśli masz na myśli pobranie wartości pierwszego węzła tekstowego w elemencie, ten kod zadziała:
Możesz to zobaczyć w akcji tutaj: http://jsfiddle.net/ZkjZJ/
źródło
curNode.nodeType == 3
zamiast tegonodeName
.curNode.nodeType == Node.TEXT_NODE
(porównanie liczbowe jest szybsze, ale curNode.nodeType == 3 jest nieczytelne - który węzeł ma numer 3?)curNode.NodeType === Node.TEXT_NODE
. To porównanie zachodzi w pętli nieznanych możliwych iteracji. Porównywanie dwóch małych liczb jest lepsze niż porównywanie łańcuchów o różnych długościach (względy czasu i przestrzeni). Prawidłowe pytanie, które należy zadać w tej sytuacji, to „jaki mam rodzaj / typ węzła?”, A nie „jaką mam nazwę?” developer.mozilla.org/en-US/docs/Web/API/Node/nodeTypechildNodes
, wiedz, że węzeł elementu może mieć więcej niż jeden węzeł tekstowy. W rozwiązaniu ogólnym może być konieczne określenie, do której instancji węzła tekstowego w węźle elementu chcesz kierować (pierwszą, drugą, trzecią itd.).Innym natywnym rozwiązaniem JS, które może być przydatne w przypadku „złożonych” lub głęboko zagnieżdżonych elementów, jest użycie NodeIterator . Umieść
NodeFilter.SHOW_TEXT
jako drugi argument („whatToShow”) i przeprowadź iterację tylko po elementach potomnych węzła tekstowego.Możesz także użyć
TreeWalker
. Różnica między nimi polega na tym, żeNodeIterator
jest prostym liniowym iteratorem, a jednocześnieTreeWalker
umożliwia nawigację za pośrednictwem rodzeństwa i przodków.źródło
Czysty JavaScript: minimalistyczny
Po pierwsze, zawsze miej to na uwadze, szukając tekstu w DOM.
MDN - odstępy w DOM
Ta kwestia sprawi, że zwrócisz uwagę na strukturę swojego XML / HTML.
W tym czystym przykładzie JavaScript uwzględniam możliwość wielu węzłów tekstowych, które można przeplatać z innymi rodzajami węzłów . Jednak początkowo nie oceniam białych znaków, pozostawiając to zadanie filtrowania innemu kodowi.
W tej wersji przekazuję
NodeList
kod wywołujący / klienta.Oczywiście, testując
node.hasChildNodes()
najpierw, nie byłoby potrzeby używaniafor
pętli przed testem .Czysty JavaScript: solidny
Tutaj funkcja
getTextById()
używa dwóch funkcji pomocniczych:getStringsFromChildren()
ifilterWhitespaceLines()
.getStringsFromChildren ()
filterWhitespaceLines ()
getTextById ()
Następnie wartość zwracana (Array lub null) jest wysyłana do kodu klienta, w którym ma być obsługiwana. Miejmy nadzieję, że tablica powinna zawierać elementy tekstowe prawdziwego tekstu, a nie wiersze odstępów.
Puste ciągi (
""
) nie są zwracane, ponieważ potrzebny jest węzeł tekstowy do prawidłowego wskazania obecności prawidłowego tekstu. Zwracanie (""
) może dawać fałszywe wrażenie, że istnieje węzeł tekstowy, co prowadzi do założenia, że może zmienić tekst, zmieniając wartość.nodeValue
. To jest fałsz, ponieważ węzeł tekstowy nie istnieje w przypadku pustego ciągu.Przykład 1 :
Przykład 2 :
Problem pojawia się, gdy chcesz, aby kod HTML był łatwy do odczytania, rozstawiając go. Teraz, mimo że nie ma poprawnego tekstu czytelnego dla człowieka, nadal istnieją węzły tekstowe ze
"\n"
znakami nowej linii ( ) we.nodeValue
właściwościach.Ludzie widzą przykłady pierwszy i drugi jako równoważne funkcjonalnie - puste elementy czekające na wypełnienie. DOM różni się od ludzkiego rozumowania. Dlatego
getStringsFromChildren()
funkcja musi określić, czy istnieją węzły tekstowe i zebrać.nodeValue
wartości w tablicy.W przykładzie dwa istnieją dwa węzły tekstowe i
getStringFromChildren()
zwrócą wartość.nodeValue
obu z nich ("\n"
). JednakfilterWhitespaceLines()
używa wyrażenia regularnego, aby odfiltrować wiersze zawierające czyste białe znaki.Czy powrót
null
zamiast"\n"
znaków nowej linii ( ) jest formą okłamywania klienta / kodu wywołującego? W kategoriach ludzkich nie. W kategoriach DOM, tak. Jednak problemem jest tutaj pobranie tekstu, a nie jego edycja. Nie ma tekstu, który mógłby powrócić do kodu wywołującego.Nigdy nie wiadomo, ile znaków nowej linii może pojawić się w czyimś kodzie HTML. Tworzenie licznika szukającego „drugiego” znaku nowej linii jest zawodne. Może nie istnieć.
Oczywiście w dalszej części linii, kwestia edycji tekstu w pustym
<p></p>
elemencie z dodatkowymi białymi znakami (przykład 2) może oznaczać zniszczenie (być może przeskoczenie) wszystkich węzłów tekstowych z wyjątkiem jednego między znacznikami akapitu, aby upewnić się, że element zawiera dokładnie to, czym jest powinien wyświetlić.Niezależnie od tego, z wyjątkiem przypadków, w których robisz coś niezwykłego, będziesz potrzebować sposobu na określenie, która
.nodeValue
właściwość węzła tekstowego zawiera prawdziwy, czytelny dla człowieka tekst, który chcesz edytować.filterWhitespaceLines
prowadzi nas w połowie drogi.W tym momencie możesz otrzymać wynik, który wygląda następująco:
Nie ma gwarancji, że te dwa ciągi są ze sobą sąsiadujące w DOM, więc połączenie ich
.join()
może stworzyć nienaturalny kompozyt. Zamiast tego w kodzie, który wywołujegetTextById()
musisz wybrać ciąg, z którym chcesz pracować.Przetestuj wyjście.
Można dodać
.trim()
wewnątrz,getStringsFromChildren()
aby pozbyć się wiodących i końcowych białych znaków (lub zamienić kilka spacji w ciąg znaków o zerowej długości (""
), ale skąd można wiedzieć a priori, co każda aplikacja może musieć się przydarzyć tekstowi (łańcuchowi) gdy zostanie znaleziony? Nie możesz, więc zostaw to konkretnej implementacji i niechgetStringsFromChildren()
będzie ogólne.Może się zdarzyć, że ten poziom szczegółowości (
target
i taki) nie będzie wymagany. To wspaniale. W takich przypadkach użyj prostego rozwiązania. Jednak uogólniony algorytm umożliwia dostosowanie się do prostych i złożonych sytuacji.źródło
Wersja ES6, która zwraca pierwszą zawartość węzła #text
źródło
.from()
do tworzenia płytkiej kopii tablicy. (2) Użycie.find()
do wykonania porównań ciągów przy użyciu.nodeName
. Używanienode.NodeType === Node.TEXT_NODE
byłoby lepsze. (3) Zwracanie pustego ciągu, gdy nie ma wartościnull
, jest bardziej prawdziwe, jeśli nie zostanie znaleziony węzeł tekstowy . Jeśli nie zostanie znaleziony żaden węzeł tekstowy, może być konieczne jego utworzenie! Jeśli zwrócisz pusty ciąg,""
możesz sprawić fałszywe wrażenie, że istnieje węzeł tekstowy i można nim normalnie manipulować. W istocie zwracanie pustego ciągu jest białym kłamstwem i najlepiej go unikać.[...node.childNodes]
do konwersji HTMLCollection na tablice.text() - for jquery
źródło
a
elemencie: jsfiddle.net/ekHJH.
na początku selektora, co oznacza, że faktycznie otrzymujesz teksttitle
elementu, a nie elementy zclass="title"
.innerText
to stara konwencja IE, przyjęta dopiero niedawno. Jeśli chodzi o standardowe skrypty DOM,node.nodeValue
jest to sposób pobierania tekstu węzła tekstowego.Spowoduje to również zignorowanie białych znaków, więc nigdy nie otrzymałeś pustego kodu textNodes… przy użyciu podstawowego kodu JavaScript.
Sprawdź na jsfiddle: - http://jsfiddle.net/webx/ZhLep/
źródło
curNode.nodeType === Node.TEXT_NODE
byłoby lepiej. Używanie porównania ciągów i wyrażenia regularnego w pętli jest rozwiązaniem o niskiej wydajności, zwłaszcza gdy wielkośćoDiv.childNodes.length
wzrasta. Algorytm ten rozwiązuje specyficzne pytanie OP, ale potencjalnie przy strasznych kosztach wydajności. Jeśli układ lub liczba węzłów tekstowych ulegnie zmianie, nie można zagwarantować, że to rozwiązanie zwróci dokładne wyniki. Innymi słowy, nie możesz wskazać konkretnego węzła tekstowego, który chcesz. Jesteś na łasce struktury HTML i układu tekstu w tym miejscu.Możesz również użyć
text()
testu węzłów XPath, aby uzyskać tylko węzły tekstowe. Na przykładźródło
To jest moje rozwiązanie w ES6, aby utworzyć ciąg zawierający połączony tekst wszystkich węzłów potomnych (rekurencyjny) . Zauważ, że jest to również wizyta w shdowroot of childnodes.
To rozwiązanie zostało zainspirowane rozwiązaniem https://stackoverflow.com/a/41051238./1300775 .
źródło