1/** 2 * smart_text â debounced "search as you type" trigger. 3 * 4 * History (EF-11): this used to wrap YAHOO.widget.AutoComplete purely to reuse 5 * its keyup debounce â the autocomplete dropdown itself was never displayed. 6 * Rewritten as plain vanilla JS (no YUI dependency), keeping the public API: 7 * 8 * new smart_text(textid, plink, qcallback, minlength, tagid) 9 * textid : id of the watched <input> 10 * plink : id of a postlink tag to doPost() after the delay (or null) 11 * qcallback : optional function called instead of the default length gate 12 * (the full-search FiltersView passes one that submits the form) 13 * minlength : minimum length before a query fires (an empty field is always 14 * allowed, so clearing the input still triggers a refresh) 15 * tagid : unique id of this instance 16 * 17 * .setQueryDelay(seconds) / .destroy() 18 * 19 * Behaviour changes vs the YUI version (intentional, EF-11): 20 * - Single debounce of queryDelay. The YUI version debounced twice (once in 21 * _onTextboxKeyUp, once in the overridden _sendQuery) for ~2x the delay; 22 * that was an artefact. The query now fires once, `delay` after the last 23 * keystroke. 24 * - minlength is now honoured in the qcallback path too (it was dead there 25 * under YUI, where the callback ran on every keystroke). The full-search 26 * box therefore now waits for `minlength` characters before submitting. 27 * - Listens to the `input` event instead of `keyup`, so navigation keys 28 * (arrows, modifiers) no longer trigger a spurious query. 29 */ 30var smart_text = function (textid, plink, qcallback, minlength, tagid) { 31 var self = this; 32 33 this.id = tagid; 34 this.minlength = minlength; 35 this.queryDelay = 0.2; // seconds (YUI default preserved; override via setQueryDelay) 36 // getCustomTag() returns undefined for a tag that is not registered, which 37 // the `!== null` guards below would let through â normalize to null here. 38 this.plink = (plink !== null) ? (getCustomTag(plink) || null) : null; 39 this.qcallback = qcallback || null; 40 this.input = document.getElementById(textid); 41 this.timeout = null; 42 43 this.onInput = function () { 44 if (self.timeout) { 45 clearTimeout(self.timeout); 46 self.timeout = null; 47 } 48 self.timeout = setTimeout(function () { 49 self.sendQuery(); 50 }, self.queryDelay * 1000); 51 }; 52 53 this.sendQuery = function () { 54 self.timeout = null; 55 56 if (self.plink !== null) { 57 self.plink.cancelRequest(); 58 } 59 60 var value = self.input ? self.input.value : ''; 61 62 // minlength gate â an empty field is always allowed (clears the search). 63 if (value.length !== 0 && value.length < self.minlength) { 64 return; 65 } 66 67 var result = (self.qcallback !== null) ? self.qcallback() : true; 68 69 if (result && self.plink !== null) { 70 self.plink.doPost(); 71 } 72 }; 73 74 this.setQueryDelay = function (delay) { 75 self.queryDelay = delay; 76 }; 77 78 this.destroy = function () { 79 if (self.timeout) { 80 clearTimeout(self.timeout); 81 self.timeout = null; 82 } 83 if (self.input) { 84 self.input.removeEventListener('input', self.onInput); 85 } 86 }; 87 88 if (this.input) { 89 this.input.addEventListener('input', this.onInput); 90 } 91}; 92 93// Public surface: resolved by name from server-side templates and other legacy scripts. 94window.smart_text = smart_text; // e.g. layouts/views/scripts/twig/list-fullsearch.html.twig
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.