PageSourceSearch

https://krieau.at/media/com_hikashop/js/hikashop.js?v=6502606292115

js krieau.at collected 2026-10-02 11:42:54 UTC 80,511 bytes, 2,415 lines download raw bytes

1/**
2 * @package    HikaShop
3 * @version    6.5.0
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(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 text = xhr2.responseText.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(all, code){
1120				if(all.indexOf('type="application/json"') != -1)
1121					return '';
1122				if(all.indexOf('type="application/ld+json"') != -1)
1123					return '';
1124				scripts.push(code);
1125				return '';
1126			});
1127
1128			var body = /<body.*?>([\s\S]*)<\/body>/.exec(text);
1129			if(!body)
1130				body = text;
1131			else
1132				body = body[1];
1133			window.hikashop.updateElem(div, body);
1134			// Pick the block matching the area being refreshed: if SEF rewriting drops
1135			// tmpl=raw the response is a full page with every module, not just this one.
1136			var newElem = (currentArea && currentArea.id) ? div.querySelector('#' + currentArea.id) : null;
1137			if(!newElem)
1138				newElem = div.querySelector('.filter_refresh_div');
1139
1140			// to avoid scroll in chrome
1141			setTimeout(function(){
1142				if(!currentArea) {
1143					t.refreshCounter--;
1144					return;
1145				}
1146				var className = currentArea.getAttribute('data-refresh-class');
1147				if(className) o.removeClass(currentArea, className);
1148				if(!newElem) {
1149					t.refreshCounter--;
1150					return;
1151				}
1152				var parentNode = currentArea.parentNode;
1153				if(!parentNode) {
1154					t.refreshCounter--;
1155					return;
1156				}
1157				parentNode.replaceChild(newElem, currentArea);
1158				if( scripts.length ) {
1159					scripts.forEach(function(code){
1160						var injectedCode = code.replaceAll('let jch_', 'jch_').replaceAll('const jch', 'window.hikashop.jch');
1161						injectedCode = injectedCode.replace(/(^|[;{}\n)])([ \t]*)(const|let|class)([ \t]+)([A-Za-z_$][\w$]*)/g, function(m, pre, ws, kw, sp, name) {
1162							var declared = false;
1163							try { (0, eval)(name); declared = true; }
1164							catch (err) { declared = !(err instanceof ReferenceError); }
1165							if(!declared)
1166								return m;
1167							return pre + ws + 'window.hikashop.' + name + (kw === 'class' ? ' = class' : '');
1168						});
1169						// Run each inline script on its own so one that throws (a third-party
1170						// or template script) cannot abort the ones after it, which used to
1171						// leave the price cursor and other widgets un-initialised.
1172						var script = d.createElement('script');
1173						script.setAttribute('type', 'text/javascript');
1174						script.text = injectedCode;
1175						// A runtime error in an injected inline script is reported to window.onerror
1176						// rather than thrown back to appendChild, so catch it there and log it
1177						// cleanly instead of as an uncaught error. The listener is active only for
1178						// this single script's synchronous execution.
1179						var onError = function(event){
1180							event.preventDefault();
1181							console.warn('Could not process JavaScript code:\n', event.error, '\n', injectedCode);
1182						};
1183						window.addEventListener('error', onError);
1184						try {
1185							d.head.appendChild(script);
1186							d.head.removeChild(script);
1187						} catch (e) {
1188							console.warn('Could not process JavaScript code:\n', e);
1189						}
1190						window.removeEventListener('error', onError);
1191					});
1192				}
1193
1194				if(!window.localPage) window.localPage = {};
1195				window.localPage.infiniteScrollPage = 1;
1196
1197				setTimeout(function(){
1198					var needHeightConsistency = currentArea.querySelector('[data-consistencyheight]');
1199					if(needHeightConsistency) {
1200						var elems = parentNode.querySelectorAll('.hikashop_subcontainer');
1201						if(elems && elems.length)
1202							window.hikashop.setConsistencyHeight(elems, 'min');
1203					}
1204
1205					if(window.hikaVotes)
1206						initVote(currentArea);
1207					if(hkjQuery && hkjQuery.hktooltip)
1208						hkjQuery('[data-toggle="hk-tooltip"]').hktooltip({"html": true,"container": "body"});
1209
1210					t.refreshCounter--;
1211					if(t.refreshCounter == 0) {
1212						o.fireAjax('filters.updated', {el: el, refreshAreas : refreshAreas, resp: resp});
1213					}
1214				}, 200);
1215			}, 0);
1216		});
1217	},
1218	addToCart: function(el, type, container, data) {
1219
1220		var d = document, t = this, o = window.Oby,
1221			product_id = 0,
1222			url = el.getAttribute('href'),
1223			cart_type = ((type !== 'wishlist') ? 'cart' : 'wishlist'),
1224			containerName = el.getAttribute('data-addTo-div'),
1225			extraContainer = el.getAttribute('data-addTo-extra'),
1226			dest_id = el.getAttribute('data-addTo-cartid');
1227
1228		product_id = (cart_type == 'cart') ? el.getAttribute('data-addToCart') : el.getAttribute('data-addToWishlist');
1229		dest_id = (dest_id ? parseInt(dest_id) : 0);
1230		if(!url)
1231			url = el.getAttribute('data-href');
1232
1233		// Avoid bots and crawlers to add products in the cart
1234		var r = /bot|googlebot|crawler|spider|robot|crawling/i;
1235		if(navigator && navigator.userAgent && r.test(navigator.userAgent))
1236			return false;
1237
1238		var process = true;
1239		window.Oby.fireAjax(cart_type+'-button.clicked', {el: el, product_id: product_id, type: cart_type, cart_id: dest_id, process: process});
1240		if(!process)
1241			return true;
1242
1243		// No product ID - fallback mode
1244		if(!product_id || !url) {
1245			if(containerName && d.forms[containerName]) {
1246				d.forms[containerName].submit();
1247				return false;
1248			}
1249			return true;
1250		}
1251
1252		if(typeof container !== 'undefined') {
1253			// container is provided, just use it
1254		}else if(containerName && product_id) {
1255			// search for the container on the page
1256			container = d.forms['hikashop_product_form_' + product_id + '_' + containerName] || d.forms[containerName];
1257		}
1258
1259		url += (url.indexOf('?') >= 0 ? '&' : '?') + 'tmpl=raw';
1260		if(typeof data !== 'undefined') {
1261		} else if(container) {
1262			if(window.FormData)
1263				data = new FormData(container);
1264			else
1265				data = o.getFormData(container);
1266			// Collect orphaned inputs associated with the form via the form attribute
1267			// (browsers may not include dynamically inserted inputs with form= in FormData)
1268			if(window.FormData && data && container.id) {
1269				var scope = container.closest('.hikashop_product_page') || container.parentNode;
1270				var orphans = scope.querySelectorAll('input[form="'+container.id+'"], select[form="'+container.id+'"], textarea[form="'+container.id+'"]');
1271				for(var oi = 0; oi < orphans.length; oi++) {
1272					var orphan = orphans[oi];
1273					if(!orphan.name || orphan.disabled || data.has(orphan.name))
1274						continue;
1275					var etype = orphan.tagName.toLowerCase() == 'input' ? orphan.type.toLowerCase() : '';
1276					if(etype == 'file' || etype == 'submit')
1277						continue;
1278					if((etype == 'radio' || etype == 'checkbox') && !orphan.checked)
1279						continue;
1280					data.append(orphan.name, orphan.value);
1281				}
1282			}
1283			if(extraContainer) {
1284				extraContainer = d.forms[extraContainer] || d.getElementById(extraContainer);
1285				if(window.FormData) {
1286					extra = o.getFormData(extraContainer, false);
1287					for(var k in extra) {
1288						if(!extra.hasOwnProperty(k))
1289							continue;
1290						if(k == 'product_id')
1291							extra[k] = product_id;
1292						if(typeof(extra[k]) == 'object') {
1293							for(var i in extra[k]) {
1294								data.append(k, extra[k][i]);
1295							}
1296						} else
1297							data.append(k, extra[k]);
1298					}
1299				} else {
1300					var extra = o.getFormData(extraContainer);
1301					if(extra)
1302						data += '&' + extra;
1303					data += '&product_id='+product_id;
1304				}
1305			}
1306			if(window.FormData) {
1307				data.append('cart_type', cart_type);
1308				if(dest_id)
1309					data.append('cart_id', dest_id);
1310			} else {
1311				data += '&cart_type=' + cart_type;
1312				if(dest_id)
1313					data += '&cart_id+' + dest_id;
1314			}
1315		} else {
1316			data = 'cart_type=' + cart_type;
1317			if(dest_id)
1318				data += '&cart_id+' + dest_id;
1319		}
1320
1321		var className = el.getAttribute('data-addTo-class');
1322		if(className) o.addClass(el, className);
1323
1324		// if we are in a popup we want the add to cart to happen in the parent frame.
1325		// 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
1326		if(window.self !== window.top) {
1327			try {
1328				if(window.top.hikashop)
1329					return window.top.hikashop.addToCart(el, type, container, data);
1330			} catch(e) {}
1331		}
1332
1333		o.xRequest(url, {mode:'POST', data: data}, function(xhr) {
1334			var className = el.getAttribute('data-addTo-class');
1335			if(className) o.removeClass(el, className);
1336
1337			var resp = Oby.evalJSON(xhr.responseText);
1338			var cart_id = (resp && (resp.ret || resp.ret === 0)) ? resp.ret : parseInt(xhr.responseText);
1339			if(isNaN(cart_id)) {
1340				console.log('cart_id was not returned in addToCart AJAX call');
1341				console.log(resp);
1342				return false;
1343			}
1344
1345			var triggers = window.Oby.fireAjax(cart_type+'.updated', {id: cart_id, el: el, product_id: product_id, type: cart_type, resp: resp});
1346			if(triggers !== false && triggers.length > 0)
1347				return true;
1348			if(window.localPage && cart_type == 'cart' && window.localPage.cartRedirect && typeof(window.localPage.cartRedirect) == 'function')
1349				return window.localPage.cartRedirect(cart_id, product_id, resp);
1350			if(window.localPage && cart_type == 'wishlist' && window.localPage.
1350wishlistRedirect && typeof(window.localPage.wishlistRedirect) == 'function')
1351				return window.localPage.wishlistRedirect(cart_id, product_id, resp);
1352		});
1353		return false;
1354	},
1355	addToWishlist: function(el) {
1356		return this.addToCart(el, 'wishlist');
1357	},
1358	checkQuantity: function(el) {
1359		var value = parseInt(el.value), old = el.getAttribute('data-hk-qty-old'),
1360			min = parseInt(el.getAttribute('data-hk-qty-min')),
1361			max = parseInt(el.getAttribute('data-hk-qty-max')),
1362			allowZero = el.getAttribute('data-hk-allow-zero') == 'true';
1363		if(old)
1364			old = parseInt(old);
1365		// No values - return
1366		if(isNaN(value)) {
1367			el.value = old || (isNaN(min) ? 1 : min);
1368			return false;
1369		}
1370		if(''+value != el.value)
1371			el.value = value;
1372		if(isNaN(min) || isNaN(max))
1373			return false;
1374		var triggers = window.Oby.fireAjax("quantity.checked", {el:el, value:value, max:max, min:min});
1375		if(
1376			(triggers !== false && triggers.length > 0) ||
1377			(value == 0 && allowZero) ||
1378			((value <= max || max == 0) && value >= min)
1379		) {
1380			// quantity change is ok
1381
1382			// trigger add to cart if the quantity input is synchronized with the cart
1383			var isSynch = document.getElementById(el.id + '_synch');
1384			if(isSynch) {
1385				isSynch.value = value;
1386				var addToCartButton = document.getElementById(el.id + '_add_to_cart_button');
1387				if(addToCartButton) {
1388					addToCartButton.onclick();
1389				}
1390			}
1391			return true;
1392		}
1393		if(max > 0 && value > max) {
1394			el.value = max;
1395			if(hkjQuery.notify) {
1396				this.translate(['QUANTITY_CHANGE_IMPOSSIBLE', 'MAXIMUM_FOR_PRODUCT_IS_X'], function(trans){
1397					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"});
1398				});
1399			}
1400		} else if(value < min) {
1401			el.value = min;
1402			if(hkjQuery.notify) {
1403				this.translate(['QUANTITY_CHANGE_IMPOSSIBLE', 'MINIMUM_FOR_PRODUCT_IS_X'], function(trans){
1404					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"});
1405				});
1406			}
1407		}
1408		// should not happen ?
1409		return true;
1410	},
1411	translate: function(keys, callback) {
1412		var t = this, trans = {}, missingKeys = [], o = window.Oby;
1413
1414		for(var c = 0; c < keys.length; c++) {
1415			var key = keys[c];
1416			if(!t.translations[key]) {
1417				missingKeys.push(key);
1418			} else {
1419				trans[c] = t.translations[key];
1420			}
1421		}
1422
1423		if(!missingKeys.length) {
1424			callback(trans);
1425			return;
1426		}
1427
1428		if(!t.translations_url) {
1429			console.log('missing translations URL');
1430			return;
1431		}
1432		o.xRequest(t.translations_url, {mode:'POST', data: 'translations=' + missingKeys.join(',')}, function(xhr) {
1433			var resp = o.evalJSON(xhr.responseText);
1434			foundKeys = Object.getOwnPropertyNames(resp);
1435			for(var c = 0; c < foundKeys.length; c++) {
1436				var key = foundKeys[c];
1437				trans[keys.indexOf(key)] = resp[key];
1438				t.translations[key] = resp[key];
1439			}
1440			callback(trans);
1441		});
1442	},
1443	addTrans: function(data) {
1444		for(var k in data) {
1445			if(!data.hasOwnProperty(k)) continue;
1446			this.translations[k] = data[k];
1447		}
1448	},
1449	updateQuantity: function(el, dataInput, mod) {
1450		var d = document, input = el;
1451		if(!el)
1452			return false;
1453		if(dataInput === undefined || !dataInput)
1454			dataInput = el.getAttribute('data-hk-qty-input');
1455		if(d.getElementById(dataInput))
1456			input = d.getElementById(dataInput);
1457		if(mod === undefined || !mod)
1458			mod =  parseInt(el.getAttribute('data-hk-qty-mod'));
1459		if(isNaN(mod) || mod == 0)
1460			mod = 1;
1461		var value = parseInt(input.value);
1462		if(isNaN(value))
1463			value = 0;
1464		input.value = (value + mod);
1465		this.checkQuantity(input);
1466		if(el.tagName.toLowerCase() == 'a')
1467			el.blur();
1468		return false;
1469	},
1470	deleteFromCart: function(el, cart_type, container) {
1471		if(el.processing)
1472			return false;
1473
1474		var d = document, t = this, o = window.Oby,
1475			url = el.getAttribute('href');
1476		if(!cart_type || cart_type === undefined)
1477			cart_type = el.getAttribute('data-cart-type');
1478		if(!cart_type || cart_type == '')
1479			return true;
1480
1481		url += (url.indexOf('?') >= 0 ? '&' : '?') + 'tmpl=raw';
1482		var cart_id = parseInt(el.getAttribute('data-cart-id')),
1483			cart_product_id = parseInt(el.getAttribute('data-cart-product-id'));
1484		if(cart_id === NaN || cart_product_id === NaN)
1485			return true;
1486
1487		if(container && typeof(container) == 'string')
1488			container = d.getElementById(container);
1489
1490		el.processing = true;
1491		if(container)
1492			o.addClass(container, "hikashop_checkout_loading");
1493		var data = 'cart_type=' + cart_type + '&cart_id=' + cart_id + '&cart_product_id=' + cart_product_id;
1494
1495		o.xRequest(url, {mode:'POST', data: data}, function(xhr) {
1496			el.processing = false;
1497			if(container)
1498				o.removeClass(container, "hikashop_checkout_loading");
1499
1500			var resp = Oby.evalJSON(xhr.responseText);
1501			cart_id = (resp && resp.ret) ? resp.ret : ((resp && resp.empty && resp.empty == 'true') ? cart_id : parseInt(xhr.responseText));
1502			if(cart_id === NaN)
1503				return;
1504			resp.cart_product_id = cart_product_id;
1505			resp.quantity = 0;
1506			var params = {id: cart_id, type: cart_type, resp: resp, notify: false};
1507			window.Oby.fireAjax(cart_type+'.updated', params);
1508		});
1509		return false;
1510	},
1511	submitCartModule: function(form, container, cart_type) {
1512		this.formAjaxSubmit(form, container, function(data, params) {
1513			var resp = window.Oby.evalJSON(data);
1514			var cart_id = (resp && resp.ret) ? resp.ret : parseInt(data);
1515			if(cart_id === NaN)
1516				return;
1517			var updatedElements = [];
1518			for (var key of params.keys()) {
1519				if(key.startsWith('item[') && key.endsWith('][cart_product_quantity]')) {
1520					updatedElements.push({ cart_product_id: key.replace('item[', '').replace('][cart_product_quantity]', ''), quantity_requested: params.get(key)});
1521				}
1522			}
1523			window.Oby.fireAjax(cart_type+'.updated', {id: cart_id, type: cart_type, resp: resp, updated_elements: updatedElements, notify: false});
1524		});
1525		return false;
1526	},
1527	formAjaxSubmit: function(form, container, cb) {
1528		var d = document, o = window.Oby,
1529			url = form.action;
1530		if(form.processing)
1531			return false;
1532		if(container && typeof(container) == 'string')
1533			container = d.getElementById(container);
1534		if(window.FormData) {
1535			data = new FormData(form);
1536			data.append('tmpl', 'raw');
1537		} else {
1538			data = o.getFormData(form);
1539			data += '&tmpl=raw';
1540		}
1541		form.processing = true;
1542		if(container)
1543			o.addClass(container, "hikashop_checkout_loading");
1544		o.xRequest(url, {mode:'POST', data: data}, function(xhr) {
1545			form.processing = false;
1546			if(container)
1547				o.removeClass(container, "hikashop_checkout_loading");
1548			if(!cb)
1549				o.updateElem(container, xhr.responseText);
1550			cb(xhr.responseText, data);
1551		});
1552		return false;
1553	},
1554	syncInit : function() {
1555		window.hikashop.noChzn();
1556		window.Oby.registerAjax(['cart.updated'], function(params){
1557			window.hikashop.refreshSync(params);
1558		});
1559		window.Oby.registerAjax(['hkContentChanged'], function(params){
1560			window.Oby.xRequest(window.hikashop.cartInfoUrl, {}, function(xhr) {
1561				var resp = Oby.evalJSON(xhr.responseText);
1562				var params = {resp: resp};
1563				window.hikashop.refreshSync(params);
1564			});
1565		});
1566
1567		window.Oby.registerAjax(['hkCustomFieldChanged'], function(params){
1568			if(params.field_type != 'item')
1569				return;
1570			window.Oby.xRequest(window.hikashop.cartInfoUrl, {}, function(xhr) {
1571				var resp = Oby.evalJSON(xhr.responseText);
1572				var params = {resp: resp};
1573				window.hikashop.refreshSync(params);
1574			});
1575		});
1576
1577		if(window.hikashop.cartInfo) {
1578			var params = {resp: window.hikashop.cartInfo};
1579			window.hikashop.refreshSync(params);
1580		}
1581	},
1582	xRequest: function(url, options, cb, cbError) {
1583		var t = this, xhr = window.Oby.getXHR();
1584		if(!options) options = {};
1585		if(!cb) cb = function(){};
1586		options.mode = options.mode || 'GET';
1587		options.update = options.update || false;
1588		options.replace = options.replace === undefined || options.replace;
1589		xhr.onreadystatechange = function() {
1590			if(xhr.readyState != 4)
1591				return;
1592			if( xhr.status == 200 || (xhr.status == 0 && xhr.responseText > 0) || !cbError ) {
1593				if(cb)
1594					cb(xhr,options.params);
1595				if(options.update)
1596					t.updateElem(options.update, xhr.responseText, options.replace);
1597			} else {
1598				cbError(xhr,options.params);
1599			}
1600		};
1601		xhr.open(options.mode, url, true);
1602		if(options.mode.toUpperCase() == 'POST' && typeof(options.data) == 'string') {
1603			xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
1604		}
1605		if(typeof Joomla !== 'undefined' && Joomla && Joomla.getOptions) {
1606			var csrf = Joomla.getOptions("csrf.token", "");
1607			if(csrf) {
1608				xhr.setRequestHeader("X-CSRF-Token", csrf);
1609			}
1610		}
1611		xhr.send( options.data );
1612	},
1613	updateElem: function(elem, data, replace = true) {
1614		var d = document, scripts = [], json = '';
1615		if( typeof(elem) == 'string' )
1616			elem = d.getElementById(elem);
1617
1618		// extract the javascript files and scripts from the HTML
1619		var files = [];
1620		var scriptsAlreadyLoaded = document.getElementsByTagName("script");
1621		var text = data.replace(/<script([^>]*)>([\s\S]*?)<\/script>/gi, function(all, attributes, code){
1622			if(all.indexOf('type="application/json"') != -1) {
1623				json += code + '\n';
1624				return '';
1625			}
1626			if(all.indexOf('type="application/ld+json"') != -1)
1627				return '';
1628
1629			if(all.indexOf('type="importmap"') != -1)
1630				return '';
1631			regex = RegExp('src="([^"]+)"', 'gi');
1632			result = regex.exec(attributes);
1633			if(result) {
1634				result[1] = result[1].replace(/\.js\?[0-9a-f\.]{1,128}/gi, '.js').replace(/&amp;/g, '&');
1635				for(var i = 0; i < scriptsAlreadyLoaded.length; i++) {
1636					var src = scriptsAlreadyLoaded[i].getAttribute('src');
1637					if(src && src.includes(result[1]))
1638						return '';
1639				}
1640				files.push(result[1]);
1641				return '';
1642			}
1643			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('));
1644			return '';
1645		});
1646
1647		// add the HTML without the javascript elements to the element on the page
1648		if(text.indexOf('id="hikashop_main_content"')) {
1649			var wrapper = document.createElement('div');
1650			wrapper.innerHTML = text;
1651			var mainArea = wrapper.querySelector('#hikashop_main_content');
1652			if(mainArea) {
1653				if(replace)
1654					elem.innerHTML = '';
1655				elem.appendChild(mainArea);
1656				text = false;
1657			}
1658		}
1659		if(text !== false) {
1660			if(!replace)
1661				elem.insertAdjacentHTML('beforeend',text);
1662			else
1663				elem.innerHTML = text;
1664		}
1665
1666		// add the javascript elements and run them
1667		if( json != '' && Joomla) {
1668			var option = JSON.parse(json);
1669			if (option) {
1670				Joomla.loadOptions(option);
1671			}
1672		}
1673
1674		if(files.length) {
1675			this.loadScripts(files, function() {
1676				window.hikashop.addScript(scripts);
1677			});
1678		} else {
1679			window.hikashop.addScript(scripts);
1680		}
1681	},
1682	addScript: function (code, url) {
1683		if(!code.length)
1684			return;
1685		for(var k=0; k < code.length; k++) {
1686			try {
1687				var oNew = document.createElement("script");
1688				oNew.type = "text/javascript";
1689				oNew.textContent = code[k];
1690				document.getElementsByTagName("head")[0].appendChild(oNew);
1691			} catch (e) {
1692				if (e instanceof SyntaxError) {
1693					console.log(e.message + ' for ' + url);
1694					console.log(code);
1695				}
1696			}
1697		}
1698	},
1699	loadScripts: function(scripts, complete) {
1700		var xhr = window.Oby.getXHR();
1701		var loadScript = function( src ) {
1702			xhr.open("GET", src , true);
1703			xhr.send();
1704		};
1705		xhr.onreadystatechange = function() {
1706			if (xhr.readyState != 4)
1707				return;
1708			if (xhr.status == 200) {
1709				try {
1710					window.hikashop.addScript([xhr.responseText], xhr.responseURL);
1711				} catch (e) {
1712					if (e instanceof SyntaxError) {
1713						console.log(e.message + ' for ' + xhr.responseURL);
1714						console.log(xhr.responseText);
1715					}
1716				}
1717			}
1718			var next = scripts.shift();
1719			if ( next ) {
1720				loadScript(next);
1721			} else if ( typeof complete == 'function' ) {
1722				complete();
1723			}
1724		}
1725		loadScript( scripts.shift() );
1726	},
1727	refreshSync : function(params) {
1728		// the cart is empty so reset all the synched elements and refresh them
1729		if(params.resp.empty) {
1730			synchronizedEls = document.querySelectorAll('.synchronized_add_to_cart');
1731			for(var i=0; i < synchronizedEls.length; i++) {
1732				var el = synchronizedEls[i];
1733				el.value = 0;
1734				el.setAttribute('data-cart-product-id', 0);
1735				var id = el.getAttribute('data-id');
1736				window.hikashop.syncQuantity(id, el.value, el.value);
1737			}
1738		}
1739		// the cart is updated from the cart module
1740		else if(params.resp.products) {
1741			// loop on all the products on the page
1742			var els = document.querySelectorAll('.synchronized_add_to_cart');
1743
1744			if(!els.length)
1745				return;
1746			for(var k=0; k < els.length; k++) {
1747				var el = els[k];
1748				var id = el.getAttribute('data-id');
1749				var productId = el.getAttribute('data-product-id');
1750				var options = [];
1751				if(el.form) {
1752					var optionsTable = el.form.querySelector('.hikashop_product_options_table');
1753					if(optionsTable) {
1754						options = hikaProductOptions.getOptions();
1755					}
1756				}
1757				var found = false;
1758				// see if we have the product in the cart
1759				for(var i=0; i < params.resp.products.length; i++) {
1760					var result = params.resp.products[i];
1761					// get the current quantity from the response of the server and update the quantity for the quantity input of the current loop
1762					if(productId == result.product_id) {
1763						if(options.length || (result.options && result.options.length)) {
1764							// no options selected on the product page or no options selected in the product in the cart -> products are different
1765							if(!options.length || !result.options || !result.options.length)
1766								continue;
1767							var match = true;
1768							// check that both arrays contain the same elements
1769							for(var j=0; j < options.length; j++) {
1770								if(!result.options.includes(options[j])) {
1771									match = false;
1772									break;
1773								}
1774							}
1775							for(var j=0; j < result.options.length; j++) {
1776								if(!options.includes(result.options[j])) {
1777									match = false;
1778									break;
1779								}
1780							}
1781							if(!match)
1782								continue;
1783						}
1784						found = true;
1785						el.value = result.quantity;
1786					}
1787				}
1788				// TODO: add custom item fields
1789				if(!found) {
1790					el.value = 0;
1791					el.setAttribute('data-cart-product-id', 0);
1792				}
1793				window.hikashop.syncQuantity(id, el.value, el.value);
1794			}
1795		}
1796	},
1797	syncQuantity : function(id, qtyInCart, qtyInInput) {
1798		// refresh the quantity in the input field
1799		if(typeof qtyInInput !== 'undefined') {
1800
1801			var inputField = document.getElementById(id+'_select');
1802			if(!inputField)
1803				inputField = document.getElementById(id);
1804			if(inputField) {
1805				if(qtyInInput == 0) {
1806					var minQty = inputField.getAttribute('data-hk-qty-min');
1807					if(minQty == 0)
1808						qtyInInput = 1;
1809					else
1810						qtyInInput = minQty;
1811				}
1812				inputField.value = qtyInInput;
1813			}
1814		}
1815
1816		// update the display of the quantity input field and the buttons
1817		var quantityArea = document.getElementById(id + '_area');
1818		var cartButtonArea = document.getElementById(id + '_add_to_cart_button');
1819		var wishlistButtonArea = document.getElementById(id + '_add_to_wishlist_button');
1820		if(!quantityArea || !cartButtonArea)
1821			return;
1822		if(qtyInCart > 0) {
1823			quantityArea.style.display = '';
1824			cartButtonArea.style.display = 'none';
1825			if(wishlistButtonArea)
1826				wishlistButtonArea.style.display = 'none';
1827		} else {
1828			quantityArea.style.display = 'none';
1829			cartButtonArea.style.display = '';
1830			if(wishlistButtonArea)
1831				wishlistButtonArea.style.display = '';
1832		}
1833	},
1834	toggleOverlayBlock: function(el, type, state) {
1835		var t = this, d = document, w = window, o = w.Oby;
1836		if(typeof(el) == 'string')
1837			el = d.getElementById(el);
1838		if(!el)
1839			return false;
1840		var open = !!el.toggleOpen; // (el.style.display != 'none');
1841		if(type != 'hover' && type != 'toggle' && type != 'drawer')
1842			type = 'click';
1843		if(type == 'drawer') {
1844			var target = d.getElementById(el.getAttribute('aria-controls'));
1845			if(!target) return false;
1846			if(target.classList.contains(hkDrawer.settings['activeClass']))
1847				hkDrawer.closeDrawer(target);
1848			else
1849				hkDrawer.openDrawer(el);
1850			return true;
1851		}
1852		if(type == 'hover' && (!state && open) || (state && !open))
1853			return;
1854
1855		if(jQuery) {
1856			jQuery(el).slideToggle('fast');
1857		} else {
1858			el.style.display = (el.style.display == 'none')?'block':'none';
1859		}
1860
1861		el.toggleOpen = !el.toggleOpen;
1862
1863		if(open) {
1864			if(type == 'hover') {
1865				o.removeEvent(el, "mouseout", el.toggleFunctionHover);
1866				el.toggleFunctionHover = null;
1867			}
1868			if(el.toggleFunction)
1869				o.removeEvent(document, "click", el.toggleFunction);
1870			el.toggleFunction = null;
1871			return true;
1872		}
1873		if(type == 'hover') {
1874			el.toggleFunctionHover = function(event) {
1875				if(event.target && this != event.target)
1876					return false;
1877				window.hikashop.toggleOverlayBlock(el, 'hover', true);
1878			};
1879			if(jQuery) {
1880				jQuery(el).on('mouseleave', el.toggleFunctionHover);
1881			} else {
1882				o.addEvent(el, "mouseout", el.toggleFunctionHover);
1883			}
1884		}
1885		var f = function(evt) {
1886			if (!evt) var evt = window.event;
1887			var trg = (window.event) ? evt.srcElement : evt.target;
1888			while(trg != null) {
1889				if(trg == el)
1890					return;
1891				trg = trg.parentNode;
1892			}
1893			t.toggleOverlayBlock(el);
1894			o.removeEvent(document, "click", f);
1895			el.toggleFunction = null;
1896		};
1897		el.toggleFunction = f;
1898		setTimeout(function(){ o.addEvent(document, "click", f); }, 100);
1899		return true;
1900	},
1901	addToCompare: function(el) {
1902		var t = this, d = document, w = window, o = w.Oby;
1903		if(!t.compare_list)
1904			t.compare_list = {};
1905
1906		if(el.disabled)
1907			return false;
1908
1909		var product_id = parseInt(el.getAttribute('data-addToCompare')),
1910			product_name = el.getAttribute('data-product-name'),
1911			css = el.getAttribute('data-addTo-class');
1912
1913		if(isNaN(product_id) || product_id <= 0)
1914			return false;
1915		if(!css || css == '')
1916			css = 'hika-compare';
1917
1918		var adding = !t.compare_list.hasOwnProperty(product_id);
1919		if(adding)
1920			t.compare_list[product_id] = product_name;
1921		else
1922			delete t.compare_list[product_id];
1923
1924		var elems = d.querySelectorAll('[data-addToCompare="'+product_id+'"]');
1925		if(elems && elems.forEach) {
1926			elems.forEach(function(e){
1927				if(e.nodeName.toLowerCase() == 'input' && e.type.toLowerCase() == 'checkbox')
1928					e.checked = adding;
1929				if(adding)
1930					o.addClass(e, css);
1931				else
1932					o.removeClass(e, css);
1933			});
1934		}
1935		var size = 0;
1936		if(Object.keys) {
1937			size = Object.keys(t.compare_list).length;
1938		} else {
1939			for(var k in t.compare_list) {
1940				if(compare_list.hasOwnProperty(k))
1941					size++;
1942			}
1943		}
1944		var triggers = window.Oby.fireAjax('compare.updated', {el: el, product_id: product_id, added: adding, list: t.compare_list, size: size});
1945		if(triggers !== false && triggers.length > 0)
1946			return false;
1947		return false;
1948	},
1949	toggleOptions: function() {
1950		var d = document, btnText = d.getElementById('openSearch_btn'),
1951		tagsDiv = d.getElementById('hikashop_listing_filters_id');
1952		if(tagsDiv.classList.contains("hidden-features") ) {
1953			tagsDiv.classList.remove("hidden-features");
1954			tagsDiv.classList.add("show-features");
1955			btnText.innerHTML = "<i class='fas fa-chevron-up'></i>";
1956		} else {
1957			tagsDiv.classList.remove("show-features");
1958			tagsDiv.classList.add("hidden-features");
1959			btnText.innerHTML = "<i class='fas fa-chevron-down'></i>";
1960		}
1961		return false;
1962	},
1963	clearOptions: function(options, defaults) {
1964		var d = document, btnText = d.getElementById('openSearch_btn'),
1965		tagsDiv = d.getElementById('hikashop_listing_filters_id');
1966		if(!options)
1967			return false;
1968		for(var i = options.length - 1; i >= 0; i--) {
1969			var name = 'filter_' + options[i];
1970			var el = d.getElementById(name);
1971			if(!el) {
1972				console.log('Filter option '+name+' not found');
1973				continue;
1974			}
1975			el.value = defaults[i];
1976		}
1977		var	clearEl = document.getElementById('hkclear');
1978		if(clearEl) {
1979			clearEl.value = 1;
1980		}
1981		return true;
1982	},
1983	clearSearch: function(el, id, all) {
1984		if(el.form.limitstart)
1985			el.form.limitstart.value = 0;
1986		var search = document.getElementById(id);
1987		if(search)
1988			search.value = '';
1989		if(all) {
1990			var v, els = el.form.querySelectorAll('[data-search-clear]');
1991			for(var i = els.length - 1; i >= 0; i--) {
1992				v = els[i].getAttribute('data-search-clear');
1993				els[i].value = v;
1994			}
1995		} else
1996			all = false;
1997		var triggers = window.Oby.fireAjax('search.cleared', {el: el, id: id, all: all});
1998		if(triggers !== false && triggers.length > 0)
1999			return false;
2000		el.form.submit();
2001		return true;
2002	},
2003	compareProducts: function(el, elems) {
2004		var t = this, params = '',
2005			url = el.getAttribute('data-compare-href');
2006		if(!url)
2007			return false;
2008		if(!elems)
2009			elems = t.compare_list;
2010		if(!elems)
2011			return false;
2012		for(var k in elems) {
2013			if(!elems.hasOwnProperty)
2014				continue;
2015			if(params != '') params += '&';
2016			params += 'cid[]=' + k;
2017		}
2018		el.href = url + ((url.indexOf('?') >= 0) ? '&' : '?') + params;
2019		return true;
2020	},
2021	toggleField: function(new_value, namekey, field_type, id, prefix, type) {
2022		var d = document, checked = 0, size = 0, obj = null, specialField = false,
2023			checkedGood = [], count = [], el = null,
2024			arr = d.getElementsByName('data['+field_type+']['+namekey+'][]');
2025
2026		// handle when this is passed in new_value
2027		// it allows for better handling of radios and checkboxes
2028		if(new_value instanceof Element) {
2029			if(new_value.type == 'radio' || new_value.type == 'checkbox') {
2030				elements = d.getElementsByName(new_value.name);
2031				for(cpt = 0; cpt < elements.length; cpt++) {
2032					if(elements[cpt].checked) {
2033						new_value = elements[cpt].value;
2034					}
2035				}
2036				if(new_value instanceof Element) {
2037					new_value = '';
2038				}
2039			} else {
2040				new_value = new_value.value;
2041			}
2042		} 
2043		if(!arr)
2044			return false;
2045
2046		if( new_value === null) {
2047			if(d.getElementById(type + namekey))
2048				new_value = d.getElementById(type + namekey).value;
2049			else {
2050				inputs = d.getElementsByName('data['+field_type+']['+namekey+']');
2051				for(var i = inputs.length - 1; i >= 0; i--) {
2052					if(inputs[i].checked)
2053						new_value = inputs[i].value;
2054				}
2055			}
2056		}
2057
2058		if(!this.fields_data && window.hikashopFieldsJs) {
2059			this.fields_data = window.hikashopFieldsJs;
2060		} else {
2061			for(var n in window.hikashopFieldsJs) {
2062				if(!window.hikashopFieldsJs.hasOwnProperty(n)) continue;
2063				if(this.fields_data[n]) continue;
2064				this.fields_data[n] = window.hikashopFieldsJs[n];
2065			}
2066		}
2067		if(this.fields_data === undefined || this.fields_data[field_type] === undefined) {
2068
2069		} else {
2070			size = (arr[0] && arr[0].length !== undefined) ? arr[0].length : arr.length;
2071
2072			if(prefix === undefined || !prefix || prefix.length == 0 || prefix.substr(-1) != '_')
2073				prefix = 'hikashop_';
2074
2075			var elementName = prefix + field_type + '_' + namekey;
2076			if(id)
2077				elementName = elementName + '_' + id;
2078			el = document.getElementById(elementName);
2079			var parentHidden = (el && el.style.display && el.style.display == 'none');
2080
2081			for(var c = 0; c < size; c++) {
2082				if(arr && arr[0] != undefined && arr[0].length != undefined)
2083					obj = d.getElementsByName('data['+field_type+']['+namekey+'][]').item(0).item(c);
2084				else
2085					obj = d.getElementsByName('data['+field_type+']['+namekey+'][]').item(c);
2086
2087				if(obj.checked || obj.selected)
2088					checked++;
2089
2090				if((obj.type && obj.type == 'checkbox') || obj.selected)
2091					specialField = true;
2092			}
2093			var data = this.fields_data[field_type][namekey];
2094
2095			for(var k in data) {
2096				if(typeof data[k] != 'object')
2097					continue;
2098
2099				for(var l in data[k]) {
2100					if(typeof data[k][l] != 'string')
2101						continue;
2102
2103					if (typeof count[k] == 'undefined') {
2104						count[k] = 0;
2105						checkedGood[k] = 0;
2106					}
2107					count[k]++;
2108					newEl = d.getElementById(namekey + '_' + k);
2109					if(newEl && (newEl.checked || newEl.selected)) {
2110						checkedGood[k]++;
2111						break;
2112					}
2113				}
2114			}
2115
2116			specialField = specialField || (arr[0] && arr[0].length && count.length > 1);
2117
2118			for(var j in data) {
2119				if(typeof data[j] != 'object')
2120					continue;
2121				for(var i in data[j]) {
2122					if(typeof data[j][i] != 'string')
2123						continue;
2124
2125					var elementName = prefix + field_type + '_' + data[j][i];
2126					if(id)
2127						elementName = elementName + '_' + id;
2128					el = document.getElementById(elementName);
2129					if(!el)
2130						continue;
2131					var condition = 'IS';
2132					if(data[j]['condition'] && data[j]['condition'][i])
2133						condition = data[j]['condition'][i];
2134					if( condition != 'IS NOT') {
2135						var display = 'none';
2136						var value = '';
2137					} else {
2138						var display = '';
2139						var value = el.value;
2140					}
2141					if(!parentHidden &&
2142						(
2143							(specialField && checkedGood[j] == count[j] && new_value != '')
2144							||
2145							(!specialField &&
2146								(
2147									j == new_value
2148									||
2149									(checkedGood[j] && count[j] && checkedGood[j] == count[j])
2150								)
2151							)
2152						)
2153					) {
2154						if(condition != 'IS NOT') {
2155							display = '';
2156							value = el.value;
2157						} else {
2158							display = 'none';
2159							value = '';
2160						}
2161					}
2162
2163					// set and unset the required attribute so that HTML5 validation works properly with hidden fields
2164					var input = document.getElementById(data[j][i]);
2165					if(input && input.hasAttribute('aria-required')) {
2166						if(display == 'none') {
2167							input.removeAttribute('required');
2168							input.classList.remove('required', 'invalid', 'form-control-danger');
2169							input.setAttribute('aria-invalid', 'false');
2170							var label = document.querySelector("label[for='"+data[j][i]+"']");
2171							if (label) {
2172								label.classList.remove("invalid");
2173								var fb = label.querySelector('.form-control-feedback');
2174								if (fb) {
2175									fb.remove();
2176								}
2177							}
2178						} else {
2179							input.setAttribute('required', 'required');
2180							input.classList.add('required');
2181						}
2182					}
2183
2184					el.style.display = display;
2185					this.toggleField(value, data[j][i], field_type, id, prefix);
2186				}
2187			}
2188		}
2189		if(window.Oby && window.Oby.fireAjax)
2190			window.Oby.fireAjax("hkCustomFieldChanged", {field_type: field_type, namekey: namekey});
2191		return false;
2192	},
2193	updateFieldError: function(el) {
2194		if(!el || !el.id) return;
2195		var errorSpan = document.getElementById(el.id + '_error');
2196		if(!errorSpan) return;
2197		var isInvalid = el.classList.contains('invalid') || (el.validity && !el.validity.valid);
2198		if(isInvalid) {
2199			var msg = el.getAttribute('data-validation-text') || errorSpan.getAttribute('data-validation-text') || '';
2200			errorSpan.textContent = msg;
2201			errorSpan.style.display = '';
2202			el.setAttribute('aria-invalid', 'true');
2203		} else {
2204			errorSpan.textContent = '';
2205			errorSpan.style.display = 'none';
2206			el.removeAttribute('aria-invalid');
2207		}
2208	}
2209};
2210window.hikashop = hikashop;
2211
2212if(oldHikaShop && oldHikaShop instanceof Object) {
2213	for (var attr in oldHikaShop) {
2214		if (oldHikaShop.hasOwnProperty(attr) && !window.hikashop.hasOwnProperty(attr))
2215			window.hikashop[attr] = oldHikaShop[attr];
2216	}
2217}
2218})();
2219
2220function tableOrdering(order, dir, task) {
2221	var form = document.adminForm;
2222	form.filter_order.value = order;
2223	form.filter_order_Dir.value	= dir;
2224	submitform(task);
2225}
2226
2227function submitform(pressbutton) {
2228	var d = document;
2229	if(!d.adminForm)
2230		return false;
2231	if(pressbutton)
2232		d.adminForm.task.value = pressbutton;
2233
2234	// old codeMirror code
2235	if(typeof(CodeMirror) == 'function') {
2236		for(x in CodeMirror.instances) {
2237			d.getElementById(x).value = CodeMirror.instances[x].getCode();
2238		}
2239	}
2240	// Creating the event
2241	var event = new Event('submit', {
2242		'bubbles'    : true, // Whether the event will bubble up through the DOM or not
2243		'cancelable' : true  // Whether the event may be canceled or not
2244	});
2245	if(d.adminForm.dispatchEvent( event )) {
2246		d.adminForm.submit();
2247	}
2248	return false;
2249}
2250
2251if(!window.submitbutton) {
2252	window.submitbutton = function(name) { submitform(name); };
2253}
2254
2255function hikashopCheckChangeForm(type, form) {
2256	if(!form)
2257		return true;
2258	var varform = document[form];
2259
2260	if(typeof(hikashopFieldsJs) == 'undefined' || typeof(hikashopFieldsJs['reqFieldsComp']) == 'undefined' || typeof(hikashopFieldsJs['reqFieldsComp'][type]) == 'undefined' || hikashopFieldsJs['reqFieldsComp'][type].length <= 0)
2261		return true;
2262
2263	var d = document;
2264	for(var i = 0; i < hikashopFieldsJs['reqFieldsComp'][type].length; i++) {
2265		elementName = 'data['+type+']['+hikashopFieldsJs['reqFieldsComp'][type][i]+']';
2266		if(typeof(varform.elements[elementName]) == 'undefined')
2267			elementName = type+'_'+hikashopFieldsJs['reqFieldsComp'][type][i];
2268
2269		elementToCheck = varform.elements[elementName];
2270		elementId = 'hikashop_'+type+'_'+ hikashopFieldsJs['reqFieldsComp'][type][i];
2271		el = d.getElementById(elementId);
2272
2273		if(elementToCheck && (typeof el == 'undefined' || el == null || typeof el.style == 'undefined' || el.style.display!='none') && !hikashopCheckField(elementToCheck,type,i,elementName,varform.elements)) {
2274			if(typeof(hikashopFieldsJs['entry_id']) == 'undefined')
2275				return false;
2276
2277			for(var j = 1; j <= hikashop['entry_id']; j++) {
2278				elementName = 'data['+type+'][entry_'+j+']['+hikashopFieldsJs['reqFieldsComp'][type][i]+']';
2279				elementToCheck = varform.elements[elementName];
2280				elementId = 'hikashop_'+type+'_'+ hikashopFieldsJs['reqFieldsComp'][type][i] + '_' + j;
2281				el = d.getElementById(elementId);
2282				if(elementToCheck && (typeof el == 'undefined' || el == null || typeof el.style == 'undefined' || el.style.display != 'none') && !hikashopCheckField(elementToCheck,type,i,elementName,varform.elements)) {
2283					return false;
2284				}
2285			}
2286		}
2287	}
2288
2289	if(type == 'register') {
2290		// 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
2291		var register = d.getElementById('data_register_registration_method0');
2292		if(!register)
2293			register = d.getElementById('data[register][registration_method]0');
2294
2295		var simplified_pwd = d.getElementById('data_register_registration_method3');
2296		if(!simplified_pwd)
2297			simplified_pwd = d.getElementById('data[register][registration_method]3');
2298
2299		if((simplified_pwd && simplified_pwd.checked) || (register && register.checked) || (!simplified_pwd && !register)) {
2300			// check password
2301			if(typeof(varform.elements['data[register][password]']) != 'undefined' && typeof(varform.elements['data[register][password2]']) != 'undefined') {
2302				passwd = varform.elements['data[register][password]'];
2303				passwd2 = varform.elements['data[register][password2]'];
2304				if(passwd.value != passwd2.value) {
2305					alert(hikashopFieldsJs['password_different']);
2306					return false;
2307				}
2308			}
2309		}
2310
2311		//check email
2312		var emailField = varform.elements['data[register][email]'];
2313		emailField.value = emailField.value.replace(/ /g,"");
2314		var filter = /^([a-z0-9_'&\.\-\+])+\@(([a-z0-9\-])+\.)+([a-z0-9]{2,14})+$/i;
2315		if(!emailField || !filter.test(emailField.value)) {
2316			alert(hikashopFieldsJs['valid_email']);
2317			return false;
2318		}
2319	} else if(type == 'address' && typeof(varform.elements['data[address][address_telephone]']) != 'undefined') {
2320		var phoneField = varform.elements['data[address][address_telephone]'], filter = /[0-9]+/i;
2321		if(phoneField) {
2322			phoneField.value = phoneField.value.replace(/ /g,"");
2323			if(phoneField.value.length > 0 && !filter.test(phoneField.value)) {
2324				alert(hikashopFieldsJs['valid_phone']);
2325				return false;
2326			}
2327		}
2328	}
2329
2330	return true;
2331}
2332
2333function hikashopCheckField(elementToCheck, type, i, elementName, form) {
2334	if(!elementToCheck)
2335		return true;
2336
2337	var d = document, isValid = false;
2338	if(typeof(elementToCheck.value) != 'undefined') {
2339		if(elementToCheck.value == ' ' && typeof(form[elementName+'[]']) != 'undefined') {
2340			if(form[elementName+'[]'].checked) {
2341				isValid = true;
2342			} else {
2343				for(var a = form[elementName+'[]'].length - 1; a >= 0; a--) {
2344					if(form[elementName+'[]'][a].checked && form[elementName+'[]'][a].value.length > 0)
2345						isValid = true;
2346				}
2347			}
2348		} else if(elementToCheck.value.length > 0){
2349			var found = false;
2350			for(var j in hikashopFieldsJs['regexFieldsComp'][type]) {
2351				if(hikashopFieldsJs['regexFieldsComp'][type][j] == hikashopFieldsJs['reqFieldsComp'][type][i]) found = j;
2352			}
2353			if(typeof(hikashopFieldsJs['regexFieldsComp']) != 'undefined' && typeof(hikashopFieldsJs['regexFieldsComp'][type]) != 'undefined' && found){
2354				myregexp = new RegExp(hikashopFieldsJs['regexValueFieldsComp'][type][found]);
2355				if(myregexp.test(elementToCheck.value)){
2356					isValid = true;
2357				}
2358			}else{
2359				isValid = true;
2360			}
2361		}
2362	} else {
2363		for(var a = elementToCheck.length - 1; a >= 0; a--) {
2364			 if(elementToCheck[a].checked && elementToCheck[a].value.length > 0)
2365			 	isValid = true;
2366		}
2367	}
2368
2369	// Case for the switcher display, ignore check according to the method selected
2370	// joomla 3 ids are differents than joomla 1.5...
2371	var simplified_pwd = d.getElementById('data_register_registration_method3');
2372	if(!simplified_pwd) simplified_pwd = d.getElementById('data[register][registration_method]3');
2373
2374	var simplified = d.getElementById('data_register_registration_method1');
2375	if(!simplified) simplified = d.getElementById('data[register][registration_method]1');
2376
2377	var guest = d.getElementById('data_register_registration_method2');
2378	if(!guest) guest = d.getElementById('data[register][registration_method]2');
2379
2380	if(!isValid && ((simplified && simplified.checked) || (guest && guest.checked) ) && (elementName == 'data[register][password]' || elementName == 'data[register][password2]')){
2381		window.Oby.addClass(elementToCheck, 'invalid');
2382		return true;
2383	}
2384
2385	if(!isValid && ( (simplified && simplified.checked) || (guest && guest.checked) || (simplified_pwd && simplified_pwd.checked) ) && (elementName == 'data[register][name]' || elementName == 'data[register][username]')) {
2386		window.Oby.addClass(elementToCheck, 'invalid');
2387		return true;
2388	}
2389	if(!isValid) {
2390		window.Oby.addClass(elementToCheck, 'invalid');
2391		alert(hikashopFieldsJs['validFieldsComp'][type][i]);
2392		return false;
2393	} else {
2394		window.Oby.removeClass(elementToCheck, 'invalid');
2395	}
2396	return
2396 true;
2397}
2398
2399window.hikashop.ready(function(){
2400	if(window.jQuery && typeof(jQuery.noConflict) == "function" && !window.hkjQuery) {
2401		window.hkjQuery = jQuery.noConflict();
2402	}
2403	if(window.hikaVotes && typeof(initVote) == 'function')
2404		initVote();
2405	// timeout to make sure that everything is rendered before triggering the height calculations
2406	window.setTimeout(
2407		function(){
2408			window.hikashop.checkConsistency();
2409		},
2410		50
2411	);
2412});
2413if(window.jQuery && typeof(jQuery.noConflict) == "function" && !window.hkjQuery) {
2414	window.hkjQuery = jQuery.noConflict();
2415}

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.