Основным препятствием на пути к достижению того, что вы хотите, является то, как сказать вашей программе, что такое «слово» на самом деле.
Один из способов - это получить полный словарь всех английских слов.
const setOfAllEnglishWords = new Set([
"Hello",
"a",
"text",
"for",
"the",
"example"
// ... many many more
]);
const selection = "lo, a text for the example!";
const result = selection
.replace(/[^A-Za-z0-9\s]/g, "") // remove punctuation by replacing anything that is not a letter or a digit with the empty string
.split(/\s+/) // split text into words by using 1 or more whitespace as the break point
.filter(word => setOfAllEnglishWords.has(word));
console.log(result);
Для этого может потребоваться большой объем памяти.Оксфордский словарь английского языка, основанный на быстром поиске в Google, содержит приблизительно 218632
слов.Средняя длина слова составляет 4.5
букв и JS хранит 2
байтов на символ, что дает нам 218632 * (4.5 * 2) = 1967688 B = 1.967 MB
, что может занять до 1 минуты для загрузки при медленном соединении 3G.
Лучшим подходом может бытьпросто создавать словарь слов каждый раз, когда страница загружается, собирая все уникальные слова на странице.
function getSetOfWordsOnPage() {
const walk = document.createTreeWalker(
document.body,
NodeFilter.SHOW_TEXT
);
const dict = new Set();
let n;
while ((n = walk.nextNode())) {
for (const word of n.textContent
.replace(/[^A-Za-z0-9\s]/g, "")
.split(/\s+/)
.map(word => word.trim())
.filter(word => !!word)) {
dict.add(word);
}
}
return dict;
}
const setOfWordsOnThePage = getSetOfWordsOnPage();
function getSelectionText() {
if (window.getSelection) {
return window.getSelection().toString();
} else if (document.selection && document.selection.type !== "Control") {
return document.selection.createRange().text;
}
return "";
}
// Just adding the function as listeners.
document.querySelector("#button").addEventListener("click", () => {
const result = getSelectionText()
.replace(/[^A-Za-z0-9\s]/g, "") // remove punctuation
.split(/\s+/) // split text into words
.filter(word => setOfWordsOnThePage.has(word));
console.log(result);
});
<button id="button">Show result</button>
<p>this is some text</p>
<p>again this is a text!!!!!</p>
<p>another,example,of,a,sentence</p>
Может быть, мы можем пойти еще дальше.Нужно ли помнить слова?Кажется, что определения «слово - это текст, окруженный пробелами» достаточно.
Кроме того, как упомянуто в комментарии ниже от OP, у нас также есть ошибка вышеупомянутого решения, сопоставляющая частично выбранные слова, если выбранный раздел также является допустимым словом.
Чтобы уменьшитьненужные накладные расходы на запоминание слов на странице, а также на устранение ошибки частичного выбора действительного слова, мы можем проверить содержимое левого (якорного) и самого правого (фокусного) узлов выбранной областисразу после выделения и просто игнорируйте их, если они содержат дополнительный невыбранный текст.
Здесь мы предполагаем, что для любого произвольного выделения текста у нас может быть не более 2 частично выбранных слов, по одному вкаждый конец выбора.
Примечание: подход ниже также обрабатывает заглавные буквы, предполагая, что THIS
, tHiS
и this
- это одно и то же слово.
function removePunctuation(string) {
return string.replace(/[^A-Za-z0-9\s]/g, " ");
}
function splitIntoWords(string) {
return removePunctuation(string)
.split(/\s+/)
.map(word => word.toLowerCase().trim())
.filter(word => !!word);
}
function getSelectedWords() {
const selection = window.getSelection();
const words = splitIntoWords(selection.toString());
if (selection.anchorNode) {
const startingsWords = splitIntoWords(selection.anchorNode.textContent);
if (words[0] !== startingsWords[0]) {
words.shift(); // remove the start since it's not a whole word
}
}
if (selection.focusNode) {
const endingWords = splitIntoWords(selection.focusNode.textContent);
if (words[words.length - 1] !== endingWords[endingWords.length - 1]) {
words.pop(); // remove the end since it's not a whole word
}
}
return words;
}
// Just adding the function as listeners.
document.querySelector("#button").addEventListener("click", () => {
console.log(getSelectedWords());
});
<button id="button">Show result</button>
<p><div>this is</div> <div>some text</div></p>
<p><span>again</span><span> </span><span>this</span><span> </span><span>is</span><span> </span><span>a</span> <span>text</span><span>!!!!!</span></p>
<p>another,example,of,a,sentence</p>
Примечание: этот код будет по-прежнему разбиваться, если ваши слова разбиты на несколько html-элементов, таких как <span>w</span><span>o</span><span>r</span><span>d</span>
.Этот сценарий нарушает наше определение слова, и для его решения вам нужно будет также включить некоторый словарь, чтобы проверить правильность слова, по существу объединяя последние 2 решения выше.