Javascript число слов для любого данного элемента DOM

Мне интересно, есть ли способ подсчитать слова внутри div, например. Скажем, у нас есть div как:

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

Затем функция JS возвращает целое число из 4.

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

Любые идеи?

г

Ответы

Ответ 1

Если вы знаете, что в 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 использует для достижения эффекта text(). jQuery - довольно удивительная библиотека, которая в этом случае не нужна. Однако, если вы обнаружите, что выполняете много манипуляций с DOM или AJAX, вы можете проверить его.

ИЗМЕНИТЬ

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

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

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

Ответ 2

Второе решение Паоло Бергантино неверно для пустых строк или строк, которые начинаются или заканчиваются пробелами. Здесь исправление:

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

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

Ответ 3

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

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

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

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

Ответ 4

Или просто используйте Countable.js, чтобы выполнить тяжелую работу;)

Ответ 5

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

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

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;
}

Ответ 7

Функция 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;
    }
}

ИЗМЕНИТЬ

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

Ответ 8

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