PageSourceSearch

https://steelsolid.ru/media/com_hikashop/js/hikashop.js?v=6522608242115

js steelsolid.ru collected 2026-10-08 15:57:46 UTC 81,622 bytes, 2,437 lines download raw bytes

1/**
2 * @package    HikaShop
3 * @version    6.5.2
4 * @author     hikashop.com
5 * @copyright  (C) 2010-2026 HIKARI SOFTWARE. All rights reserved.
6 * @license    GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
7 */
8(function() {
9
10function preventDefault() { this.returnValue = false; }
11function stopPropagation() { this.cancelBubble = true; }
12
13var Oby = {
14	version: 20171104,
15	ajaxEvents : {},
16
17	hasClass: function(o,n) {
18		if(o.classList && o.classList.contains)
19			return o.classList.contains(n);
20		if(o.className == '' ) return false;
21		var reg = new RegExp("(^|\\s+)"+n+"(\\s+|$)");
22		return reg.test(o.className);
23	},
24	addClass: function(o,n) {
25		if(o.classList && o.classList.add)
26			return o.classList.add(n);
27		if( !this.hasClass(o,n) ) {
28			if( o.className == '' ) {
29				o.className = n;
30			} else {
31				o.className += ' '+n;
32			}
33		}
34	},
35	trim: function(s) {
36		if(s.trim) return s.trim();
37		return (s ? '' + s : '').replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
38	},
39	removeClass: function(e, c) {
40		if(e.classList && e.classList.remove)
41			return e.classList.remove(c);
42		var t = this;
43		if( t.hasClass(e,c) ) {
44			var cn = ' ' + e.className + ' ';
45			e.className = t.trim(cn.replace(' '+c+' ',' '));
46		}
47	},
48	toggleClass: function(e,c) {
49		if(e.classList && e.classList.toggle)
50			return e.classList.toggle(c);
51		var t = this;
52		if( t.hasClass(e,c) ) {
53			return t.removeClass(e,c);
54		}
55		return t.addClass(e,c);
56	},
57	addEvent: function(d,e,f) {
58		if( d.attachEvent )
59			d.attachEvent('on' + e, f);
60		else if (d.addEventListener)
61			d.addEventListener(e, f, false);
62		else
63			d['on' + e] = f;
64		return f;
65	},
66	removeEvent: function(d,e,f) {
67		try {
68			if( d.detachEvent )
69				d.detachEvent('on' + e, f);
70			else if( d.removeEventListener)
71				d.removeEventListener(e, f, false);
72			else
73				d['on' + e] = null;
74		} catch(e) {}
75	},
76	cancelEvent: function(e) {
77		if( !e ) {
78			e = window.event;
79			if( !e )
80				return false;
81		}
82		if(e.stopPropagation)
83			e.stopPropagation();
84		else
85			 e.cancelBubble = true;
86		if( e.preventDefault )
87			e.preventDefault();
88		else
89			e.returnValue = false;
90		return false;
91	},
92	fireEvent: function(obj,e,data) {
93		var d = document, evt = null;
94		if(document.createEvent) {
95			evt = d.createEvent('HTMLEvents');
96			evt.initEvent(e, false, true);
97			if(data) evt.data = data;
98			obj.dispatchEvent(evt);
99			return;
100		}
101		if(data && d.createEventObject) {
102			evt = d.createEventObject();
103			evt.data = data;
104			obj.fireEvent('on'+e, evt);
105			return;
106		}
107		obj.fireEvent('on'+e);
108	},
109	fireAjax: function(name,params) {
110		var t = this, ev, r = null, ret = [];
111		if( t.ajaxEvents[name] === undefined )
112			return false;
113		for(var e in t.ajaxEvents[name]) {
114			if( e == '_id' )
115				continue;
116			ev = t.ajaxEvents[name][e];
117			if(!ev || typeof(ev) != 'function')
118				continue;
119			try {
120				r = ev(params);
121				if(r !== undefined)
122					ret.push(r);
123			}catch(e){}
124		}
125		return ret;
126	},
127	registerAjax: function(name, fct) {
128		var t = this;
129		if(typeof(name) == 'object') {
130			var r = [];
131			for(var k = name.length - 1; k >= 0; k--) {
132				r[r.length] = t.registerAjax(name[k], fct);
133			}
134			return r;
135		}
136		if( t.ajaxEvents[name] === undefined )
137			t.ajaxEvents[name] = {'_id':0};
138		var id = t.ajaxEvents[name]['_id'];
139		t.ajaxEvents[name]['_id'] += 1;
140		t.ajaxEvents[name][id] = fct;
141		return id;
142	},
143	unregisterAjax: function(name, id) {
144		if( t.ajaxEvents[name] === undefined || t.ajaxEvents[name][id] === undefined)
145			return false;
146		t.ajaxEvents[name][id] = null;
147		return true;
148	},
149	ready: function(fct) {
150		var w = window, d = document, t = this;
151		if(d.readyState === "complete") {
152			fct();
153			return;
154		}
155		var done = false, top = true, root = d.documentElement,
156			init = function(e) {
157				if(e.type == 'readystatechange' && d.readyState != 'complete') return;
158				t.removeEvent((e.type == 'load' ? w : d), e.type, init);
159				if(!done && (done = true))
160					fct();
161			},
162			poll = function() {
163				try{ root.doScroll('left'); } catch(e){ setTimeout(poll, 50); return; }
164				init('poll');
165			};
166		if(d.createEventObject && root.doScroll) {
167			try{ top = !w.frameElement; } catch(e){}
168			if(top) poll();
169		}
170		t.addEvent(d,'DOMContentLoaded',init);
171		t.addEvent(d,'readystatechange',init);
172		t.addEvent(w,'load',init);
173	},
174	evalJSON: function(text, secure) {
175		if( typeof(text) != "string" || !text.length) return null;
176		if(JSON !== undefined && typeof(JSON.parse) == 'function') {
177			try { var ret = JSON.parse(text); return ret; } catch(e) {
178				return this.extractJSON(text);
179			}
180		}
181		if(secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(text.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''))) return null;
182		try { var ret = eval('(' + text + ')'); return ret; } catch(e) { }
183		return null;
184	},
185	extractJSON: function(str) {
186		var firstOpen, firstClose, candidate;
187		firstOpen = str.indexOf('{', firstOpen + 1);
188		do {
189			firstClose = str.lastIndexOf('}');
190			if(firstClose <= firstOpen) {
191				return null;
192			}
193			do {
194				candidate = str.substring(firstOpen, firstClose + 1);
195				try {
196					var res = JSON.parse(candidate);
197					return res;
198				}
199				catch(e) {
200					console.log('failed parsing JSON in string below:');
201					console.log(candidate);
202				}
203				firstClose = str.substr(0, firstClose).lastIndexOf('}');
204			} while(firstClose > firstOpen);
205			firstOpen = str.indexOf('{', firstOpen + 1);
206		} while(firstOpen != -1);
207		return null;
208	},
209	getXHR: function() {
210		var xhr = null, w = window;
211		if(w.XMLHttpRequest || w.ActiveXObject) {
212			if(w.ActiveXObject) {
213				try {
214					xhr = new ActiveXObject("Microsoft.XMLHTTP");
215				} catch(e) {}
216			} else
217				xhr = new w.XMLHttpRequest();
218		}
219		return xhr;
220	},
221	xRequest: function(url, options, cb, cbError) {
222		var t = this, xhr = t.getXHR();
223		if(!options) options = {};
224		if(!cb) cb = function(){};
225		options.mode = options.mode || 'GET';
226		options.update = options.update || false;
227		xhr.onreadystatechange = function() {
228			if(xhr.readyState != 4)
229				return;
230			if( xhr.status == 200 || (xhr.status == 0 && xhr.responseText > 0) || !cbError ) {
231				if(cb)
232					cb(xhr,options.params);
233				if(options.update)
234					t.updateElem(options.update, xhr.responseText);
235			} else {
236				cbError(xhr,options.params);
237			}
238		};
239		xhr.open(options.mode, url, true);
240		if(options.mode.toUpperCase() == 'POST' && typeof(options.data) == 'string') {
241			xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
242		}
243		if(typeof Joomla !== 'undefined' && Joomla && Joomla.getOptions) {
244			var csrf = Joomla.getOptions("csrf.token", "");
245			if(csrf) {
246				xhr.setRequestHeader("X-CSRF-Token", csrf);
247			}
248		}
249		xhr.send( options.data );
250	},
251	getFormData: function(target, encoded) {
252		var d = document, ret = {};
253		if(encoded === undefined) encoded = true;
254		if( typeof(target) == 'string' )
255			target = d.getElementById(target);
256		if( target === undefined )
257			target = d;
258		var typelist = ['input','select','textarea'];
259		for(var t in typelist) {
260			if(!typelist.hasOwnProperty(t))
261				continue;
262			t = typelist[t];
263			var inputs = target.getElementsByTagName(t);
264			for(var i = 0; i < inputs.length; i++) {
265				if( !inputs[i].name || inputs[i].disabled )
266					continue;
267				var evalue = inputs[i].value, n = inputs[i].name, etype = '';
268				if( t == 'input' )
269					etype = inputs[i].type.toLowerCase();
270				if( (etype == 'radio' || etype == 'checkbox') && !inputs[i].checked )
271					evalue = null;
272				if(t == 'select' && inputs[i].multiple) {
273					for(var k = inputs[i].options.length - 1; k >= 0; k--) {
274						if(!inputs[i].options[k].selected)
275							continue;
276						//if( ret != '' ) ret += '&';
277						//ret += encodeURI(inputs[i].name) + '=' + encodeURIComponent(inputs[i].options[k].value);
278						if(ret.hasOwnProperty(n)) {
279							if(typeof(ret[n]) != 'object')
280								ret[n] = [ ret[n] ];
281							ret[n][ ret[n].length ] = inputs[i].options[k].value;
282						} else
283							ret[ n ] = inputs[i].options[k].value;
284						evalue = null;
285					}
286				}
287				if( (etype != 'file' && etype != 'submit') && evalue != null ) {
288					//if( ret != '' ) ret += '&';
289					//ret += encodeURI(inputs[i].name) + '=' + encodeURIComponent(evalue);
290
291					if(ret.hasOwnProperty(n)) {
292						if(typeof(ret[n]) != 'object')
293							ret[n] = [ ret[n] ];
294						ret[n][ ret[n].length ] = evalue;
295					} else
296						ret[ n ] = evalue;
297				}
298			}
299		}
300		// Collect orphaned inputs associated with the form via the HTML form attribute
301		// (these are outside the form element in the DOM but linked to it by form="formId")
302		if(target && target.id) {
303			var scope = target.closest('.hikashop_product_page') || target.parentNode;
304			var orphanSelector = 'input[form="'+target.id+'"], select[form="'+target.id+'"], textarea[form="'+target.id+'"]';
305			var orphans = scope.querySelectorAll(orphanSelector);
306			for(var oi = 0; oi < orphans.length; oi++) {
307				if(!orphans[oi].name || orphans[oi].disabled)
308					continue;
309				var n = orphans[oi].name;
310				if(ret.hasOwnProperty(n))
311					continue;
312				var etype = orphans[oi].tagName.toLowerCase() == 'input' ? orphans[oi].type.toLowerCase() : '';
313				if(etype == 'file' || etype == 'submit')
314					continue;
315				if((etype == 'radio' || etype == 'checkbox') && !orphans[oi].checked)
316					continue;
317				ret[n] = orphans[oi].value;
318			}
319		}
320		if(encoded)
321			return this.encodeFormData(ret);
322		return ret;
323	},
324	encodeFormData: function(data) {
325		var ret = '', v = null;
326		if(typeof(data) == "string")
327			return data;
328		for(var k in data) {
329			if(!data.hasOwnProperty(k))
330				continue;
331			v = data[k];
332			if(typeof(v) == 'object') {
333				for(var i in v) {
334					if(!v.hasOwnProperty(i))
335						continue;
336					if( ret != '' ) ret += '&';
337					ret += encodeURI(k) + '=' + encodeURIComponent(v[i]);
338				}
339			} else {
340				if( ret != '' ) ret += '&';
341				ret += encodeURI(k) + '=' + encodeURIComponent(v);
342			}
343		}
344		return ret;
345	},
346	updateElem: function(elem, data) {
347		var d = document, scripts = [];
348		if( typeof(elem) == 'string' )
349			elem = d.getElementById(elem);
350		var text = data.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(all, code){
351			if(all.indexOf('type="application/json"')>=0 || all.indexOf('type="application/ld+json"')>=0)
352				return all;
353			scripts.push(code);
354			return '';
355		});
356		elem.innerHTML = text;
357		if( scripts.length ) {
358			scripts.forEach(function(code){
359				var script = d.createElement('script');
360				script.setAttribute('type', 'text/javascript');
361				script.text = code;
362				try {
363					d.head.appendChild(script);
364					d.head.removeChild(script);
365				} catch(e) {}
366			});
367		}
368	},
369	ease: function(v) {
370		return 1+Math.pow(v-1,3);
371	},
372	easeInOut: function(t,s,dt,du) {
373		return dt/2 * (1 - Math.cos(Math.PI*t/du)) + s;
374	},
375	scrollTo: function(name, anim, visible, margin) {
376		var t = this, d = document, w = window,
377			elem = d.getElementById(name);
378		if(!elem)
379			return;
380		if(margin === undefined) margin = 0;
381		if(!anim) {
382			window.scrollTo(0, elem.offsetTop - margin);
383			return;
384		}
385		if( t.anim && t.anim.timer )
386			clearInterval( t.anim.timer );
387		t.anim = { timer:null, s:null, dt:0, du:150, t:0, inc:10 };
388		if( w.scrollY )
389			t.anim.s = w.scrollY;
390		else if( d.documentElement.scrollTop )
391			t.anim.s = d.documentElement.scrollTop;
392		else
393			t.anim.s = d.body.scrollTop;
394		if(visible) {
395			if( d.documentElement.scrollTop )
396				h = d.documentElement.clientHeight;
397			else
398				h = d.body.clientHeight;
399			if(t.anim.s <= elem.offsetTop && (t.anim.s + h - 150) > elem.offsetTop)
400				return;
401		}
402		t.anim.dt = elem.offsetTop - t.anim.s - margin;
403		var o = this;
404		t.anim.timer = setInterval( function() {
405			var a = o.anim;
406			if( !a || !a.timer )
407				return;
408			a.t += a.inc;
409			if( a.t < a.du ) {
410				window.scrollTo(0, o.easeInOut(a.t, a.s, a.dt, a.du), false, margin);
411			} else {
412				window.scrollTo(0, a.s + a.dt, false, margin);
413				clearInterval(a.timer);
414				a.timer = null;
415			}
416		}, t.anim.inc );
417	}
418};
419if((typeof(window.Oby) == 'undefined') || window.Oby.version < Oby.version) {
420	window.Oby = Oby;
421	window.obscurelighty = Oby;
422}
423
424var oldHikaShop = window.hikashop || hikashop;
425
426var hikashop = {
427	translations: {},
428	translations_url: null,
429	submitFct: null,
430	filterRefreshTimer: false,
431
432	setCookie: function (name,value,delay) {
433		document.cookie = name + "=" + (value || "")  +  "; expires=" + delay + "; path=/";
434   	},
435	submitBox: function(data) {
436		var t = this, d = document, w = window;
437		if( t.submitFct ) {
438			try {
439				t.submitFct(data);
440			} catch(err) {}
441		}
442		t.closeBox();
443	},
444	deleteId: function(id) {
445		var t = this, d = document, el = id;
446		if( typeof(id) == "string") {
447			el = d.getElementById(id);
448		}
449		if(!el)
450			return;
451		el.parentNode.removeChild(el);
452	},
453	dup: function(tplName, htmlblocks, id, extraData, appendTo) {
454		var d = document, tplElem = d.getElementById(tplName);
455		if(!tplElem) return;
456		var container = tplElem.parentNode;
457		elem = tplElem.cloneNode(true);
458		if(!appendTo) {
459			container.insertBefore(elem, tplElem);
460		} else {
461			if(typeof(appendTo) == "string")
462				appendTo = d.getElementById(appendTo);
463			appendTo.appendChild(elem);
464		}
465		elem.style.display = "";
466		elem.id = '';
467		if(id)
468			elem.id = id;
469		for(var k in htmlblocks) {
470			elem.innerHTML = elem.innerHTML.replace(new RegExp("{"+k+"}","g"), htmlblocks[k]);
471			elem.innerHTML = elem.innerHTML.replace(new RegExp("%7B"+k+"%7D","g"), htmlblocks[k]);
472		}
473		if(extraData) {
474			for(var k in extraData) {
475				elem.innerHTML = elem.innerHTML.replace(new RegExp('{'+k+'}','g'), extraData[k]);
476				elem.innerHTML = elem.innerHTML.replace(new RegExp('%7B'+k+'%7D','g'), extraData[k]);
477			}
478		}
479		return elem;
480	},
481	deleteRow: function(id) {
482		var t = this, d = document, el = id;
483		if( typeof(id) == "string") {
484			el = d.getElementById(id);
485		} else {
486			while(el != null && el.tagName.toLowerCase() != 'tr') {
487				el = el.parentNode;
488			}
489		}
490		if(!el)
491			return;
492		var table = el.parentNode;
493		table.removeChild(el);
494		if( table.tagName.toLowerCase() == 'tbody' )
495			table = table.parentNode;
496		t.cleanTableRows(table);
497		return;
498	},
499	dupRow: function(tplName, htmlblocks, id, extraData) {
500		var d = document, tplLine = d.getElementById(tplName),
501				tableUser = tplLine.parentNode;
502		if(!tplLine) return;
503		trLine = tplLine.cloneNode(true);
504		tableUser.insertBefore(trLine, tplLine);
505		trLine.style.display = "";
506		trLine.id = "";
507		if(id)
508			trLine.id = id;
509		for(var i = tplLine.cells.length - 1; i >= 0; i--) {
510			if(trLine.cells[i]) {
511				for(var k in htmlblocks) {
512					if(!htmlblocks.hasOwnProperty(k))
513						continue;
514					trLine.cells[i].innerHTML = trLine.cells[i].innerHTML.replace(new RegExp("{"+k+"}","g"), htmlblocks[k]);
515					trLine.cells[i].innerHTML = trLine.cells[i].innerHTML.replace(new RegExp("%7B"+k+"%7D","g"), htmlblocks[k]);
516				}
517				if(extraData) {
518					for(var k in extraData) {
519						if(!extraData.hasOwnProperty(k))
520							continue;
521						trLine.cells[i].innerHTML = trLine.cells[i].innerHTML.replace(new RegExp('{'+k+'}','g'), extraData[k]);
522						trLine.cells[i].innerHTML = trLine.cells[i].innerHTML.replace(new RegExp('%7B'+k+'%7D','g'), extraData[k]);
523					}
524				}
525			}
526		}
527		if(tplLine.className == "row0") tplLine.className = "row1";
528		else if(tplLine.className == "row1") tplLine.className = "row0";
529		return trLine;
530	},
531	cleanTableRows: function(id) {
532		var d = document, el = id;
533		if(typeof(id) == "string")
534			el = d.getElementById(id);
535		if(el == null || el.tagName.toLowerCase() != 'table')
536			return;
537
538		var k = 0, c = '', line = null, lines = el.getElementsByTagName('tr');
539		for(var i = 0; i < lines.length; i++) {
540			line = lines[i];
541			if( line.style.display != "none") {
542				c = ' '+line.className+' ';
543				if( c.indexOf(' row0 ') >= 0 || c.indexOf(' row1 ') >= 0 ) {
544					line.className = c.replace(' row'+(1-k)+' ', ' row'+k+' ').replace(/^\s*|\s*$/g, '');
545					k = 1 - k;
546				}
547			}
548		}
549	},
550	checkRow: function(id) {
551		var t = this, d = document, el = id;
552		if(typeof(id) == "string")
553			el = d.getElementById(id);
554		if(el == null || el.tagName.toLowerCase() != 'input')
555			return;
556		if(this.clicked) {
557			this.clicked = null;
558			t.isChecked(el);
559			return;
560		}
561		el.checked = !el.checked;
562		t.isChecked(el);
563	},
564	isChecked: function(id,cancel) {
565		var d = document, el = id;
566		if(typeof(id) == "string")
567			el = d.getElementById(id);
568		if(el == null || el.tagName.toLowerCase() != 'input')
569			return;
570		if(el.form.boxchecked) {
571			if(el.checked)
572				el.form.boxchecked.value++;
573			else
574				el.form.boxchecked.value--;
575		}
576	},
577	checkAll: function(checkbox, stub) {
578		stub = stub || 'cb';
579		if(!checkbox.form)
580			return false;
581		var o = window.Oby, cb = checkbox.form, c = 0;
582		for(var i = 0, n = cb.elements.length; i < n; i++) {
583			var e = cb.elements[i];
584			if (e != checkbox && e.type == checkbox.type && ((stub && e.id.indexOf(stub) == 0) || !stub)) {
585				e.checked = checkbox.checked;
586				o.fireEvent(e, 'change');
587				o.fireEvent(e, 'click');
588				c += (e.checked == true ? 1 : 0);
589			}
590		}
591		if (cb.boxchecked) {
592			cb.boxchecked.value = c;
593		}
594		return true;
595	},
596	submitform: function(task, form, extra) {
597		var d = document;
598		if(typeof form == 'string') {
599			var f = d.getElementById(form);
600			if(!f)
601				f = d.forms[form];
602			if(!f)
603				return true;
604			form = f;
605		}
606		if(task) {
607			form.task.value = task;
608		}
609		if(typeof form.onsubmit == 'function')
610			form.onsubmit();
611		form.submit();
612		return false;
613	},
614	get: function(elem, target) {
615		window.hikashop.xRequest(elem.getAttribute('href'), {update: target});
616		return false;
617	},
618	form: function(elem, target) {
619		var data = window.Oby.getFormData(target);
620		window.hikashop.xRequest(elem.getAttribute('href'), {update: target, mode: 'POST', data: data});
621		return false;
622	},
623	openBox: function(elem, url, jqmodal) {
624		var w = window;
625		if(typeof(elem) == "string")
626			elem = document.getElementById(elem);
627		if(!elem)
628			return false;
629		try {
630			var hkpopup = elem.getAttribute('data-hk-popup');
631			if(jqmodal === undefined) {
632				jqmodal = false;
633				var test_rel = elem.getAttribute('rel');
634				if(test_rel == null && hkpopup == null && typeof(jQuery) != "undefined")
635					jqmodal = true;
636			}
637			if(hkpopup) {
638				var fct = this['openBox_' + hkpopup.toLowerCase()];
639				if(fct) {
640					var ret = fct(elem, url);
641					if(ret == true)
642						return false;
643				}
644			}
645			if(!jqmodal && this.openBox_squeezebox(elem, url))
646				return false;
647			if(this.openBox_bootstrap(elem, url))
648				return false;
649			console.log('no popup system found');
650		} catch(e) { console.log(e); }
651		return false;
652	},
653	openBox_squeezebox: function(elem, url) {
654		if(window.SqueezeBox === undefined)
655			return false;
656		if(url !== undefined && url !== null)
657			elem.href = url;
658		if(!elem.rel && elem.getAttribute('data-hk-popup') == 'squeezebox')
659			elem.rel = elem.getAttribute('data-squeezebox');
660		if(window.SqueezeBox.open !== undefined)
661			SqueezeBox.open(elem, {parse: 'rel'});
662		else if(window.SqueezeBox.fromElement !== undefined)
663			SqueezeBox.fromElement(elem);
664		setTimeout(function(){
665			jQuery('#sbox-content').find('iframe').attr('name', 'hikashop_popup_iframe');
666		},500);
667		return true;
668	},
669	openBox_bootstrap: function(elem, url) {
670		if(typeof(jQuery) == "undefined")
671			return false;
672		var id = elem.getAttribute('id');
673		jQuery('#modal-' + id).modal('show');
674		if(!url)
675			return true;
676		if(document.getElementById('modal-' + id + '-container'))
677			jQuery('#modal-' + id + '-container').find('iframe').attr('src', url);
678		else
679			jQuery('#modal-' + id).find('iframe').attr('src', url);
680		jQuery('#modal-' + id).find('iframe').attr('name', 'hikashop_popup_iframe');
681		return true;
682	},
683	openBox_vex: function(elem, url) {
684		if(typeof(vex) == "undefined")
685			return false;
686		var href = elem.href || null;
687		if(url !== undefined && url !== null)
688			href = url;
689		if(!href) href = elem.getAttribute('href');
690		settings = window.Oby.evalJSON(elem.getAttribute('data-vex'));
691		var triggerEl = elem;
692		if(settings.x && settings.y && href) {
693			settings.content = '<iframe style="border:0;margin:0;padding:0;" name="hikashop_popup_iframe" width="'+settings.x+'px" height="'+settings.y+'px" src="'+href+'"></iframe>';
694			var origAfterOpen = settings.afterOpen || null;
695			settings.afterOpen = function(context) {
696				if(origAfterOpen) origAfterOpen(context);
697				context.width(settings.x + 'px');
698				hikashop.vexA11y(context, triggerEl);
699			};
700		}
701		settings.beforeClose = function() {
702			if(triggerEl && triggerEl.focus) triggerEl.focus();
703		};
704		vex.defaultOptions.className = 'vex-theme-default';
705		vex.open( settings );
706
707		// Fix for CSS filter on body (e.g. Joomla a11y_contrast) breaking position:fixed.
708		// When a CSS filter is set on the body, position:fixed elements are positioned
709		// relative to the body instead of the viewport. We compensate by converting
710		// the popup to position:absolute and setting its top to the current scroll position.
711		var bodyStyle = window.getComputedStyle(document.body);
712		if(bodyStyle.filter && bodyStyle.filter !== 'none') {
713			var vexEls = document.querySelectorAll('.vex');
714			for(var vi = 0; vi < vexEls.length; vi++) {
715				vexEls[vi].style.position = 'absolute';
716				vexEls[vi].style.top = window.scrollY + 'px';
717				vexEls[vi].style.height = window.innerHeight + 'px';
718				// Also fix the overlay inside
719				var overlay = vexEls[vi].querySelector('.vex-overlay');
720				if(overlay) {
721					overlay.style.position = 'absolute';
722					overlay.style.top = '0';
723					overlay.style.height = '100%';
724				}
725			}
726		}
727
728		return true;
729	},
730	vexA11y: function(context, triggerEl) {
731		var el = context.get(0) || context[0];
732		if(!el) return;
733		var content = el.querySelector('.vex-content');
734		if(!content) return;
735		// ARIA attributes
736		content.setAttribute('role', 'dialog');
737		content.setAttribute('aria-modal', 'true');
738		var title = triggerEl ? (triggerEl.getAttribute('title') || triggerEl.textContent || '') : '';
739		if(title) content.setAttribute('aria-label', title.trim().substring(0, 100));
740		// Make close button accessible
741		var closeBtn = content.querySelector('.vex-close');
742		if(closeBtn) {
743			closeBtn.setAttribute('role', 'button');
744			closeBtn.setAttribute('tabindex', '0');
745			closeBtn.setAttribute('aria-label', window.hikashop.translations['HIKA_CLOSE'] || 'Close');
746			closeBtn.addEventListener('keydown', function(e) {
747				if(e.keyCode === 13 || e.keyCode === 32) { e.preventDefault(); this.click(); }
748			});
749		}
750		// Focus trap
751		content.addEventListener('keydown', function(e) {
752			if(e.keyCode !== 9) return;
753			var focusable = content.querySelectorAll('a[href], button, textarea, input, select, iframe, [tabindex]:not
753([tabindex="-1"])');
754			if(!focusable.length) return;
755			var first = focusable[0], last = focusable[focusable.length - 1];
756			if(e.shiftKey) {
757				if(document.activeElement === first || document.activeElement === content) { e.preventDefault(); last.focus(); }
758			} else {
759				if(document.activeElement === last) { e.preventDefault(); first.focus(); }
760			}
761		});
762		// Focus the first focusable element
763		var firstFocusable = content.querySelector('iframe, button, [tabindex]:not([tabindex="-1"]), a[href], input, select, textarea');
764		if(firstFocusable) firstFocusable.focus();
765	},
766	closeBox: function(parent) {
767		var d = document, w = window;
768		if(parent) {
769			d = window.parent.document;
770			w = window.parent;
771		}
772		try {
773			var e = d.getElementById('sbox-window');
774			if(e && typeof(e.close) != "undefined") {
775				e.close();
776			} else if(typeof(w.jQuery) != "undefined" && w.jQuery('div.modal.in') && w.jQuery('div.modal.in').hasClass('in')) {
777				w.jQuery('div.modal.in').modal('hide');
778			} else if(typeof(vex) != 'undefined' && vex.close && vex.close() === true) {
779				return;
780			} else if(w.SqueezeBox !== undefined) {
781				w.SqueezeBox.close();
782			}
783		} catch(err) {}
784	},
785	submitPopup: function(id, task, form) {
786		var d = document, t = this, el = d.getElementById('modal-'+id+'-iframe');
787		if(!el) {
788			if(document.getElementById('modal-' + id + '-container'))
789				el = jQuery('#modal-' + id + '-container').find('iframe').get(0);
790			else
791				el = jQuery('#modal-' + id).find('iframe').get(0);
792		}
793		if(el && el.contentWindow.hikashop) {
794			if(task === undefined) task = null;
795			if(form === undefined) form = 'adminForm';
796			el.contentWindow.hikashop.submitform(task, form);
797		}
798		return false;
799	},
800	tabSelect: function(m,c,id) {
801		var d = document, sub = null;
802		if(typeof m == 'string')
803			m = d.getElementById(m);
804		if(!m) return;
805		if(typeof id == 'string')
806			id = d.getElementById(id);
807		sub = m.getElementsByTagName('div');
808		if(sub) {
809			for(var i = sub.length - 1; i >= 0; i--) {
810				if(sub[i].getAttribute('class') == c) {
811					sub[i].style.display = 'none';
812				}
813			}
814		}
815		if(id) id.style.display = '';
816	},
817	changeState: function(el, id, url) {
818		var d = document;
819		if(!d.getElementById(id + '_container'))
820			return false;
821		var mainDiv = el.closest('.hikashop_checkout_address');
822		if(mainDiv)
823			window.checkout.setLoading(mainDiv, true, true);
824		window.Oby.xRequest(url, null, function(xhr){
825			var w = window;
826			w.hikashop.updateElem(id + '_container', xhr.responseText);
827			var defaultVal = '', defaultValInput = d.getElementById(id + '_default_value'), stateSelect = d.getElementById(id);
828			if(defaultValInput) { defaultVal = defaultValInput.value; }
829			if(stateSelect && w.hikashop.optionValueIndexOf(stateSelect.options, defaultVal) >= 0)
830				stateSelect.value = defaultVal;
831			if(typeof(jQuery) != "undefined" && jQuery().chosen) { jQuery('#'+id).chosen(); }
832			if(mainDiv)
833				window.checkout.setLoading(mainDiv, false);
834			w.Oby.fireAjax('hikashop.stateupdated', {id: id, elem: stateSelect});
835		});
836	},
837	optionValueIndexOf: function(options, value) {
838		for(var i = options.length - 1; i >= 0; i--) {
839			if(options[i].value == value)
840				return i;
841		}
842		return -1;
843	},
844	getOffset: function(el) {
845		var x = 0, y = 0;
846		while(el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop )) {
847			x += el.offsetLeft - el.scrollLeft;
848			y += el.offsetTop - el.scrollTop;
849			el = el.offsetParent;
850		}
851		return { top: y, left: x };
852	},
853	dataStore: function(name, value) {
854		if(localStorage) {
855			localStorage.setItem(name, value);
856		} else {
857			var expire = new Date(); expire.setDate(expire.getDate() + 5);
858			document.cookie = name+"="+value+"; expires="+expire;
859		}
860	},
861	dataGet: function(name) {
862		if(localStorage) {
863			return localStorage.getItem(name);
864		}
865		if(document.cookie.length > 0 && document.cookie.indexOf(name+"=") != -1) {
866			var s = name+"=", o = document.cookie.indexOf(s) + s.length, e = document.cookie.indexOf(";",o);
867			if(e == -1) e = document.cookie.length;
868			return unescape(document.cookie.substring(o, e));
869		}
870		return null;
871	},
872	setArrayDisplay: function(fields, displayValue) {
873		var d = document, e = null;
874		if(displayValue === true) displayValue = '';
875		if(displayValue === false) displayValue = 'none';
876		for(var i = 0; i < fields.length; i++) {
877			e = d.getElementById(fields[i]);
878			if(e) e.style.display = displayValue;
879		}
880	},
881	ready: function(fct) {
882		var w = window, d = w.document;
883		if(d.readyState === "complete") {
884			fct();
885			return;
886		}
887		if(w.jQuery !== undefined) {
888			jQuery(fct);
889		} else if(window.addEvent) {
890			w.addEvent("domready", fct);
891		} else
892			w.Oby.ready(fct);
893	},
894	noChzn: function() {
895		if(!window.jQuery)
896			return false;
897		jQuery('.no-chzn').each(function(i,el) {
898			var id = el.getAttribute('id'), chzn = null;
899			if(id) {
900				id = id.replace('{','_').replace('}','_');
901				chzn = jQuery('#'+id+'_chzn');
902			} else {
903				chzn = el.nextSibling;
904			}
905			if(chzn) chzn.remove();
906			jQuery(el).removeClass('chzn-done').show();
907		});
908		return true;
909	},
910	switchTab: function(el) {
911		if(!el || !el.parentNode || !el.parentNode.parentNode) return false;
912		var d = document, w = window, o = w.Oby,
913			c = el.parentNode.parentNode,
914			r = c.getAttribute('rel'),
915			current = el.getAttribute('rel'),
916			dest = null;
917		if(!r || r.substring(0,5) != 'tabs:') return false;
918		if(current.substring(0,4) != 'tab:') return false;
919		var id = r.substring(5),
920			tabs = c.childNodes;
921		current = current.substring(4);
922		dest = d.getElementById(id + current);
923		if(!dest) return false;
924		for(var k = 0; k < tabs.length; k++) {
925			if(!tabs[k] || tabs[k].nodeName.toLowerCase() != 'li') continue;
926			var i = 0, l = tabs[k].childNodes[i], lr = null;
927			while(l.nodeName.toLowerCase() != 'a' && i < tabs[k].childNodes.length)
928				l = tabs[k].childNodes[++i];
929			if(l.nodeName.toLowerCase() == 'a')
930				lr = l.getAttribute('rel');
931			if(!lr || lr.substring(0,4) != 'tab:')
932				continue;
933			var lid = lr.substring(4);
934			if(lid == current) continue;
935			o.removeClass(tabs[k], 'active');
936			var ld = d.getElementById(id + lid);
937			if(ld) ld.style.display = 'none';
938		}
939		dest.style.display = '';
940		o.addClass(el.parentNode, 'active');
941		el.blur();
942		return false;
943	},
944	dlTitle: function(parent) {
945		var t = this, d = document, w = window;
946		if(parent && typeof(parent) == 'string')
947			parent = d.getElementById(parent);
948		if(!parent)
949			parent = d;
950		var dt = parent.getElementsByTagName('dt'), val = null,
951			hkTip = (typeof(hkjQuery) != "undefined" && hkjQuery().hktooltip);
952		for(var i = 0; i < dt.length; i++) {
953			if(dt[i].offsetWidth === 0) {
954				dt[i].dlTitleFct = function(evt){
955					t.dlTitle(this.parentNode);
956					if(hkTip)
957						hkjQuery(this).hktooltip('show');
958					this.removeEventListener('mouseover', this.dlTitleFct);
959					this.dlTitleFct = null;
960				};
961				dt[i].addEventListener('mouseover', dt[i].dlTitleFct);
962			}
963			if(dt[i].offsetWidth < dt[i].scrollWidth && !dt[i].getAttribute('title')) {
964				val = (dt[i].innerText !== undefined) ? dt[i].innerText : dt[i].textContent;
965
966				if(hkTip) {
967					dt[i].setAttribute('data-title', val);
968					hkjQuery(dt[i]).hktooltip({"html": true,"container": "body"});
969				} else
970					dt[i].setAttribute('title', val);
971			}
972		}
973	},
974	checkConsistency: function() {
975		if(!document.querySelectorAll)
976			return;
977		var s = null, elems = null,
978			parents = document.querySelectorAll('[data-consistencyheight]');
979		if(!parents || !parents.length)
980			return;
981		for(var i = parents.length - 1; i >= 0; i--) {
982			s = parents[i].getAttribute('data-consistencyheight');
983			if(s == '' || s == 'true')
984				continue;
985			var reg = new RegExp('^\.[-_a-z0-9]+$', 'i');
986			if(reg.test(s) && document.getElementsByClassName)
987				elems = parents[i].getElementsByClassName(s.substring(1));
988			else
989				elems = parents[i].querySelectorAll(s);
990			if(!elems || !elems.length)
991				continue;
992			if(this.setConsistencyHeight(elems, 'min') === false)
993				continue;
994			parents[i].setAttribute('data-consistencyheight-done', s);
995			parents[i].removeAttribute('data-consistencyheight');
996		}
997	},
998	setConsistencyHeight: function(elems, mode) {
999		if(!elems || !elems.length || elems.length == 0)
1000			return;
1001		var maxHeight = 0, cpt = 0, h = 0, w = window;
1002		for(var i = elems.length - 1; i >= 0; i--) {
1003			if(!elems[i].offsetParent)
1004				continue;
1005			try {
1006				h = parseFloat( w.getComputedStyle(elems[i], '').getPropertyValue('height') );
1007				h = Math.ceil(h);
1008			} catch(e) {
1009				h = NaN;
1010			}
1011			if(isNaN(h))
1012				h = (elems[i].currentStyle ? elems[i].currentStyle.height : elems[i].clientHeight);
1013
1014			if(maxHeight > 0 && h < maxHeight) {
1015				cpt++;
1016			} else if(h > maxHeight) {
1017				maxHeight = h;
1018				cpt++;
1019			}
1020		}
1021		if(maxHeight <= 0)
1022			return false;
1023
1024		if(cpt <= 1)
1025			return;
1026		for(var i = elems.length - 1; i >= 0; i--) {
1027			if(mode !== undefined && mode == 'min')
1028				elems[i].style.minHeight = maxHeight + 'px';
1029			else
1030				elems[i].style.height = maxHeight + 'px';
1031		}
1032	},
1033	refreshFilters: function (el, skipSelf) {
1034		"use strict";
1035		var d = document, t = this, o = window.Oby,
1036		container = null, data = null, containerName = el.getAttribute('data-container-div');
1037
1038		if(containerName)
1039			container = d.forms[containerName];
1040
1041		if(!container)
1042			return false;
1043
1044		var url = container.getAttribute('action');
1045		var scrollToTop = container.getAttribute('data-scroll');
1046
1047		// delay timer to avoid too many ajax calls
1048		if(t.filterRefreshTimer !== false) clearTimeout(t.filterRefreshTimer);
1049		t.filterRefreshTimer = setTimeout(function() {
1050
1051			data = o.getFormData(container);
1052			data += '&tmpl=raw';
1053			o.xRequest(url, {mode:'POST', data: data}, function(xhr) {
1054				var resp = o.evalJSON(xhr.responseText);
1055
1056				if(resp.newURL) {
1057					var urlInHistory = resp.newURL.replace('tmpl=raw&', '', 'g').replace('tmpl=component&', '', 'g').replace('filter=1&', '', 'g').replace('&tmpl=raw', '', 'g').replace('&tmpl=component', '', 'g').replace('&filter=1', '', 'g');
1058					window.history.pushState(data, d.title, urlInHistory);
1059
1060					window.addEventListener('popstate', function(e) {
1061						if(window.location.href.includes('hikashop_url_reload=1')) {
1062							window.location.href.replace('&hikashop_url_reload=1','').reload();
1063						}
1064					});
1065				}
1066
1067				var refreshAreas = document.querySelectorAll('.filter_refresh_div');
1068
1069				var triggers = o.fireAjax('filters.update', {el: el, refreshAreas : refreshAreas, resp: resp});
1070				if(triggers !== false && triggers.length > 0)
1071					return true;
1072
1073				var refreshUrl = null;
1074				t.refreshCounter = 0;
1075				for(let i = 0; i < refreshAreas.length; i++) {
1076					var currentArea = refreshAreas[i];
1077					if(skipSelf && currentArea.querySelector('#'+el.id))
1078						continue;
1079
1080					if(resp.newURL && currentArea.getAttribute('data-use-url')) {
1081						refreshUrl = resp.newURL;
1082					} else {
1083						refreshUrl = currentArea.getAttribute('data-refresh-url');
1084						if(refreshUrl && resp.params) {
1085							refreshUrl += '&' + resp.params + '&return_url=' + encodeURIComponent(window.location.href);
1086						}
1087					}
1088					if(!refreshUrl)
1089						continue;
1090					t.refreshCounter++;
1091					var className = currentArea.getAttribute('data-refresh-class');
1092					if(className) o.addClass(currentArea, className);
1093					t.refreshOneArea(refreshUrl, currentArea, el, refreshAreas, resp);
1094				}
1095
1096				if(scrollToTop) {
1097					window.hikashop.smoothScroll();
1098				}
1099			});
1100			t.filterRefreshTimer = false;
1101		}, 300);
1102		return false;
1103	},
1104	smoothScroll: function(target) {
1105		var target = document.querySelector('div[id^="hikashop_category_information_menu_"]');
1106		if(!target)
1107			return;
1108		var currentScroll = document.documentElement.scrollTop || document.body.scrollTop;
1109		if (currentScroll > target.offsetTop) {
1110			window.requestAnimationFrame(window.hikashop.smoothScroll);
1111			window.scrollTo (target.offsetTop, currentScroll - (currentScroll/5));
1112		}
1113	},
1114	refreshOneArea: function(refreshUrl, currentArea, el, refreshAreas, resp) {
1115		var d = document, t = this, o = window.Oby;
1116		o.xRequest(refreshUrl, {mode:'GET'}, function (xhr2) {
1117			var div = d.createElement('div');
1118			var scripts = [];
1119			var response = xhr2.responseText;
1120			// When SEF or a proxy strips tmpl=raw, the response is the whole page with
1121			// every module instead of the raw block. Detect that so we inject only the
1122			// refreshed block and run only its own scripts: re-running the whole page's
1123			// template and third-party scripts after load blanks the page.
1124			var isFullPage = /<!DOCTYPE|<html[\s>]|<body[\s>]/i.test(response);
1125
1126			var body = /<body.*?>([\s\S]*)<\/body>/i.exec(response);
1127			body = body ? body[1] : response;
1128
1129			if(isFullPage) {
1130				// Parse detached (innerHTML never executes scripts), then keep only the
1131				// scripts that belong to the block being refreshed.
1132				div.innerHTML = body;
1133				var block = (currentArea && currentArea.id) ? div.querySelector('#' + currentArea.id) : null;
1134				if(!block)
1135					block = div.querySelector('.filter_refresh_div');
1136				if(block) {
1137					var blockScripts = block.querySelectorAll('script');
1138					for(var s = 0; s < blockScripts.length; s++) {
1139						var sn = blockScripts[s], stype = sn.getAttribute('type') || '';
1140						if(!sn.getAttribute('src') && stype.indexOf('application/json') == -1 && stype.indexOf('application/ld+json') == -1)
1141							scripts.push(sn.textContent);
1142						sn.parentNode.removeChild(sn);
1143					}
1144				}
1145			} else {
1146				// Raw block: strip and run every script it carries, as before.
1147				var text = body.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(all, code){
1148					if(all.indexOf('type="application/json"') != -1)
1149						return '';
1150					if(all.indexOf('type="application/ld+json"') != -1)
1151						return '';
1152					scripts.push(code);
1153					return '';
1154				});
1155				window.hikashop.updateElem(div, text);
1156			}
1157
1158			var newElem = (currentArea && currentArea.id) ? div.querySelector('#' + currentArea.id) : null;
1159			if(!newElem)
1160				newElem = div.querySelector('.filter_refresh_div');
1161
1162			// to avoid scroll in chrome
1163			setTimeout(function(){
1164				if(!currentArea) {
1165					t.refreshCounter--;
1166					return;
1167				}
1168				var className = currentArea.getAttribute('data-refresh-class');
1169				if(className) o.removeClass(currentArea, className);
1170				if(!newElem) {
1171					t.refreshCounter--;
1172					return;
1173				}
1174				var parentNode = currentArea.parentNode;
1175				if(!parentNode) {
1176					t.refreshCounter--;
1177					return;
1178				}
1179				parentNode.replaceChild(newElem, currentArea);
1180				if( scripts.length ) {
1181					scripts.forEach(function(code){
1182						var injectedCode = code.replaceAll('let jch_', 'jch_').replaceAll('const jch', 'window.hikashop.jch');
1183						injectedCode = injectedCode.replace(/(^|[;{}\n)])([ \t]*)(const|let|class)([ \t]+)([A-Za-z_$][\w$]*)/g, function(m, pre, ws, kw, sp, name) {
1184							var declared = false;
1185							try { (0, eval)(name); declared = true; }
1186							catch (err) { declared = !(err instanceof ReferenceError); }
1187							if(!declared)
1188								return m;
1189							return pre + ws + 'window.hikashop.' + name + (kw === 'class' ? ' = class' : '');
1190						});
1191						// Run each inline script on its own so one that throws (a third-party
1192						// or template script) cannot abort the ones after it, which used to
1193						// leave the price cursor and other widgets un-initialised.
1194						var script = d.createElement('script');
1195						script.setAttribute('type', 'text/javascript');
1196						script.text = injectedCode;
1197						// A runtime error in an injected inline script is reported to window.onerror
1198						// rather than thrown back to appendChild, so catch it there and log it
1199						// cleanly instead of as an uncaught error. The listener is active only for
1200						// this single script's synchronous execution.
1201						var onError = function(event){
1202							event.preventDefault();
1203							console.warn('Could not process JavaScript code:\n', event.error, '\n', injectedCode);
1204						};
1205						window.addEventListener('error', onError);
1206						try {
1207							d.head.appendChild(script);
1208							d.head.removeChild(script);
1209						} catch (e) {
1210							console.warn('Could not process JavaScript code:\n', e);
1211						}
1212						window.removeEventListener('error', onError);
1213					});
1214				}
1215
1216				if(!window.localPage) window.localPage = {};
1217				window.localPage.infiniteScrollPage = 1;
1218
1219				setTimeout(function(){
1220					var needHeightConsistency = currentArea.querySelector('[data-consistencyheight]');
1221					if(needHeightConsistency) {
1222						var elems = parentNode.querySelectorAll('.hikashop_subcontainer');
1223						if(elems && elems.length)
1224							window.hikashop.setConsistencyHeight(elems, 'min');
1225					}
1226
1227					if(window.hikaVotes)
1228						initVote(currentArea);
1229					if(hkjQuery && hkjQuery.hktooltip)
1230						hkjQuery('[data-toggle="hk-tooltip"]').hktooltip({"html": true,"container": "body"});
1231
1232					t.refreshCounter--;
1233					if(t.refreshCounter == 0) {
1234						o.fireAjax('filters.updated', {el: el, refreshAreas : refreshAreas, resp: resp});
1235					}
1236				}, 200);
1237			}, 0);
1238		});
1239	},
1240	addToCart: function(el, type, container, data) {
1241
1242		var d = document, t = this, o = window.Oby,
1243			product_id = 0,
1244			url = el.getAttribute('href'),
1245			cart_type = ((type !== 'wishlist') ? 'cart' : 'wishlist'),
1246			containerName = el.getAttribute('data-addTo-div'),
1247			extraContainer = el.getAttribute('data-addTo-extra'),
1248			dest_id = el.getAttribute('data-addTo-cartid');
1249
1250		product_id = (cart_type == 'cart') ? el.getAttribute('data-addToCart') : el.getAttribute('data-addToWishlist');
1251		dest_id = (dest_id ? parseInt(dest_id) : 0);
1252		if(!url)
1253			url = el.getAttribute('data-href');
1254
1255		// Avoid bots and crawlers to add products in the cart
1256		var r = /bot|googlebot|crawler|spider|robot|crawling/i;
1257		if(navigator && navigator.userAgent && r.test(navigator.userAgent))
1258			return false;
1259
1260		var process = true;
1261		window.Oby.fireAjax(cart_type+'-button.clicked', {el: el, product_id: product_id, type: cart_type, cart_id: dest_id, process: process});
1262		if(!process)
1263			return true;
1264
1265		// No product ID - fallback mode
1266		if(!product_id || !url) {
1267			if(containerName && d.forms[containerName]) {
1268				d.forms[containerName].submit();
1269				return false;
1270			}
1271			return true;
1272		}
1273
1274		if(typeof container !== 'undefined') {
1275			// container is provided, just use it
1276		}else if(containerName && product_id) {
1277			// search for the container on the page
1278			container = d.forms['hikashop_product_form_' + product_id + '_' + containerName] || d.forms[containerName];
1279		}
1280
1281		url += (url.indexOf('?') >= 0 ? '&' : '?') + 'tmpl=raw';
1282		if(typeof data !== 'undefined') {
1283		} else if(container) {
1284			if(window.FormData)
1285				data = new FormData(container);
1286			else
1287				data = o.getFormData(container);
1288			// Collect orphaned inputs associated with the form via the form attribute
1289			// (browsers may not include dynamically inserted inputs with form= in FormData)
1290			if(window.FormData && data && container.id) {
1291				var scope = container.closest('.hikashop_product_page') || container.parentNode;
1292				var orphans = scope.querySelectorAll('input[form="'+container.id+'"], select[form="'+container.id+'"], textarea[form="'+container.id+'"]');
1293				for(var oi = 0; oi < orphans.length; oi++) {
1294					var orphan = orphans[oi];
1295					if(!orphan.name || orphan.disabled || data.has(orphan.name))
1296						continue;
1297					var etype = orphan.tagName.toLowerCase() == 'input' ? orphan.type.toLowerCase() : '';
1298					if(etype == 'file' || etype == 'submit')
1299						continue;
1300					if((etype == 'radio' || etype == 'checkbox') && !orphan.checked)
1301						continue;
1302					data.append(orphan.name, orphan.value);
1303				}
1304			}
1305			if(extraContainer) {
1306				extraContainer = d.forms[extraContainer] || d.getElementById(extraContainer);
1307				if(window.FormData) {
1308					extra = o.getFormData(extraContainer, false);
1309					for(var k in extra) {
1310						if(!extra.hasOwnProperty(k))
1311							continue;
1312						if(k == 'product_id')
1313							extra[k] = product_id;
1314						if(typeof(extra[k]) == 'object') {
1315							for(var i in extra[k]) {
1316								data.append(k, extra[k][i]);
1317							}
1318						} else
1319							data.append(k, extra[k]);
1320					}
1321				} else {
1322					var extra = o.getFormData(extraContainer);
1323					if(extra)
1324						data += '&' + extra;
1325					data += '&product_id='+product_id;
1326				}
1327			}
1328			if(window.FormData) {
1329				data.append('cart_type', cart_type);
1330				if(dest_id)
1331					data.append('cart_id', dest_id);
1332			} else {
1333				data += '&cart_type=' + cart_type;
1334				if(dest_id)
1335					data += '&cart_id+' + dest_id;
1336			}
1337		} else {
1338			data = 'cart_type=' + cart_type;
1339			if(dest_id)
1340				data += '&cart_id+' + dest_id;
1341		}
1342
1343		var className = el.getAttribute('data-addTo-class');
1344		if(className) o.addClass(el, className);
1345
1346		// if we are in a popup we want the add to cart to happen in the parent frame.
1347		// however, this can cause issues if the website is inside an iframe from another domain so we add a try/catch so that the add to cart can work
1348		if(window.self !== window.top) {
1349			try {
1350				if(window.top.hikashop)
1351					return window.top.hikashop.addToCart(el, type, container, data);
1352			} catch(e) {}
1353		}
1354
1355		o.xRequest(url, {mode:'POST', data: data}, function(xhr) {
1356			var className = el.getAttribute('data-addTo-class');
1357			if(className) o.removeClass(el, className);
1358
1359			var resp = Oby.evalJSON(xhr.responseText);
1360			var cart_id = (resp && (resp.ret || resp.ret === 0)) ? resp.ret : parseInt(xhr.responseText);
1361			if(isNaN(cart_id)) {
1362				console.log('cart_id was not returned in addToCart AJAX call');
1363				console.log(resp);
1364				return false;
1365			}
1366
1367			var triggers = window.Oby.fireAjax(cart_type+'.updated', {id: cart_id, el: el, product_id: product_id, type: cart_type, resp: resp});
1368			if(triggers !== false && triggers.length > 0)
1369				return true;
1370			if(window.localPage && cart_type == 'cart' && window.localPage.cartRedirect && typeof(window.localPage.cartRedirect) == 'function')
1371				return window.localPage.cartRedirect(cart_id, product_id, resp);
1372			if(window.localPage && cart_type == 'wishlist' && window.localPage.
1372wishlistRedirect && typeof(window.localPage.wishlistRedirect) == 'function')
1373				return window.localPage.wishlistRedirect(cart_id, product_id, resp);
1374		});
1375		return false;
1376	},
1377	addToWishlist: function(el) {
1378		return this.addToCart(el, 'wishlist');
1379	},
1380	checkQuantity: function(el) {
1381		var value = parseInt(el.value), old = el.getAttribute('data-hk-qty-old'),
1382			min = parseInt(el.getAttribute('data-hk-qty-min')),
1383			max = parseInt(el.getAttribute('data-hk-qty-max')),
1384			allowZero = el.getAttribute('data-hk-allow-zero') == 'true';
1385		if(old)
1386			old = parseInt(old);
1387		// No values - return
1388		if(isNaN(value)) {
1389			el.value = old || (isNaN(min) ? 1 : min);
1390			return false;
1391		}
1392		if(''+value != el.value)
1393			el.value = value;
1394		if(isNaN(min) || isNaN(max))
1395			return false;
1396		var triggers = window.Oby.fireAjax("quantity.checked", {el:el, value:value, max:max, min:min});
1397		if(
1398			(triggers !== false && triggers.length > 0) ||
1399			(value == 0 && allowZero) ||
1400			((value <= max || max == 0) && value >= min)
1401		) {
1402			// quantity change is ok
1403
1404			// trigger add to cart if the quantity input is synchronized with the cart
1405			var isSynch = document.getElementById(el.id + '_synch');
1406			if(isSynch) {
1407				isSynch.value = value;
1408				var addToCartButton = document.getElementById(el.id + '_add_to_cart_button');
1409				if(addToCartButton) {
1410					addToCartButton.onclick();
1411				}
1412			}
1413			return true;
1414		}
1415		if(max > 0 && value > max) {
1416			el.value = max;
1417			if(hkjQuery.notify) {
1418				this.translate(['QUANTITY_CHANGE_IMPOSSIBLE', 'MAXIMUM_FOR_PRODUCT_IS_X'], function(trans){
1419					hkjQuery(el).notify({title:trans[0],text:trans[1].replace('%s', max), image:'<i class="fa fa-3x fa-exclamation-circle"></i>'},{style:"metro",className:"warning",arrowShow:true,position:"top left"});
1420				});
1421			}
1422		} else if(value < min) {
1423			el.value = min;
1424			if(hkjQuery.notify) {
1425				this.translate(['QUANTITY_CHANGE_IMPOSSIBLE', 'MINIMUM_FOR_PRODUCT_IS_X'], function(trans){
1426					hkjQuery(el).notify({title:trans[0],text:trans[1].replace('%s', min), image:'<i class="fa fa-3x fa-exclamation-circle"></i>'},{style:"metro",className:"warning",arrowShow:true,position:"top left"});
1427				});
1428			}
1429		}
1430		// should not happen ?
1431		return true;
1432	},
1433	translate: function(keys, callback) {
1434		var t = this, trans = {}, missingKeys = [], o = window.Oby;
1435
1436		for(var c = 0; c < keys.length; c++) {
1437			var key = keys[c];
1438			if(!t.translations[key]) {
1439				missingKeys.push(key);
1440			} else {
1441				trans[c] = t.translations[key];
1442			}
1443		}
1444
1445		if(!missingKeys.length) {
1446			callback(trans);
1447			return;
1448		}
1449
1450		if(!t.translations_url) {
1451			console.log('missing translations URL');
1452			return;
1453		}
1454		o.xRequest(t.translations_url, {mode:'POST', data: 'translations=' + missingKeys.join(',')}, function(xhr) {
1455			var resp = o.evalJSON(xhr.responseText);
1456			foundKeys = Object.getOwnPropertyNames(resp);
1457			for(var c = 0; c < foundKeys.length; c++) {
1458				var key = foundKeys[c];
1459				trans[keys.indexOf(key)] = resp[key];
1460				t.translations[key] = resp[key];
1461			}
1462			callback(trans);
1463		});
1464	},
1465	addTrans: function(data) {
1466		for(var k in data) {
1467			if(!data.hasOwnProperty(k)) continue;
1468			this.translations[k] = data[k];
1469		}
1470	},
1471	updateQuantity: function(el, dataInput, mod) {
1472		var d = document, input = el;
1473		if(!el)
1474			return false;
1475		if(dataInput === undefined || !dataInput)
1476			dataInput = el.getAttribute('data-hk-qty-input');
1477		if(d.getElementById(dataInput))
1478			input = d.getElementById(dataInput);
1479		if(mod === undefined || !mod)
1480			mod =  parseInt(el.getAttribute('data-hk-qty-mod'));
1481		if(isNaN(mod) || mod == 0)
1482			mod = 1;
1483		var value = parseInt(input.value);
1484		if(isNaN(value))
1485			value = 0;
1486		input.value = (value + mod);
1487		this.checkQuantity(input);
1488		if(el.tagName.toLowerCase() == 'a')
1489			el.blur();
1490		return false;
1491	},
1492	deleteFromCart: function(el, cart_type, container) {
1493		if(el.processing)
1494			return false;
1495
1496		var d = document, t = this, o = window.Oby,
1497			url = el.getAttribute('href');
1498		if(!cart_type || cart_type === undefined)
1499			cart_type = el.getAttribute('data-cart-type');
1500		if(!cart_type || cart_type == '')
1501			return true;
1502
1503		url += (url.indexOf('?') >= 0 ? '&' : '?') + 'tmpl=raw';
1504		var cart_id = parseInt(el.getAttribute('data-cart-id')),
1505			cart_product_id = parseInt(el.getAttribute('data-cart-product-id'));
1506		if(cart_id === NaN || cart_product_id === NaN)
1507			return true;
1508
1509		if(container && typeof(container) == 'string')
1510			container = d.getElementById(container);
1511
1512		el.processing = true;
1513		if(container)
1514			o.addClass(container, "hikashop_checkout_loading");
1515		var data = 'cart_type=' + cart_type + '&cart_id=' + cart_id + '&cart_product_id=' + cart_product_id;
1516
1517		o.xRequest(url, {mode:'POST', data: data}, function(xhr) {
1518			el.processing = false;
1519			if(container)
1520				o.removeClass(container, "hikashop_checkout_loading");
1521
1522			var resp = Oby.evalJSON(xhr.responseText);
1523			cart_id = (resp && resp.ret) ? resp.ret : ((resp && resp.empty && resp.empty == 'true') ? cart_id : parseInt(xhr.responseText));
1524			if(cart_id === NaN)
1525				return;
1526			resp.cart_product_id = cart_product_id;
1527			resp.quantity = 0;
1528			var params = {id: cart_id, type: cart_type, resp: resp, notify: false};
1529			window.Oby.fireAjax(cart_type+'.updated', params);
1530		});
1531		return false;
1532	},
1533	submitCartModule: function(form, container, cart_type) {
1534		this.formAjaxSubmit(form, container, function(data, params) {
1535			var resp = window.Oby.evalJSON(data);
1536			var cart_id = (resp && resp.ret) ? resp.ret : parseInt(data);
1537			if(cart_id === NaN)
1538				return;
1539			var updatedElements = [];
1540			for (var key of params.keys()) {
1541				if(key.startsWith('item[') && key.endsWith('][cart_product_quantity]')) {
1542					updatedElements.push({ cart_product_id: key.replace('item[', '').replace('][cart_product_quantity]', ''), quantity_requested: params.get(key)});
1543				}
1544			}
1545			window.Oby.fireAjax(cart_type+'.updated', {id: cart_id, type: cart_type, resp: resp, updated_elements: updatedElements, notify: false});
1546		});
1547		return false;
1548	},
1549	formAjaxSubmit: function(form, container, cb) {
1550		var d = document, o = window.Oby,
1551			url = form.action;
1552		if(form.processing)
1553			return false;
1554		if(container && typeof(container) == 'string')
1555			container = d.getElementById(container);
1556		if(window.FormData) {
1557			data = new FormData(form);
1558			data.append('tmpl', 'raw');
1559		} else {
1560			data = o.getFormData(form);
1561			data += '&tmpl=raw';
1562		}
1563		form.processing = true;
1564		if(container)
1565			o.addClass(container, "hikashop_checkout_loading");
1566		o.xRequest(url, {mode:'POST', data: data}, function(xhr) {
1567			form.processing = false;
1568			if(container)
1569				o.removeClass(container, "hikashop_checkout_loading");
1570			if(!cb)
1571				o.updateElem(container, xhr.responseText);
1572			cb(xhr.responseText, data);
1573		});
1574		return false;
1575	},
1576	syncInit : function() {
1577		window.hikashop.noChzn();
1578		window.Oby.registerAjax(['cart.updated'], function(params){
1579			window.hikashop.refreshSync(params);
1580		});
1581		window.Oby.registerAjax(['hkContentChanged'], function(params){
1582			window.Oby.xRequest(window.hikashop.cartInfoUrl, {}, function(xhr) {
1583				var resp = Oby.evalJSON(xhr.responseText);
1584				var params = {resp: resp};
1585				window.hikashop.refreshSync(params);
1586			});
1587		});
1588
1589		window.Oby.registerAjax(['hkCustomFieldChanged'], function(params){
1590			if(params.field_type != 'item')
1591				return;
1592			window.Oby.xRequest(window.hikashop.cartInfoUrl, {}, function(xhr) {
1593				var resp = Oby.evalJSON(xhr.responseText);
1594				var params = {resp: resp};
1595				window.hikashop.refreshSync(params);
1596			});
1597		});
1598
1599		if(window.hikashop.cartInfo) {
1600			var params = {resp: window.hikashop.cartInfo};
1601			window.hikashop.refreshSync(params);
1602		}
1603	},
1604	xRequest: function(url, options, cb, cbError) {
1605		var t = this, xhr = window.Oby.getXHR();
1606		if(!options) options = {};
1607		if(!cb) cb = function(){};
1608		options.mode = options.mode || 'GET';
1609		options.update = options.update || false;
1610		options.replace = options.replace === undefined || options.replace;
1611		xhr.onreadystatechange = function() {
1612			if(xhr.readyState != 4)
1613				return;
1614			if( xhr.status == 200 || (xhr.status == 0 && xhr.responseText > 0) || !cbError ) {
1615				if(cb)
1616					cb(xhr,options.params);
1617				if(options.update)
1618					t.updateElem(options.update, xhr.responseText, options.replace);
1619			} else {
1620				cbError(xhr,options.params);
1621			}
1622		};
1623		xhr.open(options.mode, url, true);
1624		if(options.mode.toUpperCase() == 'POST' && typeof(options.data) == 'string') {
1625			xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
1626		}
1627		if(typeof Joomla !== 'undefined' && Joomla && Joomla.getOptions) {
1628			var csrf = Joomla.getOptions("csrf.token", "");
1629			if(csrf) {
1630				xhr.setRequestHeader("X-CSRF-Token", csrf);
1631			}
1632		}
1633		xhr.send( options.data );
1634	},
1635	updateElem: function(elem, data, replace = true) {
1636		var d = document, scripts = [], json = '';
1637		if( typeof(elem) == 'string' )
1638			elem = d.getElementById(elem);
1639
1640		// extract the javascript files and scripts from the HTML
1641		var files = [];
1642		var scriptsAlreadyLoaded = document.getElementsByTagName("script");
1643		var text = data.replace(/<script([^>]*)>([\s\S]*?)<\/script>/gi, function(all, attributes, code){
1644			if(all.indexOf('type="application/json"') != -1) {
1645				json += code + '\n';
1646				return '';
1647			}
1648			if(all.indexOf('type="application/ld+json"') != -1)
1649				return '';
1650
1651			if(all.indexOf('type="importmap"') != -1)
1652				return '';
1653			regex = RegExp('src="([^"]+)"', 'gi');
1654			result = regex.exec(attributes);
1655			if(result) {
1656				result[1] = result[1].replace(/\.js\?[0-9a-f\.]{1,128}/gi, '.js').replace(/&amp;/g, '&');
1657				for(var i = 0; i < scriptsAlreadyLoaded.length; i++) {
1658					var src = scriptsAlreadyLoaded[i].getAttribute('src');
1659					if(src && src.includes(result[1]))
1660						return '';
1661				}
1662				files.push(result[1]);
1663				return '';
1664			}
1665			scripts.push(code.replace('document.addEventListener(\'DOMContentLoaded\',', 'window.hikashop.ready(').replace('document.addEventListener("DOMContentLoaded",', 'window.hikashop.ready(').replace('$(document).ready(', 'window.hikashop.ready(').replace( 'find("select").chosen(', 'find("select").filter(":visible").chosen('));
1666			return '';
1667		});
1668
1669		// add the HTML without the javascript elements to the element on the page
1670		if(text.indexOf('id="hikashop_main_content"')) {
1671			var wrapper = document.createElement('div');
1672			wrapper.innerHTML = text;
1673			var mainArea = wrapper.querySelector('#hikashop_main_content');
1674			if(mainArea) {
1675				if(replace)
1676					elem.innerHTML = '';
1677				elem.appendChild(mainArea);
1678				text = false;
1679			}
1680		}
1681		if(text !== false) {
1682			if(!replace)
1683				elem.insertAdjacentHTML('beforeend',text);
1684			else
1685				elem.innerHTML = text;
1686		}
1687
1688		// add the javascript elements and run them
1689		if( json != '' && Joomla) {
1690			var option = JSON.parse(json);
1691			if (option) {
1692				Joomla.loadOptions(option);
1693			}
1694		}
1695
1696		if(files.length) {
1697			this.loadScripts(files, function() {
1698				window.hikashop.addScript(scripts);
1699			});
1700		} else {
1701			window.hikashop.addScript(scripts);
1702		}
1703	},
1704	addScript: function (code, url) {
1705		if(!code.length)
1706			return;
1707		for(var k=0; k < code.length; k++) {
1708			try {
1709				var oNew = document.createElement("script");
1710				oNew.type = "text/javascript";
1711				oNew.textContent = code[k];
1712				document.getElementsByTagName("head")[0].appendChild(oNew);
1713			} catch (e) {
1714				if (e instanceof SyntaxError) {
1715					console.log(e.message + ' for ' + url);
1716					console.log(code);
1717				}
1718			}
1719		}
1720	},
1721	loadScripts: function(scripts, complete) {
1722		var xhr = window.Oby.getXHR();
1723		var loadScript = function( src ) {
1724			xhr.open("GET", src , true);
1725			xhr.send();
1726		};
1727		xhr.onreadystatechange = function() {
1728			if (xhr.readyState != 4)
1729				return;
1730			if (xhr.status == 200) {
1731				try {
1732					window.hikashop.addScript([xhr.responseText], xhr.responseURL);
1733				} catch (e) {
1734					if (e instanceof SyntaxError) {
1735						console.log(e.message + ' for ' + xhr.responseURL);
1736						console.log(xhr.responseText);
1737					}
1738				}
1739			}
1740			var next = scripts.shift();
1741			if ( next ) {
1742				loadScript(next);
1743			} else if ( typeof complete == 'function' ) {
1744				complete();
1745			}
1746		}
1747		loadScript( scripts.shift() );
1748	},
1749	refreshSync : function(params) {
1750		// the cart is empty so reset all the synched elements and refresh them
1751		if(params.resp.empty) {
1752			synchronizedEls = document.querySelectorAll('.synchronized_add_to_cart');
1753			for(var i=0; i < synchronizedEls.length; i++) {
1754				var el = synchronizedEls[i];
1755				el.value = 0;
1756				el.setAttribute('data-cart-product-id', 0);
1757				var id = el.getAttribute('data-id');
1758				window.hikashop.syncQuantity(id, el.value, el.value);
1759			}
1760		}
1761		// the cart is updated from the cart module
1762		else if(params.resp.products) {
1763			// loop on all the products on the page
1764			var els = document.querySelectorAll('.synchronized_add_to_cart');
1765
1766			if(!els.length)
1767				return;
1768			for(var k=0; k < els.length; k++) {
1769				var el = els[k];
1770				var id = el.getAttribute('data-id');
1771				var productId = el.getAttribute('data-product-id');
1772				var options = [];
1773				if(el.form) {
1774					var optionsTable = el.form.querySelector('.hikashop_product_options_table');
1775					if(optionsTable) {
1776						options = hikaProductOptions.getOptions();
1777					}
1778				}
1779				var found = false;
1780				// see if we have the product in the cart
1781				for(var i=0; i < params.resp.products.length; i++) {
1782					var result = params.resp.products[i];
1783					// get the current quantity from the response of the server and update the quantity for the quantity input of the current loop
1784					if(productId == result.product_id) {
1785						if(options.length || (result.options && result.options.length)) {
1786							// no options selected on the product page or no options selected in the product in the cart -> products are different
1787							if(!options.length || !result.options || !result.options.length)
1788								continue;
1789							var match = true;
1790							// check that both arrays contain the same elements
1791							for(var j=0; j < options.length; j++) {
1792								if(!result.options.includes(options[j])) {
1793									match = false;
1794									break;
1795								}
1796							}
1797							for(var j=0; j < result.options.length; j++) {
1798								if(!options.includes(result.options[j])) {
1799									match = false;
1800									break;
1801								}
1802							}
1803							if(!match)
1804								continue;
1805						}
1806						found = true;
1807						el.value = result.quantity;
1808					}
1809				}
1810				// TODO: add custom item fields
1811				if(!found) {
1812					el.value = 0;
1813					el.setAttribute('data-cart-product-id', 0);
1814				}
1815				window.hikashop.syncQuantity(id, el.value, el.value);
1816			}
1817		}
1818	},
1819	syncQuantity : function(id, qtyInCart, qtyInInput) {
1820		// refresh the quantity in the input field
1821		if(typeof qtyInInput !== 'undefined') {
1822
1823			var inputField = document.getElementById(id+'_select');
1824			if(!inputField)
1825				inputField = document.getElementById(id);
1826			if(inputField) {
1827				if(qtyInInput == 0) {
1828					var minQty = inputField.getAttribute('data-hk-qty-min');
1829					if(minQty == 0)
1830						qtyInInput = 1;
1831					else
1832						qtyInInput = minQty;
1833				}
1834				inputField.value = qtyInInput;
1835			}
1836		}
1837
1838		// update the display of the quantity input field and the buttons
1839		var quantityArea = document.getElementById(id + '_area');
1840		var cartButtonArea = document.getElementById(id + '_add_to_cart_button');
1841		var wishlistButtonArea = document.getElementById(id + '_add_to_wishlist_button');
1842		if(!quantityArea || !cartButtonArea)
1843			return;
1844		if(qtyInCart > 0) {
1845			quantityArea.style.display = '';
1846			cartButtonArea.style.display = 'none';
1847			if(wishlistButtonArea)
1848				wishlistButtonArea.style.display = 'none';
1849		} else {
1850			quantityArea.style.display = 'none';
1851			cartButtonArea.style.display = '';
1852			if(wishlistButtonArea)
1853				wishlistButtonArea.style.display = '';
1854		}
1855	},
1856	toggleOverlayBlock: function(el, type, state) {
1857		var t = this, d = document, w = window, o = w.Oby;
1858		if(typeof(el) == 'string')
1859			el = d.getElementById(el);
1860		if(!el)
1861			return false;
1862		var open = !!el.toggleOpen; // (el.style.display != 'none');
1863		if(type != 'hover' && type != 'toggle' && type != 'drawer')
1864			type = 'click';
1865		if(type == 'drawer') {
1866			var target = d.getElementById(el.getAttribute('aria-controls'));
1867			if(!target) return false;
1868			if(target.classList.contains(hkDrawer.settings['activeClass']))
1869				hkDrawer.closeDrawer(target);
1870			else
1871				hkDrawer.openDrawer(el);
1872			return true;
1873		}
1874		if(type == 'hover' && (!state && open) || (state && !open))
1875			return;
1876
1877		if(jQuery) {
1878			jQuery(el).slideToggle('fast');
1879		} else {
1880			el.style.display = (el.style.display == 'none')?'block':'none';
1881		}
1882
1883		el.toggleOpen = !el.toggleOpen;
1884
1885		if(open) {
1886			if(type == 'hover') {
1887				o.removeEvent(el, "mouseout", el.toggleFunctionHover);
1888				el.toggleFunctionHover = null;
1889			}
1890			if(el.toggleFunction)
1891				o.removeEvent(document, "click", el.toggleFunction);
1892			el.toggleFunction = null;
1893			return true;
1894		}
1895		if(type == 'hover') {
1896			el.toggleFunctionHover = function(event) {
1897				if(event.target && this != event.target)
1898					return false;
1899				window.hikashop.toggleOverlayBlock(el, 'hover', true);
1900			};
1901			if(jQuery) {
1902				jQuery(el).on('mouseleave', el.toggleFunctionHover);
1903			} else {
1904				o.addEvent(el, "mouseout", el.toggleFunctionHover);
1905			}
1906		}
1907		var f = function(evt) {
1908			if (!evt) var evt = window.event;
1909			var trg = (window.event) ? evt.srcElement : evt.target;
1910			while(trg != null) {
1911				if(trg == el)
1912					return;
1913				trg = trg.parentNode;
1914			}
1915			t.toggleOverlayBlock(el);
1916			o.removeEvent(document, "click", f);
1917			el.toggleFunction = null;
1918		};
1919		el.toggleFunction = f;
1920		setTimeout(function(){ o.addEvent(document, "click", f); }, 100);
1921		return true;
1922	},
1923	addToCompare: function(el) {
1924		var t = this, d = document, w = window, o = w.Oby;
1925		if(!t.compare_list)
1926			t.compare_list = {};
1927
1928		if(el.disabled)
1929			return false;
1930
1931		var product_id = parseInt(el.getAttribute('data-addToCompare')),
1932			product_name = el.getAttribute('data-product-name'),
1933			css = el.getAttribute('data-addTo-class');
1934
1935		if(isNaN(product_id) || product_id <= 0)
1936			return false;
1937		if(!css || css == '')
1938			css = 'hika-compare';
1939
1940		var adding = !t.compare_list.hasOwnProperty(product_id);
1941		if(adding)
1942			t.compare_list[product_id] = product_name;
1943		else
1944			delete t.compare_list[product_id];
1945
1946		var elems = d.querySelectorAll('[data-addToCompare="'+product_id+'"]');
1947		if(elems && elems.forEach) {
1948			elems.forEach(function(e){
1949				if(e.nodeName.toLowerCase() == 'input' && e.type.toLowerCase() == 'checkbox')
1950					e.checked = adding;
1951				if(adding)
1952					o.addClass(e, css);
1953				else
1954					o.removeClass(e, css);
1955			});
1956		}
1957		var size = 0;
1958		if(Object.keys) {
1959			size = Object.keys(t.compare_list).length;
1960		} else {
1961			for(var k in t.compare_list) {
1962				if(compare_list.hasOwnProperty(k))
1963					size++;
1964			}
1965		}
1966		var triggers = window.Oby.fireAjax('compare.updated', {el: el, product_id: product_id, added: adding, list: t.compare_list, size: size});
1967		if(triggers !== false && triggers.length > 0)
1968			return false;
1969		return false;
1970	},
1971	toggleOptions: function() {
1972		var d = document, btnText = d.getElementById('openSearch_btn'),
1973		tagsDiv = d.getElementById('hikashop_listing_filters_id');
1974		if(tagsDiv.classList.contains("hidden-features") ) {
1975			tagsDiv.classList.remove("hidden-features");
1976			tagsDiv.classList.add("show-features");
1977			btnText.innerHTML = "<i class='fas fa-chevron-up'></i>";
1978		} else {
1979			tagsDiv.classList.remove("show-features");
1980			tagsDiv.classList.add("hidden-features");
1981			btnText.innerHTML = "<i class='fas fa-chevron-down'></i>";
1982		}
1983		return false;
1984	},
1985	clearOptions: function(options, defaults) {
1986		var d = document, btnText = d.getElementById('openSearch_btn'),
1987		tagsDiv = d.getElementById('hikashop_listing_filters_id');
1988		if(!options)
1989			return false;
1990		for(var i = options.length - 1; i >= 0; i--) {
1991			var name = 'filter_' + options[i];
1992			var el = d.getElementById(name);
1993			if(!el) {
1994				console.log('Filter option '+name+' not found');
1995				continue;
1996			}
1997			el.value = defaults[i];
1998		}
1999		var	clearEl = document.getElementById('hkclear');
2000		if(clearEl) {
2001			clearEl.value = 1;
2002		}
2003		return true;
2004	},
2005	clearSearch: function(el, id, all) {
2006		if(el.form.limitstart)
2007			el.form.limitstart.value = 0;
2008		var search = document.getElementById(id);
2009		if(search)
2010			search.value = '';
2011		if(all) {
2012			var v, els = el.form.querySelectorAll('[data-search-clear]');
2013			for(var i = els.length - 1; i >= 0; i--) {
2014				v = els[i].getAttribute('data-search-clear');
2015				els[i].value = v;
2016			}
2017		} else
2018			all = false;
2019		var triggers = window.Oby.fireAjax('search.cleared', {el: el, id: id, all: all});
2020		if(triggers !== false && triggers.length > 0)
2021			return false;
2022		el.form.submit();
2023		return true;
2024	},
2025	compareProducts: function(el, elems) {
2026		var t = this, params = '',
2027			url = el.getAttribute('data-compare-href');
2028		if(!url)
2029			return false;
2030		if(!elems)
2031			elems = t.compare_list;
2032		if(!elems)
2033			return false;
2034		for(var k in elems) {
2035			if(!elems.hasOwnProperty)
2036				continue;
2037			if(params != '') params += '&';
2038			params += 'cid[]=' + k;
2039		}
2040		el.href = url + ((url.indexOf('?') >= 0) ? '&' : '?') + params;
2041		return true;
2042	},
2043	toggleField: function(new_value, namekey, field_type, id, prefix, type) {
2044		var d = document, checked = 0, size = 0, obj = null, specialField = false,
2045			checkedGood = [], count = [], el = null,
2046			arr = d.getElementsByName('data['+field_type+']['+namekey+'][]');
2047
2048		// handle when this is passed in new_value
2049		// it allows for better handling of radios and checkboxes
2050		if(new_value instanceof Element) {
2051			if(new_value.type == 'radio' || new_value.type == 'checkbox') {
2052				elements = d.getElementsByName(new_value.name);
2053				for(cpt = 0; cpt < elements.length; cpt++) {
2054					if(elements[cpt].checked) {
2055						new_value = elements[cpt].value;
2056					}
2057				}
2058				if(new_value instanceof Element) {
2059					new_value = '';
2060				}
2061			} else {
2062				new_value = new_value.value;
2063			}
2064		} 
2065		if(!arr)
2066			return false;
2067
2068		if( new_value === null) {
2069			if(d.getElementById(type + namekey))
2070				new_value = d.getElementById(type + namekey).value;
2071			else {
2072				inputs = d.getElementsByName('data['+field_type+']['+namekey+']');
2073				for(var i = inputs.length - 1; i >= 0; i--) {
2074					if(inputs[i].checked)
2075						new_value = inputs[i].value;
2076				}
2077			}
2078		}
2079
2080		if(!this.fields_data && window.hikashopFieldsJs) {
2081			this.fields_data = window.hikashopFieldsJs;
2082		} else {
2083			for(var n in window.hikashopFieldsJs) {
2084				if(!window.hikashopFieldsJs.hasOwnProperty(n)) continue;
2085				if(this.fields_data[n]) continue;
2086				this.fields_data[n] = window.hikashopFieldsJs[n];
2087			}
2088		}
2089		if(this.fields_data === undefined || this.fields_data[field_type] === undefined) {
2090
2091		} else {
2092			size = (arr[0] && arr[0].length !== undefined) ? arr[0].length : arr.length;
2093
2094			if(prefix === undefined || !prefix || prefix.length == 0 || prefix.substr(-1) != '_')
2095				prefix = 'hikashop_';
2096
2097			var elementName = prefix + field_type + '_' + namekey;
2098			if(id)
2099				elementName = elementName + '_' + id;
2100			el = document.getElementById(elementName);
2101			var parentHidden = (el && el.style.display && el.style.display == 'none');
2102
2103			for(var c = 0; c < size; c++) {
2104				if(arr && arr[0] != undefined && arr[0].length != undefined)
2105					obj = d.getElementsByName('data['+field_type+']['+namekey+'][]').item(0).item(c);
2106				else
2107					obj = d.getElementsByName('data['+field_type+']['+namekey+'][]').item(c);
2108
2109				if(obj.checked || obj.selected)
2110					checked++;
2111
2112				if((obj.type && obj.type == 'checkbox') || obj.selected)
2113					specialField = true;
2114			}
2115			var data = this.fields_data[field_type][namekey];
2116
2117			for(var k in data) {
2118				if(typeof data[k] != 'object')
2119					continue;
2120
2121				for(var l in data[k]) {
2122					if(typeof data[k][l] != 'string')
2123						continue;
2124
2125					if (typeof count[k] == 'undefined') {
2126						count[k] = 0;
2127						checkedGood[k] = 0;
2128					}
2129					count[k]++;
2130					newEl = d.getElementById(namekey + '_' + k);
2131					if(newEl && (newEl.checked || newEl.selected)) {
2132						checkedGood[k]++;
2133						break;
2134					}
2135				}
2136			}
2137
2138			specialField = specialField || (arr[0] && arr[0].length && count.length > 1);
2139
2140			for(var j in data) {
2141				if(typeof data[j] != 'object')
2142					continue;
2143				for(var i in data[j]) {
2144					if(typeof data[j][i] != 'string')
2145						continue;
2146
2147					var elementName = prefix + field_type + '_' + data[j][i];
2148					if(id)
2149						elementName = elementName + '_' + id;
2150					el = document.getElementById(elementName);
2151					if(!el)
2152						continue;
2153					var condition = 'IS';
2154					if(data[j]['condition'] && data[j]['condition'][i])
2155						condition = data[j]['condition'][i];
2156					if( condition != 'IS NOT') {
2157						var display = 'none';
2158						var value = '';
2159					} else {
2160						var display = '';
2161						var value = el.value;
2162					}
2163					if(!parentHidden &&
2164						(
2165							(specialField && checkedGood[j] == count[j] && new_value != '')
2166							||
2167							(!specialField &&
2168								(
2169									j == new_value
2170									||
2171									(checkedGood[j] && count[j] && checkedGood[j] == count[j])
2172								)
2173							)
2174						)
2175					) {
2176						if(condition != 'IS NOT') {
2177							display = '';
2178							value = el.value;
2179						} else {
2180							display = 'none';
2181							value = '';
2182						}
2183					}
2184
2185					// set and unset the required attribute so that HTML5 validation works properly with hidden fields
2186					var input = document.getElementById(data[j][i]);
2187					if(input && input.hasAttribute('aria-required')) {
2188						if(display == 'none') {
2189							input.removeAttribute('required');
2190							input.classList.remove('required', 'invalid', 'form-control-danger');
2191							input.setAttribute('aria-invalid', 'false');
2192							var label = document.querySelector("label[for='"+data[j][i]+"']");
2193							if (label) {
2194								label.classList.remove("invalid");
2195								var fb = label.querySelector('.form-control-feedback');
2196								if (fb) {
2197									fb.remove();
2198								}
2199							}
2200						} else {
2201							input.setAttribute('required', 'required');
2202							input.classList.add('required');
2203						}
2204					}
2205
2206					el.style.display = display;
2207					this.toggleField(value, data[j][i], field_type, id, prefix);
2208				}
2209			}
2210		}
2211		if(window.Oby && window.Oby.fireAjax)
2212			window.Oby.fireAjax("hkCustomFieldChanged", {field_type: field_type, namekey: namekey});
2213		return false;
2214	},
2215	updateFieldError: function(el) {
2216		if(!el || !el.id) return;
2217		var errorSpan = document.getElementById(el.id + '_error');
2218		if(!errorSpan) return;
2219		var isInvalid = el.classList.contains('invalid') || (el.validity && !el.validity.valid);
2220		if(isInvalid) {
2221			var msg = el.getAttribute('data-validation-text') || errorSpan.getAttribute('data-validation-text') || '';
2222			errorSpan.textContent = msg;
2223			errorSpan.style.display = '';
2224			el.setAttribute('aria-invalid', 'true');
2225		} else {
2226			errorSpan.textContent = '';
2227			errorSpan.style.display = 'none';
2228			el.removeAttribute('aria-invalid');
2229		}
2230	}
2231};
2232window.hikashop = hikashop;
2233
2234if(oldHikaShop && oldHikaShop instanceof Object) {
2235	for (var attr in oldHikaShop) {
2236		if (oldHikaShop.hasOwnProperty(attr) && !window.hikashop.hasOwnProperty(attr))
2237			window.hikashop[attr] = oldHikaShop[attr];
2238	}
2239}
2240})();
2241
2242function tableOrdering(order, dir, task) {
2243	var form = document.adminForm;
2244	form.filter_order.value = order;
2245	form.filter_order_Dir.value	= dir;
2246	submitform(task);
2247}
2248
2249function submitform(pressbutton) {
2250	var d = document;
2251	if(!d.adminForm)
2252		return false;
2253	if(pressbutton)
2254		d.adminForm.task.value = pressbutton;
2255
2256	// old codeMirror code
2257	if(typeof(CodeMirror) == 'function') {
2258		for(x in CodeMirror.instances) {
2259			d.getElementById(x).value = CodeMirror.instances[x].getCode();
2260		}
2261	}
2262	// Creating the event
2263	var event = new Event('submit', {
2264		'bubbles'    : true, // Whether the event will bubble up through the DOM or not
2265		'cancelable' : true  // Whether the event may be canceled or not
2266	});
2267	if(d.adminForm.dispatchEvent( event )) {
2268		d.adminForm.submit();
2269	}
2270	return false;
2271}
2272
2273if(!window.submitbutton) {
2274	window.submitbutton = function(name) { submitform(name); };
2275}
2276
2277function hikashopCheckChangeForm(type, form) {
2278	if(!form)
2279		return true;
2280	var varform = document[form];
2281
2282	if(typeof(hikashopFieldsJs) == 'undefined' || typeof(hikashopFieldsJs['reqFieldsComp']) == 'undefined' || typeof(hikashopFieldsJs['reqFieldsComp'][type]) == 'undefined' || hikashopFieldsJs['reqFieldsComp'][type].length <= 0)
2283		return true;
2284
2285	var d = document;
2286	for(var i = 0; i < hikashopFieldsJs['reqFieldsComp'][type].length; i++) {
2287		elementName = 'data['+type+']['+hikashopFieldsJs['reqFieldsComp'][type][i]+']';
2288		if(typeof(varform.elements[elementName]) == 'undefined')
2289			elementName = type+'_'+hikashopFieldsJs['reqFieldsComp'][type][i];
2290
2291		elementToCheck = varform.elements[elementName];
2292		elementId = 'hikashop_'+type+'_'+ hikashopFieldsJs['reqFieldsComp'][type][i];
2293		el = d.getElementById(elementId);
2294
2295		if(elementToCheck && (typeof el == 'undefined' || el == null || typeof el.style == 'undefined' || el.style.display!='none') && !hikashopCheckField(elementToCheck,type,i,elementName,varform.elements)) {
2296			if(typeof(hikashopFieldsJs['entry_id']) == 'undefined')
2297				return false;
2298
2299			for(var j = 1; j <= hikashop['entry_id']; j++) {
2300				elementName = 'data['+type+'][entry_'+j+']['+hikashopFieldsJs['reqFieldsComp'][type][i]+']';
2301				elementToCheck = varform.elements[elementName];
2302				elementId = 'hikashop_'+type+'_'+ hikashopFieldsJs['reqFieldsComp'][type][i] + '_' + j;
2303				el = d.getElementById(elementId);
2304				if(elementToCheck && (typeof el == 'undefined' || el == null || typeof el.style == 'undefined' || el.style.display != 'none') && !hikashopCheckField(elementToCheck,type,i,elementName,varform.elements)) {
2305					return false;
2306				}
2307			}
2308		}
2309	}
2310
2311	if(type == 'register') {
2312		// check the password confirmation field only if we are in selector registration and that the user selected "registration" or "simplified registration", or that the registration is on "all in one page" and that the password confirmation field is there
2313		var register = d.getElementById('data_register_registration_method0');
2314		if(!register)
2315			register = d.getElementById('data[register][registration_method]0');
2316
2317		var simplified_pwd = d.getElementById('data_register_registration_method3');
2318		if(!simplified_pwd)
2319			simplified_pwd = d.getElementById('data[register][registration_method]3');
2320
2321		if((simplified_pwd && simplified_pwd.checked) || (register && register.checked) || (!simplified_pwd && !register)) {
2322			// check password
2323			if(typeof(varform.elements['data[register][password]']) != 'undefined' && typeof(varform.elements['data[register][password2]']) != 'undefined') {
2324				passwd = varform.elements['data[register][password]'];
2325				passwd2 = varform.elements['data[register][password2]'];
2326				if(passwd.value != passwd2.value) {
2327					alert(hikashopFieldsJs['password_different']);
2328					return false;
2329				}
2330			}
2331		}
2332
2333		//check email
2334		var emailField = varform.elements['data[register][email]'];
2335		emailField.value = emailField.value.replace(/ /g,"");
2336		var filter = /^([a-z0-9_'&\.\-\+])+\@(([a-z0-9\-])+\.)+([a-z0-9]{2,14})+$/i;
2337		if(!emailField || !filter.test(emailField.value)) {
2338			alert(hikashopFieldsJs['valid_email']);
2339			return false;
2340		}
2341	} else if(type == 'address' && typeof(varform.elements['data[address][address_telephone]']) != 'undefined') {
2342		var phoneField = varform.elements['data[address][address_telephone]'], filter = /[0-9]+/i;
2343		if(phoneField) {
2344			phoneField.value = phoneField.value.replace(/ /g,"");
2345			if(phoneField.value.length > 0 && !filter.test(phoneField.value)) {
2346				alert(hikashopFieldsJs['valid_phone']);
2347				return false;
2348			}
2349		}
2350	}
2351
2352	return true;
2353}
2354
2355function hikashopCheckField(elementToCheck, type, i, elementName, form) {
2356	if(!elementToCheck)
2357		return true;
2358
2359	var d = document, isValid = false;
2360	if(typeof(elementToCheck.value) != 'undefined') {
2361		if(elementToCheck.value == ' ' && typeof(form[elementName+'[]']) != 'undefined') {
2362			if(form[elementName+'[]'].checked) {
2363				isValid = true;
2364			} else {
2365				for(var a = form[elementName+'[]'].length - 1; a >= 0; a--) {
2366					if(form[elementName+'[]'][a].checked && form[elementName+'[]'][a].value.length > 0)
2367						isValid = true;
2368				}
2369			}
2370		} else if(elementToCheck.value.length > 0){
2371			var found = false;
2372			for(var j in hikashopFieldsJs['regexFieldsComp'][type]) {
2373				if(hikashopFieldsJs['regexFieldsComp'][type][j] == hikashopFieldsJs['reqFieldsComp'][type][i]) found = j;
2374			}
2375			if(typeof(hikashopFieldsJs['regexFieldsComp']) != 'undefined' && typeof(hikashopFieldsJs['regexFieldsComp'][type]) != 'undefined' && found){
2376				myregexp = new RegExp(hikashopFieldsJs['regexValueFieldsComp'][type][found]);
2377				if(myregexp.test(elementToCheck.value)){
2378					isValid = true;
2379				}
2380			}else{
2381				isValid = true;
2382			}
2383		}
2384	} else {
2385		for(var a = elementToCheck.length - 1; a >= 0; a--) {
2386			 if(elementToCheck[a].checked && elementToCheck[a].value.length > 0)
2387			 	isValid = true;
2388		}
2389	}
2390
2391	// Case for the switcher display, ignore check according to the method selected
2392	// joomla 3 ids are differents than joomla 1.5...
2393	var simplified_pwd = d.getElementById('data_register_registration_method3');
2394	if(!simplified_pwd) simplified_pwd = d.getElementById('data[register][registration_method]3');
2395
2396	var simplified = d.getElementById('data_register_registration_method1');
2397	if(!simplified) simplified = d.getElementById('data[register][registration_method]1');
2398
2399	var guest = d.getElementById('data_register_registration_method2');
2400	if(!guest) guest = d.getElementById('data[register][registration_method]2');
2401
2402	if(!isValid && ((simplified && simplified.checked) || (guest && guest.checked) ) && (elementName == 'data[register][password]' || elementName == 'data[register][password2]')){
2403		window.Oby.addClass(elementToCheck, 'invalid');
2404		return true;
2405	}
2406
2407	if(!isValid && ( (simplified && simplified.checked) || (guest && guest.checked) || (simplified_pwd && simplified_pwd.checked) ) && (elementName == 'data[register][name]' || elementName == 'data[register][username]')) {
2408		window.Oby.addClass(elementToCheck, 'invalid');
2409		return true;
2410	}
2411	if(!isValid) {
2412		window.Oby.addClass(elementToCheck, 'invalid');
2413		alert(hikashopFieldsJs['validFieldsComp'][type][i]);
2414		return false;
2415	} else {
2416		window.Oby.removeClass(elementToCheck, 'invalid');
2417	}
2418	return
2418 true;
2419}
2420
2421window.hikashop.ready(function(){
2422	if(window.jQuery && typeof(jQuery.noConflict) == "function" && !window.hkjQuery) {
2423		window.hkjQuery = jQuery.noConflict();
2424	}
2425	if(window.hikaVotes && typeof(initVote) == 'function')
2426		initVote();
2427	// timeout to make sure that everything is rendered before triggering the height calculations
2428	window.setTimeout(
2429		function(){
2430			window.hikashop.checkConsistency();
2431		},
2432		50
2433	);
2434});
2435if(window.jQuery && typeof(jQuery.noConflict) == "function" && !window.hkjQuery) {
2436	window.hkjQuery = jQuery.noConflict();
2437}

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.