PageSourceSearch

https://trendoptom.ru/catalog/view/javascript/mmlivesearch/mmlivesearch.js

js trendoptom.ru collected 2026-10-07 18:59:14 UTC 14,068 bytes, 374 lines download raw bytes

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, '&quot;').replace(/'/g, '&quot;');
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, '&quot;').replace(/'/g, '&quot;');
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, '&quot;').replace(/'/g, '&quot;');
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, '&quot;').replace(/'/g, '&quot;');
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, '&quot;').replace(/'/g, '&quot;');
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, '&quot;').replace(/'/g, '&quot;');
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.