PageSourceSearch

https://www.ledlightexpert.com/assets/templates/ledlightexpert2026-core/fusionbot/sl.js?vcart=26.37.3

js ledlightexpert.com collected 2026-10-02 04:01:36 UTC 16,074 bytes, 444 lines download raw bytes

1/*
2 * jQuery Search Light Plugin
3 * version: 1.0.1 (2009/07/29)
4 * @requires jQuery v1.3.0 or later
5 *
6 * Copyright 2009 Ryan Williams
7 *   http://ryanwilliams.org
8 *   [email protected]
9 *
10 * Dual licensed under the MIT and GPL licenses:
11 *   http://www.opensource.org/licenses/mit-license.php
12 *   http://www.gnu.org/licenses/gpl.html
13 *
14 */
15
16//For jsonp version of searchlight, surround the .jso template content in the FusionBot account
17//in a static function named jsonp_callback()
18
19//make global var, so can reference outside of dynamic function
20var searchlight;
21
22(function($) {
23    var SearchLight = function(input, url, options) {
24        settings = $.extend({
25            minimumCharacters: 3,
26            searchDelay: 100,
27            limitPerCategory: 5,
28            actionFunction: null,
29            align: 'left',
30            width: '400',
31            showIcons: true,
32            ratings: false,
33            saleImg: '/assets/templates/time-core/fusionbot/on-sale-tag.png',
34            showEffect: 'scroll', // TODO
35            hideEffect: 'fade'  // TODO
36        }, options);
37        this._settings = settings;
38
39        //short circuit for small screens
40        if( $( document ).width() <= 766)
41          return true;
42
43        var input = $(input);
44        var container = $(document.createElement('div'));
45        container.attr('class',  'searchlight-balloon');
46
47        //myTop defined before insertion of sl.js in client side page, to hard code position of preview box, rather than calculate dynamically
48        if(typeof myTop == "undefined")
49        {
50           container.css({
51              position: 'absolute',
52              top: input.offset().top + input.outerHeight() + 3,
53              display: 'none'
54          });
55        }
56        else
57        {
58           container.css({
59              position: 'absolute',
60              top: myTop,
61              display: 'none'
62          });
63
64        }
65
66
67        if (settings.width == 'auto') {
68            container.css('width', input.outerWidth());
69        }
70
71        if (settings.align == 'left') {
72          //myLeft defined before insertion of sl.js in client side page, to hard code position of preview box, rather than calculate dynamically
73          if(typeof myLeft == "undefined")
74            container.css('left', input.offset().left - 1.5);
75          else
76            container.css('left', myLeft);
77
78
79        } else if (settings.align == 'right') {
80            if(typeof myRight == "undefined")
81              container.css('right', $(document.body).innerWidth() - (input.offset().left + input.outerWidth()));
82            else
83              container.css('right', myRight);
84        }
85
86
87        var results = $(document.createElement('div'));
88        results.attr('class', 'searchlight-results-wrapper');
89        //results.css({
90        //    height: '100%'
91        //});
92
93        //if ($.browser.msie && parseFloat($.browser.version) <= 7) {
94        //    results.css({
95        //        width: '100%'
96        //    });
97        //}
98
99        container.append(results);
100        $(document.body).append(container);
101
102
103        this._input = input;
104        this._container = container;
105        this._searchURL = url;
106        this._resultsContainer = results;
107
108        input.bind('focus.searchlight', {searchlight: this}, function(evt) {
109            searchlight = evt.data.searchlight;
110            if (this.value.length >= settings.minimumCharacters) {
111                searchlight.search(this.value);
112            }
113        });
114        $(document.body).bind('mousedown.searchlight', {searchlight: this}, function(evt) {
115            searchlight = evt.data.searchlight;
116
117            // Make sure we didn't click the searchlight
118            var node = evt.target;
119            var c = 0
120            while (node) {
121                // Clicked searchlight, so return
122                if (node == searchlight._input[0] || node == searchlight._container[0]) {
123                    return;
124                }
125                node = node.parentNode;
126            }
127
128            searchlight.hide();
129        });
130
131        input.bind('keydown.searchlight', {searchlight: this}, function(evt) {
132            searchlight = evt.data.searchlight;
133            if (evt.which == 38 && searchlight._selectedRow > 0) {
134                // Up arrow
135                searchlight.selectRow(searchlight._selectedRow-1);
136            } else if (evt.which == 40 && searchlight._selectedRow < searchlight._rowCount -1) {
137                // Down arrow
138                searchlight.selectRow(searchlight._selectedRow+1);
139            } else if (evt.which == 13 && searchlight._selectedRow > -1) {
140                searchlight.activateRow(searchlight._selectedRow);
141            }
142            //if (evt.which == 13 || evt.which == 38 || evt.which == 40) {
143            //remove 13 so can submit search with enter key
144            if (evt.which == 38 || evt.which == 40) {
145                evt.preventDefault();
146            }
147        });
148        input.bind('keyup.searchlight', {searchlight: this}, function(evt) {
149            searchlight = evt.data.searchlight;
150            if (searchlight._searchDelayTimer) {
151                clearTimeout(searchlight._searchDelayTimer);
152            }
153            searchlight._searchDelayTimer = setTimeout(function() {
154                var input = searchlight._input[0];
155                if (input.value == searchlight._previousQuery) {
156                } else if (input.value.length >= settings.minimumCharacters) {
157                    searchlight.search(input.value);
158                } else {
159                    searchlight.hide();
160                }
161            }, settings.searchDelay);
162        });
163        input.bind('keypress.searchlight', {searchlight: this}, function(evt) {
164
165            searchlight = evt.data.searchlight;
166        });
167        this._container.bind('mouseleave.searchlight', {searchlight: this}, function(evt) {
168            searchlight = evt.data.searchlight;
169            searchlight.selectRow(-1);
170        });
171
172
173        this.resultAction = settings.actionFunction ? settings.actionFunction : this.defaultResultAction;
174    };
175    SearchLight.prototype.show = function() {
176        if (!this._container.is(':visible')) {
177            this._container.fadeIn('fast');
178        }
179    };
180    SearchLight.prototype.hide = function() {
181        if (this._disableHide) {
182            return;
183        }
184        this._container.fadeOut('fast');
185    };
186
187    SearchLight.prototype.search = function(query) {
188        searchlight = this;
189        this._previousXHR = $.ajax({
190          dataType: 'jsonp',
191          data: 'k=' + query,
192          url: this._searchURL,
193          success: function jsonp_callback(results){}
194        });
195        searchlight.show();
196    };
197
198    SearchLight.prototype.clearResults = function() {
199        this._categoryCount = 0;
200        this._rowCount = 0;
201        this._selectedRow = -1;
202        this._resultsContainer.html('<table class="searchlight-results"></table>');
203    };
204
205    SearchLight.prototype.addFooter = function(results) {
206
207      if(results.length == 5) {
208
209        theForm = "";
210        if(document.fbsearch !== undefined)
211          theForm = "fbsearch";
212        else if(document.searchForm !== undefined)
213          theForm = "searchForm";
214
215        if(theForm.length > 0) {
216
217          var tr = document.createElement('tr');
218          $(tr).attr('id', 'searchlight-footer');
219          var td = document.createElement('td');
220          $(td).attr('align', 'center');
221          $(td).attr('width', '100%');
222          $(td).attr('colspan', '2');
223          //$(td).html('<div id="searchlight-footer" onclick="document.getElementsByName(theForm)[0].submit();">More...</div>');
224          $(td).html('<div id="searchlight-footer" onclick="document.getElementsByName(theForm)[0].submit();">View All Results<div id="qsMoleculeDiv"><a onclick="event.stopPropagation();" href="https://www.fusionbot.com/default.asp?source=FB-164720028" target="_blank"><img id="qsMoleculeImg" title="Powered by FusionBot" src="/assets/templates/ledlightexpert-core/fusionbot/molecule.png" border=0></a></div></div>');
225          $(tr).append(td);
226          this._resultsContainer.children('table').append(tr);
227
228        }
229
230      }
231
232    };
233
234
235SearchLight.prototype.addResultCategory = function(name, results) {
236        var first = true;
237        for (var i = 0; i < results.length; i++) {
238            var r = results[i];
239
240            var tr = document.createElement('tr');
241            $(tr).attr('class', 'searchlight-not-selected');
242
243            //var th = document.createElement('th');
244            var td = document.createElement('td');
245            //$(th).html('<span class="searchlight-header-text"></span>');
246            $(td).html('<span class="searchlight-result-text"></span>');
247            //var th_d = th.firstChild;
248            var td_d = td.firstChild;
249
250            //if (first) {
251            //    $(th_d).text(name);
252            //    first = false;
253            //}
254
255            if (this._settings.showIcons) {
256                var img = document.createElement('img');
257                img.className = 'searchlight-result-icon';
258                //img.style.width = '50px';
259                //if(typeof noHeight == "undefined")
260                //  img.style.height = '50px';
261                // If icon, then use that otherwise use blank
262                img.src = r[2] ? r[2] : 'assets/templates/common/images/spacer.gif';
263                $(td_d).append(img);
264                //$(".searchlight-result-icon").attr("onerror","this.onerror=null;this.src='/assets/images/default.jpg'");
265                $(img).error(function() {
266                  $(this).attr( "src", "/assets/images/default.jpg" );
267                })
268              }
269
270            var ttl = r[1];
271            $(td_d).append("<span class=sl_title>" + ttl + "</span>");
272            //if(!r[4] || 0 === r[4].length || r[4] == "-1") {
273            //  $(td_d).append("<br><span align=left class=search-price>" + r[3] + "</span>");
274            //} else {
275
276			//r[5] = $RES_ONS (is on sale?)
277			var priceline = "";
278			//var clvl = getPriceLvl();
279			var clvl = 0;
280			if(clvl > 0) {
281			  if(typeof(r[7]) !== "undefined" && r[7].length > 0) //r[7] = price level 2 when present
282			    $(td_d).append("<br><span align=left class='search-price'>" + r[7] + "</span>");
283			  else
284			    $(td_d).append("<br><span align=left class='search-price'>" + r[3] + "</span>");
285		    } else {
286			  if(typeof(r[5]) !== "undefined" && r[5] == "1") {
287			    if( typeof(r[6]) !== "undefined" && r[6].length > 0)
288			      priceline = "<span align=left class='search-price' style='margin-right:5px;'><s>" + r[6] + "</s></span><img class='sale-price-img' src='" + this._settings.saleImg + "'>";
289			    priceline += "<span align=left class='sale-price'>" + r[3] + "</span>";
290		        $(td_d).append("<br>" + priceline);
291		      } else {
292		        $(td_d).append("<br><span align=left class='search-price'>" + r[3] + "</span>");
293		      }
294		    }
295
296            if (this._settings.ratings) {
297              rating = 0;
298              if(typeof r[4] != "undefined" && r[4].length > 0)
299		        rating = r[4];
300              $(td_d).append("<br><span class='star"+rating+"'><i class='fa fa-star-o'></i> <i class='fa fa-star-o'></i> <i class='fa fa-star-o'></i> <i class='fa fa-star-o'></i> <i class='fa fa-star-o'></i></span>");
301		    }
302
303            //$(tr).append(th);
304            $(tr).append(td);
305
306            $(tr).bind('mousemove', {searchlight: this}, function(evt) {
307                searchlight = evt.data.searchlight;
308                searchlight.selectRow(this._rowId);
309            });
310            $(tr).bind('click', {searchlight: this}, function(evt) {
311                searchlight = evt.data.searchlight;
312                searchlight.activateRow(this._rowId);
313            });
314
315            tr._rowId = this._rowCount;
316            actURL = r[0];
317            actURL = actURL.replace(/&amp;/g, "&");
318            tr._actionValue = actURL;
319            this._resultsContainer.children('table').append(tr);
320            this._rowCount++;
321        }
322
323        // Add spacer if this isn't the first category
324        var tr = document.createElement('tr');
325        //var th = document.createElement('th');
326        var td = document.createElement('td');
327        tr.className = 'searchlight-spacer-row';
328
329        //$(tr).append(th);
330        $(tr).append(td);
331        this._resultsContainer.children('table').append(tr);
332
333        this._categoryCount++;
334    };
335
336
337    SearchLight.prototype.selectRow = function(id) {
338        this._selectedRow = id;
339
340        this._resultsContainer.find('tr:not(.searchlight-spacer-row)').each(function(i) {
341            if (this._rowId == id) {
342                if (!$(this).hasClass('searchlight-selected')) {
343                    $(this).removeClass('searchlight-not-selected');
344                    $(this).addClass('searchlight-selected');
345                }
346            } else {
347                if (!$(this).hasClass('searchlight-not-selected')) {
348                    $(this).removeClass('searchlight-selected');
349                    $(this).addClass('searchlight-not-selected');
350                }
351            }
352        });
353    };
354
355    SearchLight.prototype.activateRow = function(id) {
356        this.resultAction(this._resultsContainer.find('tr:not(.searchlight-spacer-row):eq('+ id +')')[0]._actionValue);
357    }
358
359    SearchLight.prototype.defaultResultAction = function(val) {
360        window.location.href = val;
361    };
362
363
364    $.fn.searchlight = function(url, options) {
365        this.each(function() {
366            new SearchLight(this, url, options);
367        });
368    };
369})(jQuery);
370
371//custom callback function for ajax based searchlight / quicksearch (cross domain requires jsonp callbacks)
372function jsonp_callback(results) {
373  searchlight.clearResults();
374  for (var i = 0; i < results.length; i++) {
375    var r = results[i];
376    if (r.results.length > 0 && typeof r.results[0][0] != 'undefined') { //hide of no results returned (empty array values) in json callback
377          //console.log(r.results[0][0]);
378      searchlight.addResultCategory(r.title, r.results);
379    }
380  }
381  if(typeof r.results[0][0] != 'undefined') {
382    searchlight.addFooter(r.results);
383    //setScrollbar();
384
385  } else {
386    jQuery('.searchlight-balloon').hide();
387  }
388  //run custom stuff directly in search results template (file that instansiates search light), if desired.  Just include function in main template
389  if (typeof slPostProcessing == 'function') {
390    slPostProcessing();
391  }
392
393}
394
395//Adjust position of quicksearch once search box is opened, since position changes after page load to to slow load of logo and/or pop down coupon bar
396function calibrateQS() {
397
398  var input = $("#searchlight");
399  $(".searchlight-balloon").css({
400    position: 'absolute',
401    top: input.offset().top + input.outerHeight(),
402    //width: input.outerWidth(),
403    //left: input.offset().left
404    right: $(document.body).innerWidth() - (input.offset().left + input.outerWidth())
405  });
406}
407
408function setScrollbar() {
409
410  //QuickSearch ScrollBar
411
412  if(typeof mCustomScrollbar !== "undefined") {
413    var $searchScroll = $('.searchlight-balloon');
414    $searchScroll.mCustomScrollbar('destroy');
415    if (jQuery.browser.mobile) {
416      $searchScroll.mCustomScrollbar('destroy');
417      $searchScroll.css({
418        'overflow': 'auto',
419         'max-height': '98px'
420       });
421    } else {
422      $searchScroll.mCustomScrollbar({
423        scrollInertia: 400
424      });
425    }
426  }
427}
428
429function getPriceLvlQS() {
430
431  if(typeof pLvl != "undefined" && pLvl.length > 0) {
432
433    var num = parseInt(pLvl) || 0;
434    return num;
435
436  } else {
437
438    return 0;
439
440  }
441
442}
443
444

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.