1function getURLVar(key) { 2 var value = []; 3 4 var query = String(document.location).split('?'); 5 6 if (query[1]) { 7 var part = query[1].split('&'); 8 9 for (i = 0; i < part.length; i++) { 10 var data = part[i].split('='); 11 12 if (data[0] && data[1]) { 13 value[data[0]] = data[1]; 14 } 15 } 16 17 if (value[key]) { 18 return value[key]; 19 } else { 20 return ''; 21 } 22 } 23} 24 25// Observe 26+function($) { 27 $.fn.observe = function(callback) { 28 observer = new MutationObserver(callback); 29 30 observer.observe($(this)[0], { 31 characterData: false, 32 childList: true, 33 attributes: false 34 }); 35 }; 36}(jQuery); 37 38$(document).ready(function() { 39 // Tooltip 40 var oc_tooltip = function() { 41 // Get tooltip instance 42 tooltip = bootstrap.Tooltip.getInstance(this); 43 44 if (!tooltip) { 45 // Apply to current element 46 tooltip = bootstrap.Tooltip.getOrCreateInstance(this); 47 tooltip.show(); 48 } 49 } 50 51 $(document).on('mouseenter', '[data-bs-toggle=\'tooltip\']', oc_tooltip); 52 53 $(document).on('click', 'button', function() { 54 $('.tooltip').remove(); 55 }); 56 57 $('#alert').observe(function() { 58 window.setTimeout(function() { 59 $('#alert .alert-dismissible').fadeTo(3000, 0, function() { 60 $(this).remove(); 61 }); 62 }, 3000); 63 }); 64}); 65 66// Button 67$(document).ready(function() { 68 +function($) { 69 $.fn.button = function(state) { 70 return this.each(function() { 71 var element = this; 72 73 if (state == 'loading') { 74 this.html = $(element).html(); 75 this.state = $(element).prop('disabled'); 76 77 $(element).prop('disabled', true).width($(element).width()).html('<i class="fa-solid fa-circle-notch fa-spin text-light"></i>'); 78 } 79 80 if (state == 'reset') { 81 $(element).prop('disabled', this.state).width('').html(this.html); 82 } 83 }); 84 }; 85 }(jQuery); 86}); 87 88// Forms 89$(document).on('submit', 'form', function (e) { 90 var element = this; 91 var button = (e.originalEvent !== undefined && e.originalEvent.submitter !== undefined) ? e.originalEvent.submitter : ''; 92 93 if ($(element).attr('data-oc-toggle') == 'ajax' || $(button).attr('data-oc-toggle') == 'ajax') { 94 e.preventDefault(); 95 96 var form = e.target; 97 var action = $(button).attr('formaction') || $(form).attr('action'); 98 var method = $(button).attr('formmethod') || $(form).attr('method') || 'post'; 99 var enctype = $(button).attr('formenctype') || $(form).attr('enctype') || 'application/x-www-form-urlencoded'; 100 101 console.log(e); 102 console.log(element); 103 console.log('action ' + action); 104 console.log('button ' + button); 105 console.log('method ' + method); 106 console.log('enctype ' + enctype); 107 console.log($(element).serialize()); 108 109 // https://github.com/opencart/opencart/issues/9690 110 if (typeof CKEDITOR != 'undefined') { 111 for (instance in CKEDITOR.instances) { 112 CKEDITOR.instances[instance].updateElement(); 113 } 114 } 115 116 $.ajax({ 117 url: action.replaceAll('&', '&'), 118 type: method, 119 data: $(form).serialize(), 120 dataType: 'json', 121 contentType: enctype, 122 beforeSend: function () { 123 $(button).button('loading'); 124 }, 125 complete: function () { 126 $(button).button('reset'); 127 }, 128 success: function (json, textStatus) { 129 console.log(json); 130 console.log(textStatus); 131 132 $('.alert-dismissible').remove(); 133 $(element).find('.is-invalid').removeClass('is-invalid'); 134 $(element).find('.invalid-feedback').removeClass('d-block'); 135 136 if (json['redirect']) { 137 location = json['redirect']; 138 } 139 140 if (typeof json['error'] == 'string') { 141 $('#alert').prepend('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>'); 142 } 143 144 if (typeof json['error'] == 'object') { 145 if (json['error']['warning']) { 146 $('#alert').prepend('<div class="alert alert-danger alert-dismissible"><i class="fa-solid fa-circle-exclamation"></i> ' + json['error']['warning'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>'); 147 } 148 149 for (key in json['error']) { 150 $('#input-' + key.replaceAll('_', '-')).addClass('is-invalid').find('.form-control, .form-select, .form-check-input, .form-check-label').addClass('is-invalid'); 151 $('#error-' + key.replaceAll('_', '-')).html(json['error'][key]).addClass('d-block'); 152 } 153 } 154 155 if (json['success']) { 156 $('#alert').prepend('<div class="alert alert-success alert-dismissible"><i class="fa-solid fa-circle-check"></i> ' + json['success'] + ' <button type="button" class="btn-close" data-bs-dismiss="alert"></button></div>'); 157 158 // Refresh 159 var url = $(form).attr('data-oc-load'); 160 var target = $(form).attr('data-oc-target'); 161 162 if (url !== undefined && target !== undefined) { 163 $(target).load(url); 164 } 165 } 166 167 // Replace any form values that correspond to form names. 168 for (key in json) { 169 $(element).find('[name=\'' + key + '\']').val(json[key]); 170 } 171 }, 172 error: function (xhr, ajaxOptions, thrownError) { 173 console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText); 174 } 175 }); 176 } 177}); 178 179// Upload 180$(document).on('click', 'button[data-oc-toggle=\'upload\']', function() { 181 var element = this; 182 183 if (!$(element).prop('disabled')) { 184 $('#form-upload').remove(); 185 186 $('body').prepend('<form enctype="multipart/form-data" id="form-upload" style="display: none;"><input type="file" name="file" value=""/></form>'); 187 188 $('#form-upload input[name=\'file\']').trigger('click'); 189 190 $('#form-upload input[name=\'file\']').on('change', function(e) { 191 if ((this.files[0].size / 1024) > $(element).attr('data-oc-size-max')) { 192 alert($(element).attr('data-oc-size-error')); 193 194 $(this).val(''); 195 } 196 }); 197 198 if (typeof timer !== 'undefined') { 199 clearInterval(timer); 200 } 201 202 var timer = setInterval(function() { 203 if ($('#form-upload input[name=\'file\']').val() != '') { 204 clearInterval(timer); 205 206 $.ajax({ 207 url: $(element).attr('data-oc-url'), 208 type: 'post', 209 data: new FormData($('#form-upload')[0]), 210 dataType: 'json', 211 cache: false, 212 contentType: false, 213 processData: false, 214 beforeSend: function() { 215 $(element).button('loading'); 216 }, 217 complete: function() { 218 $(element).button('reset'); 219 }, 220 success: function(json) { 221 console.log(json); 222 223 if (json['error']) { 224 alert(json['error']); 225 } 226 227 if (json['success']) { 228 alert(json['success']); 229 } 230 231 if (json['code']) { 232 $($(element).attr('data-oc-target')).attr('value', json['code']); 233 } 234 }, 235 error: function(xhr, ajaxOptions, thrownError) { 236 console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText); 237 } 238 }); 239 } 240 }, 500); 241 } 242}); 243 244// Chain ajax calls. 245class Chain { 246 constructor() { 247 this.start = false;
248 this.data = []; 249 } 250 251 attach(call) { 252 this.data.push(call); 253 254 if (!this.start) { 255 this.execute(); 256 } 257 } 258 259 execute() { 260 if (this.data.length) { 261 this.start = true; 262 263 var call = this.data.shift(); 264 265 var jqxhr = call(); 266 267 jqxhr.done(function() { 268 chain.execute(); 269 }); 270 } else { 271 this.start = false; 272 } 273 } 274} 275 276var chain = new Chain(); 277 278// Autocomplete 279+function($) { 280 $.fn.autocomplete = function(option) { 281 return this.each(function() { 282 var element = this; 283 var $dropdown = $('#' + $(element).attr('data-oc-target')); 284 285 this.timer = null; 286 this.items = []; 287 288 $.extend(this, option); 289 290 // Focus in 291 $(element).on('focusin', function() { 292 element.request(); 293 }); 294 295 // Focus out 296 $(element).on('focusout', function(e) { 297 if (!e.relatedTarget || !$(e.relatedTarget).hasClass('dropdown-item')) { 298 $dropdown.removeClass('show'); 299 } 300 }); 301 302 // Input 303 $(element).on('input', function(e) { 304 element.request(); 305 }); 306 307 // Click 308 $dropdown.on('click', 'a', function(e) { 309 e.preventDefault(); 310 311 var value = $(this).attr('href'); 312 313 if (element.items[value] !== undefined) { 314 element.select(element.items[value]); 315 316 $dropdown.removeClass('show'); 317 } 318 }); 319 320 // Request 321 this.request = function() { 322 clearTimeout(this.timer); 323 324 $('#autocomplete-loading').remove(); 325 326 $dropdown.prepend('<li id="autocomplete-loading"><span class="dropdown-item text-center disabled"><i class="fa-solid fa-circle-notch fa-spin"></i></span></li>'); 327 $dropdown.addClass('show'); 328 329 this.timer = setTimeout(function(object) { 330 object.source($(object).val(), $.proxy(object.response, object)); 331 }, 150, this); 332 } 333 334 // Response 335 this.response = function(json) { 336 var html = ''; 337 var category = {}; 338 var name; 339 var i = 0, j = 0; 340 341 if (json.length) { 342 for (i = 0; i < json.length; i++) { 343 // update element items 344 this.items[json[i]['value']] = json[i]; 345 346 if (!json[i]['category']) { 347 // ungrouped items 348 html += '<li><a href="' + json[i]['value'] + '" class="dropdown-item">' + json[i]['label'] + '</a></li>'; 349 } else { 350 // grouped items 351 name = json[i]['category']; 352 353 if (!category[name]) { 354 category[name] = []; 355 } 356 357 category[name].push(json[i]); 358 } 359 } 360 361 for (name in category) { 362 html += '<li><h6 class="dropdown-header">' + name + '</h6></li>'; 363 364 for (j = 0; j < category[name].length; j++) { 365 html += '<li><a href="' + category[name][j]['value'] + '" class="dropdown-item">' + category[name][j]['label'] + '</a></li>'; 366 } 367 } 368 } 369 370 $dropdown.html(html); 371 } 372 }); 373 } 374}(jQuery); 375 376$(document).ready(function() { 377 // Currency 378 $('#form-currency .dropdown-item').on('click', function(e) { 379 e.preventDefault(); 380 381 $('#form-currency input[name=\'code\']').val($(this).attr('href')); 382 383 $('#form-currency').submit(); 384 }); 385 386 // Language 387 $('#form-language .dropdown-item').on('click', function(e) { 388 e.preventDefault(); 389 390 $('#form-language input[name=\'code\']').val($(this).attr('href')); 391 392 $('#form-language').submit(); 393 }); 394 395 // Product List 396 $('#button-list').on('click', function() { 397 var element = this; 398 399 $('#product-list').attr('class', 'row row-cols-1 product-list'); 400 401 $('#button-grid').removeClass('active'); 402 $('#button-list').addClass('active'); 403 404 localStorage.setItem('display', 'list'); 405 }); 406 407 // Product Grid 408 $('#button-grid').on('click', function() { 409 var element = this; 410 411 // What a shame bootstrap does not take into account dynamically loaded columns 412 $('#product-list').attr('class', 'row row-cols-1 row-cols-sm-2 row-cols-md-2 row-cols-lg-3'); 413 414 $('#button-list').removeClass('active'); 415 $('#button-grid').addClass('active'); 416 417 localStorage.setItem('display', 'grid'); 418 }); 419 420 // Local Storage 421 if (localStorage.getItem('display') == 'list') { 422 $('#product-list').attr('class', 'row row-cols-1 product-list'); 423 $('#button-list').addClass('active'); 424 } else { 425 $('#product-list').attr('class', 'row row-cols-1 row-cols-sm-2 row-cols-md-2 row-cols-lg-3'); 426 $('#button-grid').addClass('active'); 427 } 428 429 /* Agree to Terms */ 430 $('body').on('click', '.modal-link', function(e) { 431 e.preventDefault(); 432 433 var element = this; 434
435 $('#modal-information').remove(); 436 437 $.ajax({ 438 url: $(element).attr('href'), 439 dataType: 'html', 440 success: function(html) { 441 $('body').append(html); 442 443 $('#modal-information').modal('show'); 444 } 445 }); 446 }); 447 448 // Cookie Policy 449 $('#cookie button').on('click', function() { 450 var element = this; 451 452 $.ajax({ 453 url: $(this).val(), 454 type: 'get', 455 dataType: 'json', 456 beforeSend: function() { 457 $(element).button('loading'); 458 }, 459 complete: function() { 460 $(element).button('reset'); 461 }, 462 success: function(json) { 463 if (json['success']) { 464 $('#cookie').fadeOut(400, function() { 465 $('#cookie').remove(); 466 }); 467 } 468 }, 469 error: function(xhr, ajaxOptions, thrownError) { 470 console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText); 471 } 472 }); 473 }); 474});
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.