1/* 2 mmLiveSearch for Opencart 3.x 3 version: 2.0 4 author: mazein 5 telegram: @maksim_mazein 6*/ 7 8class MMLiveSearch{ 9 constructor(yandex_speller) { 10 this.speller = yandex_speller; 11 this.goToSearch = 0; 12 this.result__class = 'mmlivesearch__result'; 13 this.search_id = mmsearchid; 14 this.search_button_class = mmsearchbuttonclass; 15 this.search_input_name = mmsearchinputname; 16 this.search_input_class = 'mmlivesearch__input'; 17 this.init(); 18 } 19 20 boldQuery(texts, keywords) { 21 if (typeof keywords === 'string') { 22 keywords = keywords.replace(/[^a-zA-Zа-ÑÐ-ЯÑÐ0-9-. ]/g, ""); 23 var expression = $.map([keywords].concat(keywords.split(' ')), function(el) { 24 return "(?:" + el + ")"; 25 }).join('|'); 26 27 var regexp = new RegExp('(' + expression + ')', 'ig'); 28 var filteredText = texts.replace(regexp, '<strong>$1</strong>'); 29 30 return filteredText; 31 } 32 } 33 34 init() { 35 $('header input[name=\'' + this.search_input_name + '\']').addClass(this.search_input_class); 36 37 let self = this; 38 39 $('header input[name=\'' + self.search_input_name + '\']').click(function(){ 40 if ($(this).val()) { 41 self.mmlivesearch(this); 42 } else { 43 self.getMMLiveSearchHistory(this); 44 } 45 }); 46 47 var ctrlDown = false, 48 ctrlKey = 17, 49 cmdKey = 91, 50 vKey = 86, 51 keys = [9, 13, 16, 17, 18, 19, 20, 27, 33, 34, 35, 36, 37, 38, 39, 40, 44, 45, 91, 93, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 144, 145]; 52 $('header input[name=\'' + self.search_input_name + '\']').keydown(function(e){ 53 if (e.keyCode == ctrlKey || e.keyCode == cmdKey) ctrlDown = true; 54 }).keyup(function(e) { 55 if (e.keyCode == ctrlKey || e.keyCode == cmdKey) ctrlDown = false; 56 }); 57 $('header input[name=\'' + self.search_input_name + '\']').keydown(self.delay(function(e){ 58 if (ctrlDown && (e.keyCode == vKey)){ 59 self.mmlivesearch(this); 60 } 61 if (!ctrlDown && $.inArray(e.keyCode, keys) == -1){ 62 self.mmlivesearch(this); 63 } 64 }, 500)); 65 66 $('header input[name=\'' + self.search_input_name + '\']').parent().find('button').bind('click', function () { 67 if (!$(this).parent().parent().find('.' + self.result__class + ' span').hasClass('selected')){ 68 var url = $('base').attr('href')+'index.php?route=product/search'; 69 70 var search = $(this).parent().parent().find('input[name=\'' + self.search_input_name + '\']').val(); 71 //search = search.replace(/[^a-zA-Zа-ÑÐ-ЯÑÐ0-9-. ]/g, ""); 72 73 if (search) { 74 url += '&search=' + encodeURIComponent(search); 75 } 76 77 self.goFromMMLiveSearch('search', '', search, url); 78 } 79 }); 80 81 const div = document.querySelector('#' + self.search_id); 82 document.addEventListener('click', (e) => { 83 const withinBoundaries = e.composedPath().includes(div); 84 85 if (!withinBoundaries) { 86 if ($('header #' + self.search_id + ' .mmlsloader').length) { 87 $('header #' + self.search_id + ' .mmlsloader').remove(); 88 } 89 $("." + self.result__class).remove(); 90 $('header input[name=\'' + self.search_input_name + '\']').val(''); 91 } 92 }) 93 94 var delay = (function(){ 95 var timer = 0; 96 return function(callback, ms){ 97 clearTimeout (timer); 98 timer = setTimeout(callback, ms); 99 }; 100 })(); 101 102 self.getSearchtyped(); 103 } 104 105 mmlivesearch(thisis){ 106 let self = this; 107 108 var word = $(thisis).val(); 109 //word = word.replace(/[^a-zA-Zа-ÑÐ-ЯÑÐ0-9-. ]/g, ""); 110 111 var url_to_search = $('base').attr('href')+'index.php?route=product/search'; 112 if (word) { 113 url_to_search += '&search=' + encodeURIComponent(word); 114 } 115 116 if (word.length >= 3){ 117 if (self.speller !== null) { 118 var new__word = self.speller.init(word); 119 if(typeof(new__word) != "undefined" && new__word !== null && new__word !== '') { 120 word = new__word; 121 } 122 } 123 124 $.ajax({ 125 type: "POST", 126 url: "index.php?route=extension/mmlivesearch/mmlivesearch", 127 data: {"word": word}, 128 dataType: 'json', 129 cache: false, 130 beforeSend: function(){ 131 if (!$('header #' + self.search_id + ' .mmlsloader').length) { 132 $('header #' + self.search_id).append('<span class="mmlsloader"></span>'); 133 } 134 if ($("." + self.result__class).length) { 135 $("." + self.result__class).empty(); 136 } 137 }, 138 success: function(json){ 139 $('header #' + self.search_id + ' .mmlsloader').remove(); 140 if (!$("." + self.result__class).length) { 141 $(thisis).after('<div class="' + self.result__class + '"></div>'); 142 } 143 $(thisis).parent().find("." + self.result__class).empty(); 144 if (json){ 145 if (json['category'] || json['product']){ 146 var i; 147 148 if (json['category']){ 149 for (i in json['category']) { 150 var cname = json['category'][i]['name'].replace(/"/g, '"').replace(/'/g, '"'); 151 $(thisis).parent().find("." + self.result__class).append('<span class="search_sel tocategory" onclick="mm_live_search.goFromMMLiveSearch(\'catalog\', \'' + json['category'][i]['id'] + '\', \'' + cname + '\', \'' + json['category'][i]['href'] + '\')"><div class="im"><img style="' + json['category'][i]['image_style'] + '" src="' + json['category'][i]['image'] + '" /></div><div class="w">' + self.boldQuery(cname, word) + '</div></span>'); 152 } 153 } 154 155 if (json['product']){ 156 for (i in json['product']) { 157 if (json['product'][i]['sendto'] == 'search'){ 158 var pname = json['product'][i]['name'].replace(/"/g, '"').replace(/'/g, '"'); 159 $(thisis).parent().find("." + self.result__class).append('<span class="search_sel toproduct" onclick="mm_live_search.goFromMMLiveSearch(\'product\', \'' + json['product'][i]['id'] + '\', \'' + pname + '\', \'' + json['product'][i]['href'] + '\')"><div class="im"><img style="' + json['product'][i]['image_style'] + '" src="' + json['product'][i]['image'] + '" /></div><div class="w">' + self.boldQuery(pname, word) + '</div><div class="mmls__price">' + json['product'][i]['price'] + '</div></span>'); 160 } 161 } 162 for (i in json['product']) { 163 if (json['product'][i]['sendto'] == 'product'){ 164 var pname = json['product'][i]['name'].replace(/"/g, '"').replace(/'/g, '"'); 165 $(thisis).parent().find("." + self.result__class).append('<span class="search_sel toproduct" onclick="mm_live_search.goFromMMLiveSearch(\'product\', \'' + json['product'][i]['id'] + '\', \'' + pname + '\', \'' + json['product'][i]['href'] + '\')"><div class="im"><img style="' + json['product'][i]['image_style'] + '" src="' + json['product'][i]['image'] + '" /></div><div class="w">' + self.boldQuery(pname, word) + '</div><div class="mmls__price">' + json['product'][i]['price'] + '</div></span>'); 166 } 167 } 168 } 169 $(thisis).parent().find("." + self.result__class).append('<span class="search_sel all_products" onclick="mm_live_search.goFromMMLiveSearch(\'search\', \'\', \'' + word + '\', \'' + url_to_search + '\')">' + json['text_all'] + '</span>'); 170 self.keyClickLiveSearch(thisis); 171 self.height_mmlivesearch(thisis); 172 } else { 173 $(thisis).parent().find("." + self.result__class).append('<span class="no_find">' + json['text_no_find'] + '</span>'); 174 } 175 } 176 } 177 }); 178 } else { 179 self.getMMLiveSearchHistory(thisis); 180 } 181 } 182 183 delay(callback, ms) { 184 var timer = 0; 185 return function() { 186 var context = this, args = arguments; 187 clearTimeout(timer); 188 timer = setTimeout(function () {
189 callback.apply(context, args); 190 }, ms || 0); 191 }; 192 } 193 194 getSearchtyped(){ 195 if(typeof(JsMMSearchPhrase) != "undefined" && JsMMSearchPhrase !== null && JsMMSearchPhrase.length > 0) { 196 var typed = new Typed('.' + this.search_input_class, { 197 strings: JsMMSearchPhrase, 198 startDelay: 1500, 199 typeSpeed: 50, 200 backDelay: 1000, 201 backSpeed: 40, 202 attr: 'placeholder', 203 bindInputFocusEvents: true, 204 loop: true, 205 onDestroy: function (self) { 206 }, 207 }); 208 } 209 } 210 211 getMMLiveSearchHistory(thisis){ 212 let self = this; 213 214 $.ajax({ 215 type: "POST", 216 url: "index.php?route=extension/mmlivesearch/getMMLiveSearchHistory", 217 data:'', 218 dataType: 'json', 219 cache: false, 220 beforeSend: function(){ 221 if ($("." + self.result__class).length) { 222 $("." + self.result__class).remove(); 223 } 224 }, 225 success: function(json){ 226 if (json['success']){ 227 if (json['category'] || json['product'] || json['search']){ 228 229 $(thisis).after('<div class="' + self.result__class + '"></div>'); 230 $(thisis).parent().find("." + self.result__class).append('<div class="title"><strong>' + json['text_history'] + '</strong><a href="javascript:void(0);" class="clearMMLiveSearch" onclick="mm_live_search.clearMMLiveSearch();">' + json['text_clear'] + '</a></div>'); 231 232 var i; 233 234 if (json['category']){ 235 for (i in json['category']) { 236 var cname = json['category'][i]['name'].replace(/"/g, '"').replace(/'/g, '"'); 237 $(thisis).parent().find("." + self.result__class).append('<span class="search_sel history tocategory" onclick="mm_live_search.goFromMMLiveSearch(\'catalog\', \'' + json['category'][i]['id'] + '\', \'' + cname + '\', \'' + json['category'][i]['href'] + '\')"><div class="im"><img style="' + json['category'][i]['image_style'] + '" src="' + json['category'][i]['image'] + '" /></div><div class="w">' + cname + '</div></span>'); 238 } 239 } 240 241 if (json['search']){ 242 for (i in json['search']) { 243 var sname = json['search'][i]['name'].replace(/"/g, '"').replace(/'/g, '"'); 244 $(thisis).parent().find("." + self.result__class).append('<span class="search_sel history tosearch" onclick="mm_live_search.goFromMMLiveSearch(\'search\', \'\', \'' + sname + '\', \'index.php?route=product/search&search=' + sname + '\')"><div class="im"><img style="' + json['search'][i]['image_style'] + '" src="' + json['search'][i]['image'] + '" /></div><div class="w">' + sname + '</div></span>'); 245 } 246 } 247 248 if (json['product']){ 249 for (i in json['product']) { 250 var pname = json['product'][i]['name'].replace(/"/g, '"').replace(/'/g, '"'); 251 $(thisis).parent().find("." + self.result__class).append('<span class="search_sel history toproduct" onclick="mm_live_search.goFromMMLiveSearch(\'product\', \'' + json['product'][i]['id'] + '\', \'' + pname + '\', \'' + json['product'][i]['href'] + '\')"><div class="im"><img style="' + json['product'][i]['image_style'] + '" src="' + json['product'][i]['image'] + '" /></div><div class="w">' + pname + '</div></span>'); 252 } 253 } 254 self.keyClickLiveSearch(thisis); 255 self.height_mmlivesearch(thisis); 256 } 257 } 258 } 259 }); 260 } 261 262 goFromMMLiveSearch(sendto, id, name, href) { 263 $('header input[name=\'' + this.search_input_name + '\']').val(name); 264 265 if (this.goToSearch == 0){ 266 //пиÑем иÑÑоÑÐ¸Ñ 267 $.ajax({ 268 type: "POST", 269 url: "index.php?route=extension/mmlivesearch/mmLiveSearchAddHistory", 270 data: {"id": id, "name": name, "sendto" : sendto, "href" : href}, 271 dataType: 'json', 272 cache: false, 273 beforeSend: function(){ 274 }, 275 success: function(){ 276 } 277 }); 278 this.goToSearch = 1; 279 location = href; 280 } 281 } 282 283 keyClickLiveSearch(thisis){ 284 let self = this; 285 var li; 286 var liSelected; 287 var next; 288 li = $(thisis).parent().find('.' + self.result__class + ' span'); 289 290 $(thisis).keyup(function(e){ 291 if(e.keyCode === 40){ 292 if(liSelected){ 293 liSelected.removeClass('selected'); 294 next = liSelected.next(); 295 if(next.length > 0){ 296 liSelected = next.addClass('selected'); 297 $(self).val($(liSelected).children('.w').text()); 298 }else{ 299 liSelected = li.eq(0).addClass('selected'); 300 $(self).val($(liSelected).children('.w').text()); 301 } 302 }else{ 303 liSelected = li.eq(0).addClass('selected'); 304 $(self).val($(liSelected).children('.w').text()); 305 } 306 }else if(e.keyCode === 38){ 307 if(liSelected){ 308 liSelected.removeClass('selected'); 309 next = liSelected.prev(); 310 if(next.length > 0){ 311 liSelected = next.addClass('selected'); 312 $(self).val($(liSelected).children('.w').text()); 313 }else{
314 liSelected = li.last().addClass('selected'); 315 $(self).val($(liSelected).children('.w').text()); 316 } 317 }else{ 318 liSelected = li.last().addClass('selected'); 319 $(self).val($(liSelected).children('.w').text()); 320 } 321 }else if(e.keyCode === 13){ 322 if ($(thisis).parent().find('.' + self.result__class + ' span').hasClass('selected')){ 323 $(thisis).parent().find('.' + self.result__class + ' span.selected').trigger('click'); 324 } else { 325 var url = $('base').attr('href')+'index.php?route=product/search'; 326 327 var search = $(thisis).val(); 328 //search = search.replace(/[^a-zA-Zа-ÑÐ-ЯÑÐ0-9-. ]/g, ""); 329 330 if (search) { 331 url += '&search=' + encodeURIComponent(search); 332 } 333 334 self.goFromMMLiveSearch('search', '', search, url); 335 } 336 } 337 }); 338 } 339 340 clearMMLiveSearch(){ 341 let self = this; 342 $.ajax({ 343 type: "POST", 344 url: "index.php?route=extension/mmlivesearch/clearMMLiveSearch", 345 data: '', 346 dataType: 'json', 347 cache: false, 348 beforeSend: function(){}, 349 success: function(json){ 350 if (json){ 351 if (json['clear'] == 1){ 352 $("." + self.result__class).remove(); 353 } 354 } 355 } 356 }); 357 } 358 359 height_mmlivesearch(thisis){ 360 var height_mmlivesearch = $(window).height() - 180; 361 $(thisis).parent().find('.' + this.result__class).css('max-height', height_mmlivesearch); 362 } 363} 364 365let mm_live_search = null; 366window.onload = function(){ 367 yandex_speller = null; 368 if (typeof(YandexSpeller) == 'function') { 369 yandex_speller = new YandexSpeller(); 370 } 371 372 mm_live_search = new MMLiveSearch(yandex_speller); 373} 374//mmlivesearch END
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.