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