2009-04-19 2 views
15

Мне интересно, есть ли способ подсчитать слова внутри div, например. Скажем, у нас есть DIV как так:Javascript word-count для любого заданного элемента DOM

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

Тогда имеет функцию JS возвращают целое число от 4

Возможно ли это? Я сделал это с элементами формы, но не могу сделать это для неформальных.

Любые идеи?

г

ответ

31

Если вы знаете, что DIV является только будет иметь текст в нем, вы можете KISS:

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

Если DIV может иметь HTML-теги в нем, вы придется пройти через своих детей ищет текстовых узлов:

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; 

Это та же самая логика, которая использует для достижения ю библиотеку Jquery e его функции text(). jQuery - довольно удивительная библиотека, которая в этом случае не нужна. Однако, если вы обнаружите, что выполняете много манипуляций с DOM или AJAX, вы можете проверить его.

EDIT:

Как отметил Gumbo в комментариях, как мы расщепление строки выше будет засчитываться два последовательных пространства как слово. Если вы ожидаете такого рода вещи (и даже если вы этого не сделаете), то, вероятно, лучше избегать этого, разделив на регулярное выражение вместо простого символа пробела. Имея это в виду, вместо того, чтобы делать выше раскол, вы должны сделать что-то вроде этого:

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

Единственное различие состоит в том, что мы мы передаем функции split.

+0

Вы должны получить текстовый узел первым. – cgp

+0

безупречный! спасибо – givp

+0

Это будет считать теги как слова, хотя, поэтому я бы предпочел версию text(), предоставленную 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; 
} 

Я был бы довольно строг о том, что слово это- второго решение

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

Paolo Bergantino некорректно для пустых строк или строк, которые начинаются или заканчиваются пробелами. Вот исправление:

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

Объяснение: Если строка пуста, есть нулевые слова; Если строка имеет только пробелы, то есть нулевые слова; Else, подсчитайте количество пробельных групп без них с начала и конца строки.

1

Или вы можете сделать это:

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 

кажется, что это лучший способ, чем

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

По крайней мере, это не будет считаться "слово", как 2-х словах - [ 'word'], а не ['word', ''].И на самом деле это не требует смешной аддитивной логики.

+0

Лучше, но это stil считает пустую строку '' как 1. Попробуйте: 'string_var.match (/ [^ \ s] +/g) .length - 1;' –

0

Функция get_text в ответе Паоло Бергантино не работает должным образом для меня, когда у двух дочерних узлов нет места между ними. например <h1> товарная позиция </h1 > <p> пункт </p > будет возвращен как заголовок пункта (обратите внимание на отсутствие пробела между словами). Таким образом, добавление пробела в nodeValue исправляет это. Но он вводит пробел в начале текста, но я нашел функцию подсчета слов, которая отключает ее (плюс она использует несколько регулярных выражений, чтобы гарантировать, что она учитывает только слова). Количество слов и отредактированные функции get_text ниже:

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 Слово счетчик действительно хорошо. Но тот, который я нашел, включает число как слово, которое мне нужно. Тем не менее, это легко добавить к kennebec's. Но функция поиска текста kennebec будет иметь одинаковую проблему.

0

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

Смежные вопросы