Introduction
Introduction Statistics Contact Development Disclaimer Help
add XMLHttprequest support for querying remote results - jscancer - Javascript …
git clone git://git.codemadness.org/jscancer
Log
Files
Refs
README
LICENSE
---
commit 3c60e3f53de3ffe7c696d316ae627a30cdaa384e
parent 2e6c151065631ab71a1766c2ec8fc1c61600e5b1
Author: Hiltjo Posthuma <[email protected]>
Date: Thu, 29 Jun 2017 18:56:54 +0200
add XMLHttprequest support for querying remote results
Refactor some code to be asynchronous, because the async XHR code requires it.
This adds 50 lines of code, but it's structured in a way so it can be easily
removed: ~185 lines to ~235 LOC.
Diffstat:
M datalist/README | 11 ++++++-----
M datalist/datalist.js | 164 ++++++++++++++++++++---------…
A datalist/example-data.json | 13 +++++++++++++
M datalist/example.html | 7 +++++++
4 files changed, 131 insertions(+), 64 deletions(-)
---
diff --git a/datalist/README b/datalist/README
@@ -1,18 +1,19 @@
-autocomplete
-============
+datalist
+========
-small dropdown / autocomplete script.
+small dropdown filter / autocomplete script.
FEATURES
--------
- Small:
- - Filesize: +- 5.2KB.
- - Lines: +- 185, not much code, so hopefully easy to understand.
+ - Filesize: +- 6.7KB.
+ - Lines: +- 235, not much code, so hopefully easy to understand.
- No dependencies on other libraries like jQuery.
- (Graceful) fallback to HTML5 datalist if Javascript is disabled.
- Filtering values: case-insensitively, tokenized (separated by space).
+- Supports querying a remote server for results using a JSON XMLHttpRequest.
- Permissive ISC license, see LICENSE file, feel free to contact me for
questions or other terms.
- Officially supported browsers are:
diff --git a/datalist/datalist.js b/datalist/datalist.js
@@ -1,16 +1,20 @@
function datalist_init(input) {
var attrlist = input.getAttribute("list"), ellist = document.getElemen…
- if (attrlist === null || ellist === undefined)
- return;
+
input.removeAttribute("list");
input.autocomplete = "off";
+
var cursel = null, items = [], mouse = true, // enable mouse event han…
- dropdown = document.createElement("div");
+ datalist_match,
+ dropdown = document.createElement("div"),
+ prevmatches = [],
+ prevvalue = null,
+ url = input.getAttribute("data-url") || "";
dropdown.className = "datalist-dropdown";
- for (var i = 0, ec = ellist.children; i < ec.length; i++) {
+ var createitem = function(s) {
var div = document.createElement("div");
- div.innerHTML = ec[i].innerHTML;
+ div.innerHTML = s;
div.addEventListener("mousedown", function() {
input.value = this.textContent || this.innerText;
datalist_show(false);
@@ -19,44 +23,84 @@ function datalist_init(input) {
if (mouse)
datalist_setsel(this);
}, false);
- items.push({ el: div, search: ((div.textContent || div.innerTe…
- }
+ return { el: div, search: ((div.textContent || div.innerText).…
+ };
+
+ if (url.length) {
+ // "throttled" JSON XMLHttpRequest.
+ var timer = null;
+ datalist_match = function(s, fn) {
+ clearTimeout(timer);
+ timer = setTimeout(function() {
+ s = s.toLowerCase();
+ if (s === prevvalue) {
+ fn(prevmatches);
+ return;
+ }
+ var x = new(XMLHttpRequest);
+ x.onreadystatechange = function() {
+ if (x.readyState != 4 || [ 0, 200 ].in…
+ return;
+
+ prevmatches = [];
+ var o = JSON.parse(x.responseText);
+ for (var i = 0; i < o.length; i++)
+ prevmatches.push(createitem(o[…
+
+ prevvalue = s;
+ fn(prevmatches);
+ };
+ x.open("GET", url + encodeURIComponent(s) + "&…
+ x.setRequestHeader("X-Requested-With", "XMLHtt…
+ x.timeout = 10000;
+ x.send();
+ }, 150); // delay in ms.
+ };
+ } else {
+ // use inline <datalist>.
+ if (attrlist === null || ellist === undefined)
+ return;
+ for (var i = 0, ec = ellist.children; i < ec.length; i++)
+ items.push(createitem(ec[i].innerHTML));
+
+ var datalist_filter = function(data, s) {
+ var matches = [], tok = s.toLowerCase().split(" ");
+ for (var i = 0; i < data.length; i++) {
+ var fc = 0;
+ for (var k = 0; k < tok.length && fc < tok.len…
+ var f = false;
+ for (var j = 0; j < data[i].search.len…
+ for (var l = 0; l < data[i].se…
+ if (data[i].search[l].…
+ f = true;
+ if (f)
+ fc++;
+ }
+ // all tokens (separated by space) must match.
+ if (fc == tok.length)
+ matches.push(data[i]);
+ }
+ return matches;
+ };
- var datalist_filter = function(data, s) {
- var matches = [], tok = s.toLowerCase().split(" ");
- for (var i = 0; i < data.length; i++) {
- var fc = 0;
- for (var k = 0; k < tok.length && fc < tok.length; k++…
- var f = false;
- for (var j = 0; j < data[i].search.length && f…
- for (var l = 0; l < data[i].search.len…
- if (data[i].search[l].indexOf(…
- f = true;
- if (f)
- fc++;
+ datalist_match = function(s, fn) {
+ s = s.toLowerCase();
+ if (s === prevvalue) {
+ fn(prevmatches);
+ return;
}
- // all tokens (separated by space) must match.
- if (fc == tok.length)
- matches.push(data[i]);
- }
- return matches;
- };
- var prevmatches = [];
- var prevvalue = null;
- var datalist_match = function(s) {
- s = s.toLowerCase();
- if (s === prevvalue)
- return prevmatches;
- // if token string is different or string not in previous sear…
- // else filter on existing data and no need to sort.
- if (prevvalue === null || (prevvalue.split(" ").length != s.sp…
- s.indexOf(prevvalue) == -1)
- prevmatches = datalist_filter(items, s);
- else
- prevmatches = datalist_filter(prevmatches, s);
- prevvalue = s;
- return prevmatches;
- };
+ // if token string is different or string not in previ…
+ // else filter on existing data and no need to sort.
+ if (prevvalue === null || (prevvalue.split(" ").length…
+ s.indexOf(prevvalue) == -1)
+ prevmatches = datalist_filter(items, s);
+ else
+ prevmatches = datalist_filter(prevmatches, s);
+ prevvalue = s;
+ fn(prevmatches);
+ };
+ }
+
var datalist_render = function(m) {
var dd = dropdown.cloneNode(false);
var r = input.getClientRects() || [];
@@ -137,20 +181,21 @@ function datalist_init(input) {
}, false);
var onchange = function() {
- var m = datalist_match(input.value);
- // check if selection is still active in matches.
- if (cursel) {
- var hassel = false;
- for (var i = 0; i < m.length && !(hassel = (m[i].el ==…
- ;
- if (!hassel)
- datalist_setsel(null);
- }
- // only one match? select it.
- if (m.length == 1)
- datalist_setsel(m[0].el);
- datalist_render(m);
- datalist_show(!!m.length);
+ datalist_match(input.value, function(m) {
+ // check if selection is still active in matches.
+ if (cursel) {
+ var hassel = false;
+ for (var i = 0; i < m.length && !(hassel = (m[…
+ ;
+ if (!hassel)
+ datalist_setsel(null);
+ }
+ // only one match? select it.
+ if (m.length == 1)
+ datalist_setsel(m[0].el);
+ datalist_render(m);
+ datalist_show(!!m.length);
+ });
};
input.addEventListener("input", onchange);
input.addEventListener("keyup", function(e) {
@@ -169,10 +214,11 @@ function datalist_init(input) {
}, false);
input.addEventListener("focus", function() {
datalist_setsel(null);
- var m = datalist_match(input.value);
- datalist_render(m);
- datalist_show(!!m.length);
- dropdown.scrollTop = 0; // reset scroll.
+ datalist_match(input.value, function(m) {
+ datalist_render(m);
+ datalist_show(!!m.length);
+ dropdown.scrollTop = 0; // reset scroll.
+ });
}, false);
input.addEventListener("blur", function() {
mouse = true;
diff --git a/datalist/example-data.json b/datalist/example-data.json
@@ -0,0 +1,12 @@
+[
+"DragonflyBSD",
+"GNU/Hurd",
+"GNU/Linux",
+"FreeBSD",
+"MS-DOS 6.11",
+"OpenBSD",
+"OpenSolaris",
+"NetBSD",
+"Plan9",
+"Windows"
+]
+\ No newline at end of file
diff --git a/datalist/example.html b/datalist/example.html
@@ -9,6 +9,8 @@
<form method="post" action="">
+<p>Inline &lt;datalist&gt;</p>
+
<label for="os">OS: </label>
<input type="text" placeholder="Select OS..." value="" list="list" name="os" i…
@@ -25,6 +27,11 @@
<option>Windows</option>
</datalist>
+<p>Using XMLHttpRequest + JSON:</p>
+
+<label for="remote">OS: </label>
+<input type="text" placeholder="Select OS..." value="" data-url="example-data.…
+
</form>
<script type="text/javascript" src="datalist.js"></script>
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.