function autoSuggestService() { var exports = {}; var levenshtein = window.Levenshtein; function getDistance(str1, str2) { //levenshtein.get('mikailovitch', 'Mikhaïlovitch', { useCollator: true}); return levenshtein.get(str1, str2, { useCollator: true }); } function escapeRegExp(string) { return string.replace(/[.*+?^${}()|[\]\\]/g, '\\&'); // & means the whole matched string } var getWordsRegEx = new RegExp('\\b([^.,? ]+?)\\b', 'gm'); var getWordsRegEx = new RegExp('([^\\s.,;:]+)', 'gm'); function getWords(str) { var matches = []; var match; while (match = getWordsRegEx.exec(str)) { if (match[1].length > 0) { matches.push(match[1]); } } return matches; } function replaceWord(str, find, replace) { return str.replace(new RegExp('\\b' + escapeRegExp(find) + '\\b', 'gmi'), replace); } function multiFor(a, b, fn) { for (var i = 0; i < a.length; i++) { for (var j = 0; j < b.length; j++) { var res = fn(a[i], b[j]); if (res === false) { break; } } } } function arrayCountMatch(a, b) { var matchCount = 0; multiFor(a, b, function (c, d) { if (c === d) { matchCount++; } }); return matchCount; } function getUniqueWords(suggestions) { var wordMap = {}; suggestions.forEach(function (s) { var words = getWords((s.text || '')); words.forEach(function (w) { wordMap[w] = true; }); }); return Object.keys(wordMap); } function findWordSuggestions(text, uniqueWords) { if (!text || text === '' || text === ' ') { return []; } var words = getWords(text); var results = []; multiFor(words, uniqueWords, function (word, uniqueWord) { var lowerWord = word.toLowerCase(); var lowerUniqueWord = uniqueWord.toLowerCase(); if (lowerUniqueWord === lowerWord) { return; // exact word no suggestions } if (lowerUniqueWord.charAt(0) !== lowerWord.charAt(0)) { return; } var dist = getDistance(lowerWord, lowerUniqueWord.slice(0, lowerWord.length)); var score = (lowerWord.length / (dist + 1 * lowerWord.length)); if (score >= 0.7) { results.push({ src: word, target: uniqueWord, score: score }); } }); results.sort(function (a, b) { return b.score - a.score; }); return results; } function findSuggestions(text, suggestions) { var results = []; if (typeof text === 'string' && text.length > 3) { text = text.toLowerCase(); var words = getWords(text); if (words.length < 1) { return results; } suggestions.forEach(function (s) { var str = (s.text || '').toLowerCase(); if (str.indexOf(text) >= 0) { s.score = 1; results.push(s); return; } var sugWords = getWords(str); var matchCount = arrayCountMatch(words, sugWords); if (matchCount > 0) { s.score = matchCount / Math.min(words.length, sugWords.length); if (s.score > 0.2) { results.push(s); } } }); } results.sort(function (a, b) { return b.score - a.score; }); return results; } exports = { findSuggestions: findSuggestions, findWordSuggestions: findWordSuggestions, getUniqueWords: getUniqueWords, replaceWord: replaceWord }; return exports; } function loadSuggestions() { var suggestions = [{ text: '', value: '' }]; return suggestions; } var _suggestions = null; function getSuggestions() { if (!_suggestions) { _suggestions = loadSuggestions(); } return _suggestions; } function getSuggestionsForText(text) { return getSuggestions() .then(function (suggestions) { return autoSuggestService.findSuggestions(text, suggestions); }); } function getWordSuggestionsForText(text) { return getSuggestions() .then(function (suggestions) { var uniqueWords = autoSuggestService.getUniqueWords(suggestions); return autoSuggestService.findWordSuggestions(text, uniqueWords); }); }
131300cookie-checkJavascript autosuggest service (levenshtein + word matching)