-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathwords.js
140 lines (111 loc) · 3.25 KB
/
words.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
var TRIE_URL = 'trie.json';
var HOVER_TIMEOUT = 250;
var MAX_WORDS = 10;
var LETTERS_EL = document.getElementById('letters');
var WORDS_MATCHING_EL = document.getElementById('words_matching');
var trieView;
TrieView = function(el, trie){
var words = [];
var stack = [];
var deepestNode;
var depth = 0;
var totalWidth = el.offsetWidth;
var hoverTimeout = null;
function getAvailableLetters(trie){
var container = document.createElement("div");
var keys = Object.keys(trie).filter(function(key) { return key != "\n" }).sort();
// TODO: Can weight by occurrence.
var letterWidth = Math.floor(totalWidth / keys.length) + 'px';
keys.forEach(function(key){
var letter = document.createElement("span");
letter.className = 'leaf';
letter.style.width = letterWidth;
letter.innerText = key;
// Mouse over
letter.addEventListener("mouseover", function(e){
if (hoverTimeout) {
clearTimeout(hoverTimeout);
}
hoverTimeout = setTimeout(function(){
var elem = e.target;
var activeSibling = elem.parentNode.querySelector('.active');
if (activeSibling) {
activeSibling.classList.remove('active');
}
elem.classList.add('active');
var letter = elem.innerText;
depth = getSiblingDOMIndex(elem.parentNode);
while (stack.length > depth){
stack.pop();
el.removeChild(el.children[el.children.length - 1]);
}
stack.push(letter);
var numChilden = trie[letter][0];
deepestNode = trie[letter][1];
var words = dumpTrie(stack.join(''), deepestNode, MAX_WORDS);
showMatchingWords(words);
appendTrieLevel(deepestNode);
}, HOVER_TIMEOUT);
});
container.appendChild(letter);
});
return container;
}
function appendTrieLevel(trie){
el.appendChild(getAvailableLetters(trie));
}
appendTrieLevel(trie);
}
function showMatchingWords(words) {
WORDS_MATCHING_EL.innerHTML = '';
words.forEach(function(word){
var el = document.createElement('div');
el.innerText = word;
WORDS_MATCHING_EL.appendChild(el);
});
}
function dumpTrie(prefix, trie, maxResults) {
var words = [];
dumpTrieRecursive(prefix, trie, maxResults, words);
return words
}
function dumpTrieRecursive(prefix, trie, maxResults, words) {
var keys = Object.keys(trie).sort();
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (key == "\n") {
words.push(prefix);
if (words.length == maxResults) {
return false;
}
} else {
if (!dumpTrieRecursive(prefix + key, trie[key][1], maxResults, words)) {
return false;
}
}
}
return true;
}
function getSiblingDOMIndex(elem){
var i = 0;
while ((elem = elem.previousSibling) != null ){
i++;
}
return i;
}
function init() {
loadJSON(TRIE_URL, function(trie){
trieView = new TrieView(LETTERS_EL, trie);
});
}
function loadJSON(url, callback){
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true );
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200 ) {
callback(JSON.parse(xhr.responseText));
}
};
xhr.send(null);
}
init();