2009-04-19 6 views
15

Je me demande s'il existe un moyen de compter les mots à l'intérieur d'une div par exemple. Disons que nous avons un div comme ceci:Compte de mots Javascript pour n'importe quel élément DOM donné

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

Puis ont la fonction JS retourner un nombre entier de 4.

Est-ce possible? J'ai fait ceci avec des éléments de forme mais ne peux pas sembler le faire pour les non-forme.

Des idées?

g

Répondre

31

Si vous savez que la DIV est que va avoir du texte dans, vous pouvez KISS:

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

Si la div peut avoir des balises HTML dans, vous êtes va devoir traverser ses enfants à la recherche de nœuds de texte:

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; 

Ceci est la même logique que la bibliothèque jQuery utilise pour atteindre e Effet de sa fonction text(). jQuery est une bibliothèque assez géniale qui, dans ce cas, n'est pas nécessaire. Cependant, si vous vous trouvez à faire beaucoup de manipulation DOM ou AJAX, alors vous voudrez peut-être vérifier.

EDIT:

Comme l'a souligné Gumbo dans les commentaires, la façon dont nous répartissons les chaînes ci-dessus serait compter deux espaces consécutifs comme un mot. Si vous vous attendez à ce genre de chose (et même si vous ne le faites pas), il est probablement préférable de l'éviter en divisant une expression régulière plutôt que par un simple espace. En gardant cela à l'esprit, au lieu de faire la scission ci-dessus, vous devriez faire quelque chose comme ceci:

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

La seule différence sur ce que nous transmettons à la fonction split.

+0

Vous devez obtenir le noeud texte en premier. – cgp

+0

parfait! merci – givp

+0

Cela comptera des étiquettes comme mots cependant, c'est pourquoi je préférerais la version de text() fournie par jQuery. – 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; 
} 

Je serais assez stricte sur ce mot est-

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

deuxième solution de Paolo Bergantino est incorrect pour les chaînes ou des chaînes vides qui commencent ou se terminent par des espaces. Voici la solution:

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

Explication: Si la chaîne est vide, il y a zéro des mots; Si la chaîne n'a que des espaces, il y a zéro mot; Sinon, comptez le nombre de groupes d'espaces sans ceux du début et de la fin de la chaîne.

1

Ou vous pouvez faire ceci:

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 

semble que c'est une meilleure méthode que

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

Au moins il comptera pas "mot", comme 2 mots - [ 'mot'] plutôt que ['mot', ''].Et cela ne nécessite pas vraiment de logique addictive.

+0

Mieux, mais il compte la chaîne vide '' as 1. Essayez: 'string_var.match (/ [^ \ s] +/g) .length - 1;' –

0

La fonction get_text de la réponse de Paolo Bergantino ne fonctionnait pas correctement lorsque deux nœuds enfants ne disposaient pas d'espace entre eux. par exemple, <h1> h/h1 > < p Le paragraphe </p> sera retourné comme sous-paragraphe (remarquez le manque d'espace entre les mots). Donc, l'ajout d'un espace à nodeValue corrige cela. Mais il introduit un espace au début du texte mais j'ai trouvé une fonction de comptage de mots qui le coupe (plus il utilise plusieurs expressions rationnelles pour s'assurer qu'il ne compte que les mots). Nombre de mots et sous la direction des fonctions de get_text ci-dessous:

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

mot de Kennebec comptoir est vraiment bon. Mais celui que j'ai trouvé inclut un nombre comme un mot dont j'ai besoin. Pourtant, c'est facile à ajouter à kennebec. Mais la fonction de récupération de texte de kennebec aura le même problème.

0

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

Questions connexes