summaryrefslogtreecommitdiff
path: root/pieces/search.js
diff options
context:
space:
mode:
Diffstat (limited to 'pieces/search.js')
-rw-r--r--pieces/search.js791
1 files changed, 224 insertions, 567 deletions
diff --git a/pieces/search.js b/pieces/search.js
index 52ce4e3..0c05708 100644
--- a/pieces/search.js
+++ b/pieces/search.js
@@ -1,646 +1,303 @@
+const kb = require('./kb-util.js');
+const match = require('./match-util.js');
+const products = require('../data/products.json');
-/** Search Engine
- * ---------------------------------------------------------------------------
- *
- * TODO:
- * CRITICAL: (optimization)
- * Search initialization uses quite a lot of network sources;
- * thus it should be started in a later time;
- * lets say ... after `x` seconds
- * or... when document/core-ui-elements are ready
- *
- * @parametres (json) : options
- * ---
- * @var {string} products_json : endpoint od product descriptions
- * @var {string} search_tag : selector of field that shall act as typeahead-suggestions
- * @var {string} visualize_search_results_url : url that will visualize the sended "results-page"
- * @var {int} max_list : max-size of (rated) results expected
- * @var {int} tolerance
- * @var {boolean} debug : if true sends several debug console messages; if false mesagges are eliminated
- */
+/** VARIABLES
+ * may passed as module arguments
+ * -----------------------------------------------------------------------------
+ *//////////////////////////////////////////////////////////////////////////////
-retrosearch_module({
- products_json: 'https://storage.googleapis.com/pythia-files/uploads/json/emarket-products.json',
- search_tag: '#tagsInput',
- visualize_search_results_url: '/product_list',
- max_list: 24,
- tolerance: 42,
- debug: ((location.hostname == 'localhost') || (location.hostname == '127.0.0.1'))
-});
+var _allowFuzzy = true; // enable|disable fuzzy search
+var n = 2; // Ngram base
+var _fuzzyLimit = .5; // minimum bigram score for being considered a match
+var max_list = 24;
+var tolerance = 42;
+var STORE = { id: 904 };
-
-function retrosearch_module(options) {
-
- /** CONTENTS
- *
- * +1: Variables
- *
- * +2: Purify string functions
- * + keyboardize
- * + sanitize_GR
- * + clean
- *
- * +3: Supplementary function (vanilla js)
- * + ajax_get(url, callback)
- * + createNgram (fuzzy)
- * + checkSimilarity (fuzzy)
- * + check_match
- * + is_exact_match
- * + match_one
- *
- * +4: Actual data loading (async)
- *
- * +5: Suggestions Engine (jQuery)
- * + suggestions_engine
- *
- */
-
- if (options.debug) console.log(`preparing retrosearch... (${+ new Date()})`);
-
-
- /** 1. VARIABLES
- * -------------------------------------------------------------------------
- *//////////////////////////////////////////////////////////////////////////
-
- var _kwlinks; // keyword links (word-connections; imported via ajax-get)
- var _products = []; // all products (imported via ajax-get)
-
- // setup options
- var _maxResults = options.max_list; // limit suggestions
- var _blendProds = 4; // minimum final-produncts to blend with next-word suggestions
- var _timeout_ms = 100; // time (in ms) for the search engine to find matches (before rendering)
- var _allowFuzzy = true; // enable|disable fuzzy search
- var _fuzzyLimit = .5; // minimum bigram score for being considered a match
- var _Ngram_base = 2; // number of N in Ngram spliting algorithm
- var _isReady = false; // whether the searchbox is ready to be used
-
- // product keywords
- var keywordsURL = options.keywords_json;
-
- var cursor_on = { none: true }; // what product is highlighted; if not on product then { none: true }
+var _kwlinks; // keyword links (word-connections; imported via ajax-get)
+var _products = []; // all products (imported via ajax-get)
+
+// setup options
+var _maxResults = options.max_list; // limit suggestions
+var _blendProds = 4; // minimum final-produncts to blend with next-word suggestions
+var _Ngram_base = 2; // number of N in Ngram spliting algorithm
+var _isReady = false; // whether the searchbox is ready to be used
+
+// product keywords
+var keywordsURL = options.keywords_json;
+
+var cursor_on = { none: true }; // what product is highlighted; if not on product then { none: true }
- /** 3. SUPPLEMENTARY FUNCTIONS
- * -------------------------------------------------------------------------
- *//////////////////////////////////////////////////////////////////////////
+/** SUPPLEMENTARY FUNCTIONS
+ * -----------------------------------------------------------------------------
+ *//////////////////////////////////////////////////////////////////////////////
- // TODO:
- // exclude some generic non-critial words when proccessing user's query
- // ** example code to work with:
- // var ignoredKeys_kb = []; // keywords to ignore (in kb-format)
- // 'μας με σε για του της των από στο στον &'.split(' ').forEach(w => { ignoredKeys_kb.push(keyboardize(w)); });
-
- // pure JS ajax GET request; return data as JSON
- // no fancy things like UTF8; if needed use base64
- function ajax_get(url, callback) {
- var xmlhttp = new XMLHttpRequest();
- xmlhttp.onreadystatechange = function() {
- if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
- try {
- var data = JSON.parse(xmlhttp.responseText);
- } catch(err) {
- if (options.debug) console.log(err.message + " in " + xmlhttp.responseText);
- return;
- }
- callback(data);
- }
- };
- xmlhttp.open("GET", url, true);
- xmlhttp.send();
- }
+// callback function for sorting resulrs per r (=rating) property
+function compare_rate(a,b) {
+ return (a.r < b.r);
+}
- // callback function for sorting resulrs per r (=rating) property
- function compare_rate(a,b) {
- return (a.r < b.r);
- }
- /** vwOverUnder
- * vertical-wise over/under
- *
- * @param {document.element} el : element to check
- * @param {document.element} container : container element (compairing)
- * @return {int} .. [-1|0|+1]
- * ..: 0 if element's heignt is completely into container's viewport
- * ..: -1 if element's heignt is over container's viewport
- * ..: +1 if element's heignt is under container's veiwport
- */
- function vwOverUnder(el, container) {
- let eR = el.getBoundingClientRect();
- let cR = container.getBoundingClientRect();
- console.log('er|cr', eR, cR);
-
- let result = -1; // default: element is under container's viewport
-
- if (eR.y >= cR.y && eR.y + eR.height <= cR.y + cR.height - options.tolerance) {
- result = 0 // fully inside
-
- } else if (eR.y < cR.y) {
- result = -1
- }
-
- return result;
- }
+/** SEARCH ENGINE
+ * -------------------------------------------------------------------------
+ *//////////////////////////////////////////////////////////////////////////
-
- /** 4. ACTUAL DATA LOADING
- * -------------------------------------------------------------------------
- *//////////////////////////////////////////////////////////////////////////
+function matchWordInList(q, list = false) {
+ if (list !== false && list.length == 0) return []; // no results
- // TODO:
- // control completion of async loads via .then() rather by this custom structrure
- // Need to rewrite the folllowing code ............................. from here
- // ...........................................................................
- // ...........................................................................
-
+ var result = [];
+ var firstPass = false;
- /** workline
- * -------------------------------------------------------------------------
- * custom object/data-structure
- * to track status/completion of async svents
- * (it does the job using a special set method)
- */
- var workline = {
-
- trackerJL : 0,
- set jsonLoaded(x) {
- this.trackerJL = x;
-
- // fire event on certain values
- if (x == 2) {
- if (options.debug) console.info('suggestion-engine requirements fulfilled');
- _isReady = true;
- // code to execute
- // ...
- }
- },
- get jsonLoaded() { return this.trackerJL; }
- };
-
-
- /** LOAD DATA (from endoints)
- * ---------------------------------------------------------------------------
- */
+ if (list === false) {
+ firstPass = true; // on first pass
+ list = products; // list is all products
+ }
-
- function load_store_products(storeID) {
- let prData = getSessionObj('prd');
- if (prData !== null) {
- _products = prData;
- if (options.debug) console.log(`...products fetched from cache (${+ new Date()})`);
- workline.jsonLoaded++;
+ for(let i = 0 ; i < list.length ; i++) {
- } else {
- ajax_get(options.products_json, function(data) { // get stor's _products
- _products = data;
- _products.forEach(p => {p.kb = keyboardize(p.w).toLowerCase()} );
- setSessionObj('prd', _products);
- if (options.debug) console.log(`...products loaded; (${+ new Date()})`);
- workline.jsonLoaded++;
- CURRENT_STOREs_CATALOG = storeID;
+ // check exact + rate
+
+ // else check partial + rate
+
+ // else check similarity + rate
+
+ let found = false;
+ let similarity = 0;
+ products[i].kb.split(' ').forEach( w => {
+ let sim = match.resemblance(q, w, 2);
+ if (sim > 0.5) {
+ found = true;
+ similarity = (sim > similarity) ? sim : similarity;
+ }
});
- }
+ if (found) {
+ products[i].similarity = similarity;
+ products[i].rating = (firstPass)
+ ? similarity * 2.0
+ : products[i].rating + similarity * 2.0
+ result.push(products[i]);
+ }
}
-
- var STORE = { id: 904 };
-
- if (STORE.id != 0) load_store_products(STORE.id);
-
- // ...........................................................................
- // ...........................................................................
- // ................................................................ up to here
+
+ return result
+}
-
-
-
- /** 5. SEARCH ENGINE
- * -------------------------------------------------------------------------
- *//////////////////////////////////////////////////////////////////////////
-
- workline.jsonLoaded++; // notify workline that jQuery is ready!!
-
- // suggestions engine //////////////////////////////////////////////////
- // ---
- function suggestions_engine(qOrig) {
- var results = []; // suggestions to respond
- var pot = []; pot.length = 0;
-
- var space_ended = (qOrig.slice(-1) == ' ') ? true : false;
-
- // clean and sanitize and mark links onto q(uery) string
- var q = keyboardize( sanitize_GR( clean_text(qOrig.trim()) ) ).trim();
-
- // TODO:
- // construct direct-linked words
- // = do unequivocally replaces
- // steps:
- // 1. replace accented vowels with non accented ones
- // 2. replace `/some pattern/gi , 'SOME-REPLACE-PATTERN'`
-
- var qAr = q.split(' '); // split to words
- /// if (space_ended) qAr.push(' '); // if space-end existed, push a space to query array
- ///
- /// if (qAr.slice(-1) == "") {
- /// qAr.pop();
- /// }
-
- if (options.debug) console.log('*** init SEARCH QUERY:', qOrig, 'search:', qAr);
+
+// suggestions engine //////////////////////////////////////////////////
+// ---
+function suggestions_engine(query) {
+ var results = [];
+ var pot = []; pot.length = 0;
+
+ // clean and sanitize and mark links onto q(uery) string
+ var q = kb.keyboardize( kb.sanitizeGR( kb.clean(query.trim()) ) ).trim();
- pot = _products; // potential results // NOTE: CRITICAL: BY REFERENCE
+ // TODO:
+ // construct direct-linked words
+ // = do unequivocally replaces
+ // steps:
+ // 1. replace accented vowels with non accented ones
+ // 2. replace `/some pattern/gi , 'SOME-REPLACE-PATTERN'`
- var wi = 0; // word index (from list)
- var wc = qAr.length;
+ var qAr = q.split(' '); // split to words
+ /// if (space_ended) qAr.push(' '); // if space-end existed, push a space to query array
+ ///
+ /// if (qAr.slice(-1) == "") {
+ /// qAr.pop();
+ /// }
- qAr.forEach( w => {
- if (options.debug) console.log('...testing', w);
- let sf = []; // (matches) so far
- let mi; // position of match
- wi++;
+ pot = _products; // potential results // NOTE: CRITICAL: BY REFERENCE
- pot.forEach( it => {
- let matched = false;
- let tester = ' '+ it.kb + ' ';
-
- // reset previous history and ratings
- if (wi == 1) {
- it.r = 0;
- it.history = [];
- }
-
-
- // rate word-match > start-match > simple-match
- // ... up to 8 points
-
- if (tester.indexOf(' '+ w +' ') != -1) {
- it.r += 9;
- it.history.push({ w: w, rate: 9 });
- matched = true;
- }
- else if (tester.indexOf(' '+ w) != -1) {
- it.r += 5;
- it.history.push({ w: w, rate: 5 });
- matched = true;
- }
- else if (tester.indexOf(w) != -1) {
- it.r += 2;
- it.history.push({ w: w, rate: 2 });
- matched = true;
- }
-
- // rate `near-to-start` matching .. up to 7p
- // rate `earlyness` of word in query .. up to 7p
-
- if ((mi = tester.indexOf(' '+w)) != -1) {
- let fc1 = 100 - ((mi < 99) ? mi : 99); // near-to-start factor
- let fc2 = wc - wi + 1; // query earlyness factor
- let r1 = Math.floor(7*fc1/100);
- let r2 = Math.floor(7*fc2/wc);
-
- it.r += (r1 + r2);
- it.history.push({ w: w, left: [fc1, r1], early: [fc2, r2] });
- }
- if (matched) sf.push(it);
- });
+ var wi = 0; // word index (from list)
+ var wc = qAr.length;
- if ((sf.length > (_maxResults + Math.floor(_maxResults/2)))
- || (wi == 1) ) {
- // ..if pot has a fair amount (= max + 50%) of results
- // ..or these are results of '1st-query-word'
- // set sf as new source
- pot.lenght = 0; pot = [];
- pot = JSON.parse(JSON.stringify(sf)); // copy by value
-
- } else {
- // else.. keep the source list and increase of 'so-far rating'
- // console.log('found small list', sf, pot)
- pot.forEach( it => {
- sf.forEach( si => {
- if (it.id == si.id) {
- it.r += 10;
- it.history.push({ w: w, plus: '+10'});
- }
- });
- });
- }
- });
+ qAr.forEach( w => {
- // sort results, get max-list of best rated
- results = (pot.length > _maxResults)
- ? pot.sort(compare_rate).slice(0, _maxResults)
- : pot.sort(compare_rate)
+ let sf = []; // (matches) so far
+ let mi; // position of match
+ wi++;
- if (options.debug) console.log(results);
-
- return results;
- }
-
- // suggestions caller (router function)
- // arguments:
- // * qOrig : original query string
- // ** list : callback array structure to host results
- // ---
- var isuggest = function(qOrig, list) {
- var results;
-
- qSanit = sanitize_GR(qOrig); // sanitize greek accended chars
-
- // TODO:
- // check if all source-lists are ready
- // if not you need to wait ...
- // via async promishes or synced timouts
-
- /// // DEPRECATED: Suppport for eys-code search
- /// // if query seems to be some king of 'code/id'
- /// if (qSanit.length>2 && qSanit.match(/^[0-9]+$/) != null) {
- /// results = search_by_code(qOrig);
- ///
- /// } else {
- /// // string match procedure with suggestions engine
- results = suggestions_engine(qOrig);
- /// }
-
- list(results);
- }
+ pot.forEach( it => {
+ let matched = false;
+ let tester = ' '+ it.kb + ' ';
- // var rsfoot = document.createElement('div');
- // rsfoot.setAttribute("id", "retrosearch-footer");
- // $('#retrosearch-footer').html('Multi Search');
-
- /*
- jQuery(function() { // on document ready code //////////////////////////
-
- // UI-dependent code
- // uses reference to specific document element (passed via options)
- // -----------------------------------------------------------------------
- const searchBox = $(options.search_tag);
- searchBox.typeahead(
- {
- hint: true,
- highlight: true,
- minLength: 1
- },
- {
- limit: _maxResults, // +1 for extra button
- // name: 'kwlinks',
- displayKey: 'w',
- source: isuggest,
- templates: {
- suggestion: function(data) {
- return `<div data-id="${data.id}">${data.w}<span>Alfa, Beta and Gamma</span></div>`;
- },
-
- footer: '<div class="tt-suggestion tt-selectable call-multi-search">Multi Searh</div>',
-
- empty: '<div class="-empty-">Δεν υπάρχει στο κωδικολόγιο του καταστήματος</div>'
- }
+ // reset previous history and ratings
+ if (wi == 1) {
+ it.r = 0;
+ it.history = [];
}
- )
- .bind("typeahead:selected", function(obj, datum, name) {
- if (datum.hasOwnProperty('id')) { // ** selected: PRODUCT
-
- // $('#js-add-product-to-order').attr('disabled', false);
- // fill_fields(datum.id, datum.sc, datum.x, datum.w, 1, datum.bc, datum.eu, datum.stk, datum.img);
- if (options.debug) console.log('selected: ', datum.id, datum.w);
- // GOTO product page
- window.location.href = 'product_list?product=id-' + datum.id;
-
- // $("#product-quantity").trigger('focus');
+ // rate word-match > start-match > simple-match
+ // ... up to 8 points
+
+ if (tester.indexOf(' '+ w +' ') != -1) {
+ it.r += 9;
+ it.history.push({ w: w, rate: 9 });
+ matched = true;
}
- else { // selected: SUGGESTION
-
- $('.typeahead').typeahead('val','').trigger('blur');
- $('.typeahead').typeahead('val', datum.w +' ')
- .trigger("query");
- // give some time to the engine to calculate results
- // then fire focus again...
- setTimeout(() => { $('.typeahead').trigger('focus'); }, _timeout_ms);
+ else if (tester.indexOf(' '+ w) != -1) {
+ it.r += 5;
+ it.history.push({ w: w, rate: 5 });
+ matched = true;
}
-
- })
- .bind("typeahead:cursorchange", function( event, obj) {
- // track cursor-chane to handle special keys after a final product is selected
-
- if (typeof obj === 'object'
- && !Array.isArray(obj) && obj !== null) {
-
-
- // console.log(obj);
- // var liObj = $(`.tt-menu .tt-dataset .tt-suggestion[data-id="${obj.id}"]`)
- // var c = liObj.html();
- // liObj.html = c + '\n\n_';
- // liObj.html = c;
-
- var y = $('.tt-menu').scrollTop();
- let ou = vwOverUnder(
- document.querySelector(`.tt-menu .tt-suggestion[data-id="${obj.id}"]`),
- document.querySelector('.tt-menu')
- );
- console.log('y:',y, 'obj:', obj, 'o/u:', ou);
- $('.tt-menu').scrollTop( y - ou * options.tolerance);
-
- // TODO:
- // need to park the cursorChanged-div into tt-menu veiwport (??)
- // check: https://stackoverflow.com/questions/75002332/check-if-child-element-is-100-visible-inside-a-parent-div-that-has-overflow-hid
-
+ else if (tester.indexOf(w) != -1) {
+ it.r += 2;
+ it.history.push({ w: w, rate: 2 });
+ matched = true;
}
+ // rate `near-to-start` matching .. up to 7p
+ // rate `earlyness` of word in query .. up to 7p
- // TODO:
- // handle exception where obj is undefined;
- // this occures...
- // when cusror returns from suggestions list back to the search field
-
- if (typeof obj === 'undefined') cursor_on = { none: true };
- else if (obj.hasOwnProperty('id')) cursor_on = obj;
- else cursor_on = { none: true };
- })
- .bind('typeahead:opened', function(e) {
- console.log('attach multisearch option if not exist');
- });
-
- // TRACK user search attempt ///////////////////////////////////////////////
-
+ if ((mi = tester.indexOf(' '+w)) != -1) {
+ let fc1 = 100 - ((mi < 99) ? mi : 99); // near-to-start factor
+ let fc2 = wc - wi + 1; // query earlyness factor
+ let r1 = Math.floor(7*fc1/100);
+ let r2 = Math.floor(7*fc2/wc);
- // $('.typeahead').on('typeahead:opened', function(e) {
- // console.log('attach multisearch option if not exist');
- // });
-
- $('.typeahead').on('keyup', function(e) {
- if (_isReady) {
- // console.log('on:', cursor_on);
- // console.log('key:', e.key);
- if ((e.key == ' ') && cursor_on.hasOwnProperty('id')) {
-
- // product is actually selected
- var datum = cursor_on;
-
- // fill_fields(datum.id, datum.sc, datum.x, datum.w, 1, datum.bc, datum.eu, datum.stk, datum.img);
- $("#product-quantity").trigger('focus');
- e.preventDefault();
+ it.r += (r1 + r2);
+ it.history.push({ w: w, left: [fc1, r1], early: [fc2, r2] });
+ }
+ if (matched) sf.push(it);
+ });
- } else {
- if (e.key === "Enter") {
+ if ((sf.length > (_maxResults + Math.floor(_maxResults/2)))
+ || (wi == 1) ) {
+ // ..if pot has a fair amount (= max + 50%) of results
+ // ..or these are results of '1st-query-word'
+ // set sf as new source
+ pot.lenght = 0; pot = [];
+ pot = JSON.parse(JSON.stringify(sf)); // copy by value
- // if curson is not on some option
- if ((typeof curson_on === 'undefined') || (curson_on.none == true)) {
+ } else {
+ // else.. keep the source list and increase of 'so-far rating'
+ // console.log('found small list', sf, pot)
+ pot.forEach( it => {
+ sf.forEach( si => {
+ if (it.id == si.id) {
+ it.r += 10;
+ it.history.push({ w: w, plus: '+10'});
+ }
+ });
+ });
+ }
+ });
- // do a common search
- if (options.debug) console.log('Do a Non-Suggestions search', searchBox.val());
+ // sort results, get max-list of best rated
+ results = (pot.length > _maxResults)
+ ? pot.sort(compare_rate).slice(0, _maxResults)
+ : pot.sort(compare_rate)
- // DEPRICATED: var location = encodeURI('/product_list?productSearch=%'+ searchBox.val() +'%');
+ if (options.debug) console.log(results);
- // search_results = common_search(searchBox.val());
- // TODO:
- console.log('DO A COMMON_SEARCH');
+ return results;
+}
- } else {
- // launch a product page
- var location = '/product_list?product=id-'+ cursor_on.id;
- if (options.debug) console.log('product', cursor_on.id, cursor_on.w);
+// sub-module (start)
+////////////////////////////////////////////////////////////////////////////
- // TODO:
- console.log('GO TO PRODUCT PAGE', location)
- }
- // window.location.href = location;
- }
- }
- }
- });
-
- });
- */
-
- // sub-module (start)
- ////////////////////////////////////////////////////////////////////////////
-
- function update_common_search_results(q, results) {
- let queries = getSessionObj('sr');
- let newSRlist = [];
- let isnewQ = true;
- if (queries === null) {
- setSessionObj('sr', [{
- q: q,
- result: result,
- t: + new Date()
- }]);
- return true;
+function update_common_search_results(q, results) {
+ let queries = getSessionObj('sr');
+ let newSRlist = [];
+ let isnewQ = true;
+ if (queries === null) {
+ setSessionObj('sr', [{
+ q: q,
+ result: result,
+ t: + new Date()
+ }]);
+ return true;
- } else {
+ } else {
- queries.forEach(it => {
- if (it.q == q) {
- newSRlist.push({
- q:q,
- result: result,
- t: + new Date()
- });
- isnewQ = false;
- } else { newSRlist.push(it); }
- });
-
- if (isnewQ) {
+ queries.forEach(it => {
+ if (it.q == q) {
newSRlist.push({
q:q,
result: result,
t: + new Date()
});
- }
+ isnewQ = false;
+ } else { newSRlist.push(it); }
+ });
- return true;
+ if (isnewQ) {
+ newSRlist.push({
+ q:q,
+ result: result,
+ t: + new Date()
+ });
}
+
+ return true;
}
+}
-
- ////////////////////////////////////////////////////////////////////////////
- // sub-module (end)
-
-
- function common_search(query) {
- // clear ; sanitize ; split
- var qAr = keyboardize( sanitize_GR( clean_text(query) ) ).toLowerCase().split(' ');
- // if last item is empty, remove it
- if ((qAr.slice(-1) == ' ') || (qAr.slice(-1) == '')) qAr.pop()
+////////////////////////////////////////////////////////////////////////////
+// sub-module (end)
- var results = _products;
- // for each key fitler results
- qAr.forEach( key => {
- results = key_sublist(key, results)
- });
+function common_search(query) {
+ // clear ; sanitize ; split
+ var qAr = keyboardize( sanitize_GR( clean_text(query) ) ).toLowerCase().split(' ');
- // echo products (and prepare list to POST)
- var list_ = [];
- results.forEach( item => {
- if (options.debug) console.log(item.id, ':', item.w);
- list_.push(item.id)
- })
+ // if last item is empty, remove it
+ if ((qAr.slice(-1) == ' ') || (qAr.slice(-1) == '')) qAr.pop()
- // *** TODO: keep results in local storage (or on session storage)
+ var results = _products;
- // update_common_search_results(query, list_);
+ // for each key fitler results
+ qAr.forEach( key => {
+ results = key_sublist(key, results)
+ });
- let l = list_.join(',');
- var url = encodeURI(`${options.visualize_search_results_url}?search=${query}&eys_code=${l}`);
+ // echo products (and prepare list to POST)
+ var list_ = [];
+ results.forEach( item => {
+ if (options.debug) console.log(item.id, ':', item.w);
+ list_.push(item.id)
+ })
- console.log('common search: search query > location = search')
- window.location.href = encodeURI(`${options.visualize_search_results_url}?search=${query}`);
+ // *** TODO: keep results in local storage (or on session storage)
- }
+ // update_common_search_results(query, list_);
+
+ let l = list_.join(',');
+ var url = encodeURI(`${options.visualize_search_results_url}?search=${query}&eys_code=${l}`);
+
+ console.log('common search: search query > location = search')
+ window.location.href = encodeURI(`${options.visualize_search_results_url}?search=${query}`);
- /** return from list only items that include 'key'
- */
- function key_sublist(key, list) {
- var result = [];
- list.forEach( item => {
- if (item.kb.includes(key)) {
- result.push(item);
- }
- });
-
- return result;
- }
-
}
-
-/** test script
- * ---
- * pl = getSessionObj('prd'); wl = ['coca', 'xvris', 'zaxarh', '2x1'];
- * pot = pl;
- * console.log(+ new Date());
- * wl.forEach( w => {
- * let sf = [];
- * for(i=0 ; i < pot.length; i++) { if (pot[i].kb.includes(w)) sf.push(pot[i]); }
- * pot.lenght = 0; pot = sf;
- * });
- * console.log(+ new Date(), pot);
- *
- *
- ** test performance for vs foreach
- * ---
- * pl = getSessionObj('prd'); console.log('started', + new Date());
- * for(j=0; j<50; j++) { for(i=0; i<pl.length; i++) { let x = pl[i].kb; } }
- * console.log('ended', + new Date());
- *
- * pl = getSessionObj('prd'); console.log('started', + new Date());
- * for(j=0; j<50; j++) { pl.forEach( it => { let x = it.kb; }); }
- * console.log('ended', + new Date());
-**/ \ No newline at end of file
+/** return from list only items that include 'key'
+ */
+function key_sublist(key, list) {
+ var result = [];
+ list.forEach( item => {
+ if (item.kb.includes(key)) {
+ result.push(item);
+ }
+ });
+
+ return result;
+}