Introduction
Introduction Statistics Contact Development Disclaimer Help
datalist.js - jscancer - Javascript crap (relatively small)
git clone git://git.codemadness.org/jscancer
Log
Files
Refs
README
LICENSE
---
datalist.js (12086B)
---
1 function datalist_init(input) {
2 var tablemode = false;
3 var attrlist = input.getAttribute("data-table") || "";
4 if (attrlist !== "")
5 tablemode = true;
6 else
7 attrlist = input.getAttribute("list")
8 var ellist = document.getElementById(attrlist);
9 var thead = null;
10 if (tablemode) {
11 if (ellist.tHead)
12 thead = ellist.tHead;
13 }
14 input.removeAttribute("list");
15 input.autocomplete = "off";
16
17 var cursel = null, items = [], mouse = true, // enable mouse eve…
18 datalist_match,
19 dropdown = document.createElement("div"),
20 prevmatches = [],
21 prevvalue = null,
22 url = input.getAttribute("data-url") || "",
23 urlfn = input.getAttribute("data-urlfn") || "",
24 indom = false;
25 dropdown.className = "datalist-dropdown";
26
27 var ctx = {input: input, dropdown: dropdown};
28
29 var getlabel = function(el) {
30 return el.textContent || el.innerText || "";
31 };
32
33 // set new input value.
34 var setvalue = function(el, value) {
35 var oldvalue = el.value;
36 if (input.oldvalue === value)
37 return;
38 el.value = el.oldvalue = value; // set new value.
39 el.dispatchEvent(new Event("value-changed"));
40 };
41 input.oldvalue = input.defaultValue; // store previous value.
42
43 // get last selection value (can be different from input value).
44 var getselvalue = function(el) {
45 var value = el.getAttribute("data-value");
46 if (value !== null)
47 return value;
48 value = el.value;
49 if (value !== null)
50 return value;
51 return el.textContent || el.innerText || "";
52 };
53
54 // set selection value (can be different from input value).
55 var setselvalue = function(el, value) {
56 el.dispatchEvent(new Event("selection"));
57 var oldvalue = el.value;
58 setvalue(el, value);
59 if (oldvalue !== value)
60 el.dispatchEvent(new Event("selection-changed"));
61 };
62
63 var datalist_enabled = function() {
64 return !input.readOnly && !input.disabled && !input.hidd…
65 };
66
67 // create item: expects string, or object with name and label at…
68 var createitem = function(o) {
69 var label, row, value;
70 if (!tablemode)
71 row = document.createElement("div");
72 if (typeof(o) === "string") {
73 label = value = o;
74 row.textContent = label;
75 } else if (typeof(o.getAttribute) == "function") {
76 // element
77 label = getlabel(o);
78 value = getselvalue(o);
79 if (tablemode)
80 row = o.cloneNode(true);
81 else
82 row.textContent = label;
83 } else {
84 // (JSON) object
85 label = o.label;
86 value = o.value;
87 row.textContent = label;
88 }
89
90 row.setAttribute("data-value", value);
91 row.addEventListener("mousedown", function() {
92 if (!datalist_enabled())
93 return;
94 setselvalue(input, getselvalue(this));
95 datalist_show(false);
96 }, false);
97 row.addEventListener("mousemove", function() {
98 if (mouse)
99 datalist_setsel(this);
100 }, false);
101 return { el: row, label: label, value: value };
102 };
103
104 if (url.length || urlfn.length) {
105 urlfn = urlfn.length ? window[urlfn] : function(s, input…
106 return url + encodeURIComponent(s);
107 };
108
109 // "throttled" JSON XMLHttpRequest.
110 var timer = null, prevurl = "";
111 datalist_match = function(s, fn, ev) {
112 clearTimeout(timer);
113
114 if (!datalist_enabled())
115 return;
116
117 var requrl = urlfn(s, input);
118 if (requrl === prevurl) {
119 fn(prevmatches);
120 return;
121 }
122
123 timer = setTimeout(function() {
124 // set class for loading indicator styli…
125 input.classList.add("loading");
126
127 var x = new(XMLHttpRequest);
128 x.onreadystatechange = function() {
129 // remove loading indicator when…
130 if (x.readyState == 4)
131 input.classList.remove("…
132
133 if (x.readyState != 4 || [ 0, 20…
134 return;
135
136 prevmatches = [];
137 var o = JSON.parse(x.responseTex…
138 tablemode = !!o.columns && !!o.i…
139 if (tablemode) {
140 // create table header f…
141 thead = document.createE…
142 var tr = document.create…
143 var valueidx = 0; // def…
144
145 for (var i = 0; i < o.co…
146 var th = documen…
147 th.className = o…
148 th.textContent =…
149 if (o.columns[i]…
150 valueidx…
151 tr.appendChild(t…
152 }
153 thead.appendChild(tr);
154
155 // add items as table ro…
156 for (var i = 0; i < o.it…
157 var tr = documen…
158 if (Array.isArra…
159 tr.setAt…
160 for (var…
161 …
162 …
163 …
164 }
165 } else {
166 tr.setAt…
167 for (var…
168 …
169 …
170 …
171 …
172 …
173 …
174 …
175 …
176 …
177 …
178 …
179 …
180 }
181 }
182 prevmatches.push…
183 }
184 } else {
185 for (var i = 0; i < o.le…
186 prevmatches.push…
187 }
188
189 prevurl = requrl;
190 fn(prevmatches);
191 };
192
193 x.open("GET", requrl + "&t=" + String(ne…
194 x.setRequestHeader("X-Requested-With", "…
195 x.timeout = 10000;
196 x.send();
197 // delay in ms: throttle request on chan…
198 }, ev == "onchange" ? 150 : 1);
199 };
200 } else {
201 // use inline <datalist> or table.
202 if (attrlist === null || ellist === null)
203 return;
204
205 for (var i = 0, ec = (tablemode && ellist.tBodies.length…
206 var o = createitem(ec[i]);
207 o.search = o.label.toLowerCase().split(" ");
208 items.push(o);
209 }
210
211 var datalist_filter = function(data, s) {
212 var matches = [], tok = s.toLowerCase().split(" …
213 for (var i = 0; i < data.length; i++) {
214 var fc = 0;
215 for (var k = 0; k < tok.length && fc < t…
216 var f = false;
217 for (var j = 0; j < data[i].sear…
218 for (var l = 0; l < data…
219 if (data[i].sear…
220 f = true;
221 if (f)
222 fc++;
223 }
224 // all tokens (separated by space) must …
225 if (fc == tok.length)
226 matches.push(data[i]);
227 }
228 return matches;
229 };
230
231 datalist_match = function(s, fn) {
232 if (!datalist_enabled())
233 return;
234
235 s = s.toLowerCase();
236 if (s === prevvalue) {
237 fn(prevmatches);
238 return;
239 }
240
241 // if token string is different or string not in…
242 // else filter on existing data and no need to s…
243 if (prevvalue === null || (prevvalue.split(" ").…
244 s.indexOf(prevvalue) == -1)
245 prevmatches = datalist_filter(items, s);
246 else
247 prevmatches = datalist_filter(prevmatche…
248 prevvalue = s;
249 fn(prevmatches);
250 };
251 }
252
253 var datalist_render = function(m) {
254 if (!indom) { // add to DOM on first use when needed.
255 document.body.appendChild(dropdown);
256 indom = true;
257 }
258
259 var dd = dropdown.cloneNode(false), table, tbody;
260 if (tablemode) {
261 table = document.createElement("table");
262 if (thead)
263 table.tHead = thead.cloneNode(true);
264 tbody = document.createElement("tbody");
265 }
266
267 var r = input.getClientRects() || [];
268 if (r.length) {
269 dd.style.left = String(r[0].left + window.pageXO…
270 dd.style.top = String(r[0].top + input.offsetHei…
271 }
272 dd.style.minWidth = String(input.getAttribute("data-minw…
273 if (tablemode) {
274 for (var i = 0; i < m.length; i++)
275 tbody.appendChild(m[i].el);
276 table.appendChild(tbody);
277 dd.appendChild(table);
278 } else {
279 for (var i = 0; i < m.length; i++)
280 dd.appendChild(m[i].el);
281 }
282 dropdown.parentNode.replaceChild(dd, dropdown)
283 dropdown = dd;
284 };
285
286 var datalist_visible = false;
287 var datalist_show = function(status) {
288 if (status && !datalist_enabled()) // do not show when d…
289 return;
290 datalist_visible = status;
291 dropdown.className = "datalist-dropdown " + (status ? "v…
292 var r = dropdown.getClientRects();
293 // if dropdown popup doesn't fit then adjust x, y scroll…
294 if (!r.length)
295 return;
296 if (r[0].left + r[0].width >= window.innerWidth) {
297 dropdown.style.left = "auto";
298 dropdown.style.right = "0px";
299 }
300 var ri = input.getClientRects() || [];
301 if (input.scrollIntoView && ri.length && r[0].top + drop…
302 input.scrollIntoView();
303 };
304 var datalist_setsel = function(el) {
305 if (cursel)
306 cursel.className = "";
307 cursel = el;
308 if (el)
309 el.className = "sel";
310 };
311
312 input.addEventListener("keydown", function(e) {
313 mouse = false;
314 switch (e.which) {
315 case 13: // return
316 if (cursel)
317 setselvalue(input, getselvalue(cursel));
318 datalist_show(false);
319 e.stopPropagation();
320 return !!e.preventDefault();
321 case 27: break; // escape
322 case 33: // page up.
323 case 34: // page down.
324 case 38: // arrow up
325 case 40: // arrow down
326 var sel = cursel, dd = dropdown, dc = tablemode …
327
328 // if last and down arrow switch to first item, …
329 if (dc.length) {
330 if (e.which == 38) { // up
331 if (!sel || !(sel = sel.previous…
332 sel = dc[dc.length - 1];
333 } else if (e.which == 40) { // down
334 if (!sel || !(sel = sel.nextSibl…
335 sel = dc[0];
336 } else if (!sel) {
337 sel = dc[0];
338 }
339 }
340 if (cursel && (e.which == 33 || e.which == 34)) {
341 var n = sel.offsetHeight ? (dd.clientHei…
342 if (e.which == 33) { // page up.
343 for (; n > 0 && sel && sel.previ…
344 n--, sel = sel.previousS…
345 ;
346 } else { // page down.
347 for (; n > 0 && sel && sel.nextS…
348 n--, sel = sel.nextSibli…
349 ;
350 }
351 }
352 if (sel) {
353 datalist_setsel(sel);
354
355 // only update scroll if needed.
356 if (sel.offsetTop < dd.scrollTop)
357 dd.scrollTop = sel.offsetTop;
358 else if (sel.offsetTop + sel.offsetHeigh…
359 dd.scrollTop = sel.offsetTop;
360 }
361 }
362 }, false);
363
364 var onchange = function() {
365 setvalue(input, input.value);
366 datalist_match(input.value, function(m) {
367 // check if selection is still active in matches.
368 if (cursel) {
369 var hassel = false;
370 for (var i = 0; i < m.length && !(hassel…
371 ;
372 if (!hassel)
373 datalist_setsel(null);
374 }
375 // only one match? select it.
376 if (m.length == 1)
377 datalist_setsel(m[0].el);
378 datalist_render(m);
379 datalist_show(!!m.length);
380 }, "onchange");
381 };
382
383 input.addEventListener("input", onchange);
384 input.addEventListener("keyup", function(e) {
385 mouse = true;
386 switch (e.which) {
387 case 13: // return
388 case 27: // escape
389 datalist_show(false);
390 case 33: // page up.
391 case 34: // page down.
392 case 38: // arrow up
393 case 40: // arrow down
394 return;
395 }
396 onchange();
397 }, false);
398 input.addEventListener("focus", function() {
399 datalist_setsel(null);
400 datalist_match(input.value, function(m) {
401 datalist_render(m);
402 datalist_show(!!m.length);
403 dropdown.scrollTop = 0; // reset scroll.
404 });
405 }, false);
406 input.addEventListener("blur", function() {
407 mouse = true;
408 datalist_setsel(null);
409 datalist_show(false);
410 }, false);
411
412 return ctx;
413 }
414
415 var els = document.getElementsByClassName("datalist");
416 if (els !== null)
417 for (var i = 0; i < els.length; i++)
418 datalist_init(els[i]);
You are viewing proxied material from codemadness.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.