2009-04-19 16 views
15

Ich frage mich, ob es eine Möglichkeit gibt, die Wörter in einem div zum Beispiel zu zählen. Sagen wir, wir haben ein div wie so:Javascript Wortzählung für jedes gegebene DOM-Element

<div id="content"> 
hello how are you? 
</div> 

Dann wird die JS-Funktion eine ganze Zahl von 4.

dies möglich ist, zurückkehren können? Ich habe das mit Formelementen gemacht, aber ich kann es nicht für Nicht-Form-Elemente tun.

Irgendwelche Ideen?

g

Antwort

31

Wenn Sie wissen, dass das DIV ist nur gehen Text in ihm haben, können Sie KISS:

var count = document.getElementById('content').innerHTML.split(' ').length; 

Wenn die div HTML-Tags in ihm haben können, du bist gehen zu müssen, ihre Kinder zu durchqueren für Textknoten suchen:

function get_text(el) { 
    ret = ""; 
    var length = el.childNodes.length; 
    for(var i = 0; i < length; i++) { 
     var node = el.childNodes[i]; 
     if(node.nodeType != 8) { 
      ret += node.nodeType != 1 ? node.nodeValue : get_text(node); 
     } 
    } 
    return ret; 
} 
var words = get_text(document.getElementById('content')); 
var count = words.split(' ').length; 

Dies ist die gleiche Logik, die die jQuery-Bibliothek verwendet th zu erreichen Der Effekt seiner text() Funktion. jQuery ist eine ziemlich tolle Bibliothek, die in diesem Fall nicht notwendig ist. Wenn Sie jedoch feststellen, dass Sie eine Menge DOM-Manipulation oder AJAX machen, dann sollten Sie es sich ansehen.

EDIT:

Wie in den Kommentaren von Gumbo erwähnt, ist die Art, wie wir die Saiten spalten über zwei aufeinander folgende Leerzeichen als Wort zählen würde. Wenn Sie solche Dinge erwarten (und selbst wenn Sie das nicht tun), ist es wahrscheinlich am besten, sie zu vermeiden, indem Sie auf einen regulären Ausdruck anstatt auf ein einfaches Leerzeichen aufteilen. Mit diesem Hintergedanken, anstatt die oben Split tun, sollten Sie etwas tun:

var count = words.split(/\s+/).length; 

Der einzige Unterschied besteht darin, auf das, was wir vorbei an den split Funktion.

+0

Sie werden zuerst den Textknoten bekommen. – cgp

+0

perfekt! danke – givp

+0

Das wird Tags als Wörter zählen, weshalb ich die von jQuery bereitgestellte text() - Version bevorzugen würde. – cgp

2
document.deepText= function(hoo){ 
    var A= []; 
    if(hoo){ 
     hoo= hoo.firstChild; 
     while(hoo!= null){ 
      if(hoo.nodeType== 3){ 
       A[A.length]= hoo.data; 
      } 
      else A= A.concat(arguments.callee(hoo)); 
      hoo= hoo.nextSibling; 
     } 
    } 
    return A; 
} 

würde ich ziemlich streng sein, was ein Wort ist-

function countwords(hoo){ 
    var text= document.deepText(hoo).join(' '); 
    return text.match(/[A-Za-z\'\-]+/g).length; 
} 
alert(countwords(document.body)) 
6

Paolo Bergantino zweite Lösung für leere Strings oder Strings nicht korrekt ist, die mit Leerzeichen beginnen oder enden. Hier ist das Update:

var count = !s ? 0 : (s.split(/^\s+$/).length === 2 ? 0 : 2 + 
    s.split(/\s+/).length - s.split(/^\s+/).length - s.split(/\s+$/).length); 

Erläuterung: Wenn die Zeichenfolge leer ist, gibt es Null Worte; Wenn die Zeichenfolge nur Leerzeichen enthält, sind keine Wörter vorhanden. Andernfalls zählen Sie die Anzahl der Leerzeichengruppen ohne die vom Anfang und vom Ende der Zeichenfolge.

1

Oder Sie können dies tun:

function CountWords (this_field, show_word_count, show_char_count) { 
    if (show_word_count == null) { 
     show_word_count = true; 
    } 
    if (show_char_count == null) { 
     show_char_count = false; 
    } 
    var char_count = this_field.value.length; 
    var fullStr = this_field.value + " "; 
    var initial_whitespace_rExp = /^[^A-Za-z0-9]+/gi; 
    var left_trimmedStr = fullStr.replace(initial_whitespace_rExp, ""); 
    var non_alphanumerics_rExp = rExp = /[^A-Za-z0-9]+/gi; 
    var cleanedStr = left_trimmedStr.replace(non_alphanumerics_rExp, " "); 
    var splitString = cleanedStr.split(" "); 
    var word_count = splitString.length -1; 
    if (fullStr.length <2) { 
     word_count = 0; 
    } 
    if (word_count == 1) { 
     wordOrWords = " word"; 
    } else { 
     wordOrWords = " words"; 
    } 
    if (char_count == 1) { 
     charOrChars = " character"; 
    } else { 
     charOrChars = " characters"; 
    } 
    if (show_word_count & show_char_count) { 
     alert ("Word Count:\n" + " " + word_count + wordOrWords + "\n" + " " + char_count + charOrChars); 
    } else { 
     if (show_word_count) { 
      alert ("Word Count: " + word_count + wordOrWords); 
     } else { 
      if (show_char_count) { 
       alert ("Character Count: " + char_count + charOrChars); 
      } 
     } 
    } 
    return word_count; 
} 
5
string_var.match(/[^\s]+/g).length 

scheint, wie es eine bessere Methode ist als

string_var.split(/\s+/).length 

Zumindest wird es nicht "Wort" zählen als 2 Worte - [ "Wort"] anstatt ['Wort', ''].Und es erfordert wirklich keine lustige Zusatzlogik.

+0

Besser, aber es zählt immer noch die leere Zeichenfolge '' als 1. Probieren Sie: 'string_var.match (/ [^ \ s] +/g) .length - 1;' –

0

Die Funktion get_text in Paolo Bergantinos Antwort funktionierte nicht richtig für mich, wenn zwei untergeordnete Knoten keinen Abstand zwischen ihnen haben. z. B. <h1> Überschrift/h1 > <p> Absatz/p > würde als headingparagraph zurückgegeben werden (beachten Sie Platzmangel zwischen den Wörtern). Wenn Sie also ein Leerzeichen an den nodeValue anhängen, wird dies behoben. Aber es führt ein Leerzeichen an der Vorderseite des Textes ein, aber ich habe eine Wortzählfunktion gefunden, die es abschneidet (und es verwendet mehrere Regexps, um sicherzustellen, dass es nur Wörter zählt). Wortanzahl und bearbeitet get_text Funktionen unter:

function get_text(el) { 
    ret = ""; 
    var length = el.childNodes.length; 
    for(var i = 0; i < length; i++) { 
     var node = el.childNodes[i]; 
     if(node.nodeType != 8) { 
      ret += node.nodeType != 1 ? ' '+node.nodeValue : get_text(node); 
     } 
    } 
    return ret; 
} 

function wordCount(fullStr) { 
    if (fullStr.length == 0) { 
     return 0; 
    } else { 
     fullStr = fullStr.replace(/\r+/g, " "); 
     fullStr = fullStr.replace(/\n+/g, " "); 
     fullStr = fullStr.replace(/[^A-Za-z0-9 ]+/gi, ""); 
     fullStr = fullStr.replace(/^\s+/, ""); 
     fullStr = fullStr.replace(/\s+$/, ""); 
     fullStr = fullStr.replace(/\s+/gi, " "); 
     var splitString = fullStr.split(" "); 
     return splitString.length; 
    } 
} 

EDIT

kennebec Wort Zähler ist wirklich gut. Aber der, den ich gefunden habe, enthält eine Nummer als ein Wort, das ich brauche. Dennoch, das ist leicht zu Kennebec hinzuzufügen. Kennebecs Textabruffunktion wird jedoch dasselbe Problem haben.

0

string_var.match(/[^\s]+/g).length - 1;

Verwandte Themen