1(function (window, document, $, miniShop2Config) { 2 var miniShop2 = miniShop2 || {}; 3 miniShop2Config.callbacksObjectTemplate = function () { 4 return { 5 // return false to prevent send data 6 before: [], 7 response: { 8 success: [], 9 error: [] 10 }, 11 ajax: { 12 done: [], 13 fail: [], 14 always: [] 15 } 16 } 17 }; 18 miniShop2.Callbacks = miniShop2Config.Callbacks = { 19 Cart: { 20 add: miniShop2Config.callbacksObjectTemplate(), 21 remove: miniShop2Config.callbacksObjectTemplate(), 22 change: miniShop2Config.callbacksObjectTemplate(), 23 clean: miniShop2Config.callbacksObjectTemplate() 24 }, 25 Order: { 26 add: miniShop2Config.callbacksObjectTemplate(), 27 getcost: miniShop2Config.callbacksObjectTemplate(), 28 clean: miniShop2Config.callbacksObjectTemplate(), 29 submit: miniShop2Config.callbacksObjectTemplate(), 30 getrequired: miniShop2Config.callbacksObjectTemplate() 31 }, 32 }; 33 miniShop2.Callbacks.add = function (path, name, func) { 34 if (typeof func != 'function') { 35 return false; 36 } 37 path = path.split('.'); 38 var obj = miniShop2.Callbacks; 39 for (var i = 0; i < path.length; i++) { 40 if (obj[path[i]] == undefined) { 41 return false; 42 } 43 obj = obj[path[i]]; 44 } 45 if (typeof obj != 'object') { 46 obj = [obj]; 47 } 48 if (name != undefined) { 49 obj[name] = func; 50 } else { 51 obj.push(func); 52 } 53 return true; 54 }; 55 miniShop2.Callbacks.remove = function (path, name) { 56 path = path.split('.'); 57 var obj = miniShop2.Callbacks; 58 for (var i = 0; i < path.length; i++) { 59 if (obj[path[i]] == undefined) { 60 return false; 61 } 62 obj = obj[path[i]]; 63 } 64 if (obj[name] != undefined) { 65 delete obj[name]; 66 return true; 67 } 68 return false; 69 }; 70 miniShop2.ajaxProgress = false; 71 miniShop2.setup = function () { 72 // selectors & $objects 73 this.actionName = 'ms2_action'; 74 this.action = ':submit[name=' + this.actionName + ']'; 75 this.form = '.ms2_form'; 76 this.$doc = $(document); 77 78 this.sendData = { 79 $form: null, 80 action: null, 81 formData: null 82 }; 83 84 this.timeout = 300; 85 }; 86 miniShop2.initialize = function () { 87 miniShop2.setup(); 88 // Indicator of active ajax request 89 90 //noinspection JSUnresolvedFunction 91 miniShop2.$doc 92 .ajaxStart(function () { 93 miniShop2.ajaxProgress = true; 94 }) 95 .ajaxStop(function () { 96 miniShop2.ajaxProgress = false; 97 }) 98 .on('submit', miniShop2.form, function (e) { 99 e.preventDefault(); 100 var $form = $(this); 101 var action = $form.find(miniShop2.action).val(); 102 103 if (action) { 104 var formData = $form.serializeArray(); 105 formData.push({ 106 name: miniShop2.actionName, 107 value: action 108 }); 109 miniShop2.sendData = { 110 $form: $form, 111 action: action, 112 formData: formData 113 }; 114 miniShop2.controller(); 115 } 116 }); 117 miniShop2.Cart.initialize(); 118 miniShop2.Message.initialize(); 119 miniShop2.Order.initialize(); 120 miniShop2.Gallery.initialize(); 121 }; 122 miniShop2.controller = function () { 123 var self = this; 124 switch (self.sendData.action) { 125 case 'cart/add': 126 miniShop2.Cart.add(); 127 break; 128 case 'cart/remove': 129 miniShop2.Cart.remove(); 130 break; 131 case 'cart/change': 132 miniShop2.Cart.change(); 133 break; 134 case 'cart/clean': 135 miniShop2.Cart.clean(); 136 break; 137 case 'order/submit': 138 miniShop2.Order.submit(); 139 break; 140 case 'order/clean': 141 miniShop2.Order.clean(); 142 break; 143 default: 144 return; 145 } 146 }; 147 miniShop2.send = function (data, callbacks, userCallbacks) { 148 var runCallback = function (callback, bind) { 149 if (typeof callback == 'function') { 150 return callback.apply(bind, Array.prototype.slice.call(arguments, 2));
151 } else if (typeof callback == 'object') { 152 for (var i in callback) { 153 if (callback.hasOwnProperty(i)) { 154 var response = callback[i].apply(bind, Array.prototype.slice.call(arguments, 2)); 155 if (response === false) { 156 return false; 157 } 158 } 159 } 160 } 161 return true; 162 }; 163 // set context 164 if ($.isArray(data)) { 165 data.push({ 166 name: 'ctx', 167 value: miniShop2Config.ctx 168 }); 169 } else if ($.isPlainObject(data)) { 170 data.ctx = miniShop2Config.ctx; 171 } else if (typeof data == 'string') { 172 data += '&ctx=' + miniShop2Config.ctx; 173 } 174 175 // set action url 176 var formActionUrl = (miniShop2.sendData.$form) 177 ? miniShop2.sendData.$form.attr('action') 178 : false; 179 var url = (formActionUrl) 180 ? formActionUrl 181 : (miniShop2Config.actionUrl) 182 ? miniShop2Config.actionUrl 183 : document.location.href; 184 // set request method 185 var formMethod = (miniShop2.sendData.$form) 186 ? miniShop2.sendData.$form.attr('method') 187 : false; 188 var method = (formMethod) 189 ? formMethod 190 : 'post'; 191 192 // callback before 193 if (runCallback(callbacks.before) === false || runCallback(userCallbacks.before) === false) { 194 return; 195 } 196 // send 197 var xhr = function (callbacks, userCallbacks) { 198 return $[method](url, data, function (response) { 199 if (response.success) { 200 if (response.message) { 201 miniShop2.Message.success(response.message); 202 } 203 runCallback(callbacks.response.success, miniShop2, response); 204 runCallback(userCallbacks.response.success, miniShop2, response); 205 } else { 206 miniShop2.Message.error(response.message); 207 runCallback(callbacks.response.error, miniShop2, response); 208 runCallback(userCallbacks.response.error, miniShop2, response); 209 } 210 }, 'json').done(function () { 211 runCallback(callbacks.ajax.done, miniShop2, xhr); 212 runCallback(userCallbacks.ajax.done, miniShop2, xhr); 213 }).fail(function () { 214 runCallback(callbacks.ajax.fail, miniShop2, xhr); 215 runCallback(userCallbacks.ajax.fail, miniShop2, xhr); 216 }).always(function () { 217 runCallback(callbacks.ajax.always, miniShop2, xhr); 218 runCallback(userCallbacks.ajax.always, miniShop2, xhr); 219 }); 220 }(callbacks, userCallbacks); 221 }; 222 223 miniShop2.Cart = { 224 callbacks: { 225 add: miniShop2Config.callbacksObjectTemplate(), 226 remove: miniShop2Config.callbacksObjectTemplate(), 227 change: miniShop2Config.callbacksObjectTemplate(), 228 clean: miniShop2Config.callbacksObjectTemplate() 229 }, 230 setup: function () { 231 miniShop2.Cart.cart = '#msCart'; 232 miniShop2.Cart.miniCart = '#msMiniCart'; 233 miniShop2.Cart.miniCartClass = '.msMiniCart'; 234 miniShop2.Cart.miniCartNotEmptyClass = 'full'; 235 miniShop2.Cart.countInput = 'input[name=count]'; 236 miniShop2.Cart.totalWeight = '.ms2_total_weight'; 237 miniShop2.Cart.totalCount = '.ms2_total_count'; 238 miniShop2.Cart.totalCost = '.ms2_total_cost'; 239 miniShop2.Cart.totalDiscount = '.ms2_total_discount'; 240 miniShop2.Cart.cost = '.ms2_cost'; 241 }, 242 initialize: function () { 243 miniShop2.Cart.setup(); 244 if (!$(miniShop2.Cart.cart).length) { 245 return; 246 } 247 miniShop2.$doc.on('change', miniShop2.Cart.cart + ' ' + miniShop2.Cart.countInput, function () { 248 if (!!$(this).val()) { 249 $(this).closest(miniShop2.form).submit(); 250 } 251 }); 252 }, 253 add: function () { 254 var callbacks = miniShop2.Cart.callbacks; 255 callbacks.add.response.success = function (response) { 256 this.Cart.status(response.data); 257 }; 258 miniShop2.send(miniShop2.sendData.formData, miniShop2.Cart.callbacks.add, miniShop2.Callbacks.Cart.add); 259 }, 260 remove: function () { 261 var callbacks = miniShop2.Cart.callbacks; 262 callbacks.remove.response.success = function (response) { 263 this.Cart.remove_position(miniShop2.Utils.getValueFromSerializedArray('key')); 264 this.Cart.status(response.data); 265 }; 266 miniShop2.send(miniShop2.sendData.formData, miniShop2.Cart.callbacks.remove, miniShop2.Callbacks.Cart.remove); 267 }, 268 change: function () { 269 var callbacks = miniShop2.Cart.callbacks; 270 callbacks.change.response.success = function (response) { 271 if (typeof (response.data.key) == 'undefined') { 272 this.Cart.remove_position(miniShop2.Utils.getValueFromSerializedArray('key')); 273 } else { 274 $('#' + miniShop2.Utils.getValueFromSerializedArray('key')).find(''); 275 } 276 this.Cart.status(response.data); 277 }; 278 miniShop2.send(miniShop2.sendData.formData, miniShop2.Cart.callbacks.change, miniShop2.Callbacks.Cart.change); 279 }, 280 status: function (status) { 281 if (status['total_count'] < 1) { 282 location.reload(); 283 } else { 284 //var $cart = $(miniShop2.Cart.cart); 285 var $miniCarts = $(miniShop2.Cart.miniCart).add(miniShop2.Cart.miniCartClass); 286 if (status['total_count'] > 0 && $miniCarts.length > 0) { 287 $miniCarts.each(function (index, cart) { 288 if (!$(cart).hasClass(miniShop2.Cart.miniCartNotEmptyClass)) { 289 $(cart).addClass(miniShop2.Cart.miniCartNotEmptyClass); 290 } 291 }); 292 } 293 $(miniShop2.Cart.totalWeight).text(miniShop2.Utils.formatWeight(status['total_weight'])); 294 $(miniShop2.Cart.totalCount).text(status['total_count']); 295 $(miniShop2.Cart.totalCost).text(miniShop2.Utils.formatPrice(status['total_cost'])); 296 $(miniShop2.Cart.totalDiscount).text(miniShop2.Utils.formatPrice(status['total_discount'])); 297 if (typeof(status['cost']) === 'number') { 298 $(miniShop2.Cart.cost, '#' + status['key']).text(miniShop2.Utils.formatPrice(status['cost'])); 299 } 300 if ($(miniShop2.Order.orderCost, miniShop2.Order.order).length) { 301 miniShop2.Order.getcost(); 302 } 303 } 304 }, 305 clean: function () { 306 var callbacks = miniShop2.Cart.callbacks; 307 callbacks.clean.response.success = function (response) { 308 this.Cart.status(response.data); 309 }; 310 311 miniShop2.send(miniShop2.sendData.formData, miniShop2.Cart.callbacks.clean, miniShop2.Callbacks.Cart.clean); 312 }, 313 remove_position: function (key) { 314 $('#' + key).remove(); 315 } 316 }; 317 318 miniShop2.Gallery = { 319 setup: function () { 320 miniShop2.Gallery.gallery = $('#msGallery'); 321 miniShop2.Gallery.files = miniShop2.Gallery.gallery.find('.fotorama'); 322 }, 323 initialize: function () { 324 miniShop2.Gallery.setup(); 325 if (miniShop2.Gallery.files.length) { 326 $('<link/>', { 327 rel: 'stylesheet', 328 type: 'text/css', 329 href: miniShop2Config.cssUrl + 'lib/fotorama.min.css', 330 }).appendTo('head'); 331 $('<script/>', { 332 type: 'text/javascript', 333 src: miniShop2Config.jsUrl + 'lib/fotorama.min.js', 334 }).appendTo('head'); 335 } 336 337 // fix size gallery 338 miniShop2.$doc.on('fotorama:ready', miniShop2.Gallery.files, function (e, Fotorama, extra) { 339 if ((src = Fotorama.activeFrame.src)) { 340 measure = $.Fotorama.measures[src]; 341 if (measure === undefined) { 342 for (i in $.Fotorama.measures) { 343 measure = $.Fotorama.measures[i]; 344 break; 345 } 346 Fotorama.resize(measure); 347 } 348 } 349 }); 350 351 } 352 }; 353 354 miniShop2.Order = { 355 callbacks: { 356 add: miniShop2Config.callbacksObjectTemplate(), 357 getcost: miniShop2Config.callbacksObjectTemplate(), 358 clean: miniShop2Config.callbacksObjectTemplate(), 359 submit: miniShop2Config.callbacksObjectTemplate(), 360 getrequired: miniShop2Config.callbacksObjectTemplate() 361 }, 362 setup: function () { 363 miniShop2.Order.order = '#msOrder'; 364 miniShop2.Order.deliveries = '#deliveries'; 365 miniShop2.Order.payments = '#payments'; 366 miniShop2.Order.deliveryInput = 'input[name="delivery"]'; 367 miniShop2.Order.inputParent = '.input-parent'; 368 miniShop2.Order.paymentInput = 'input[name="payment"]'; 369 miniShop2.Order.paymentInputUniquePrefix = 'input#payment_'; 370 miniShop2.Order.deliveryInputUniquePrefix = 'input#delivery_'; 371 miniShop2.Order.orderCost = '#ms2_order_cost'; 372 miniShop2.Order.cartCost = '#ms2_order_cart_cost'; 373 miniShop2.Order.deliveryCost = '#ms2_order_delivery_cost'; 374 }, 375 initialize: function () { 376 miniShop2.Order.setup(); 377 if ($(miniShop2.Order.order).length) { 378 miniShop2.$doc 379 .on('click', miniShop2.Order.order + ' [name="' + miniShop2.actionName + '"][value="order/clean"]', function (e) { 380 miniShop2.Order.clean(); 381 e.preventDefault(); 382 }) 383 .on('change', miniShop2.Order.order + ' input,' + miniShop2.Order.order + ' textarea', function () { 384 var $this = $(this); 385 var key = $this.attr('name'); 386 if (!key) return; 387 var value = $this.val(); 388 miniShop2.Order.add(key, value); 389 }); 390 var $deliveryInputChecked = $(miniShop2.Order.deliveryInput + ':checked', miniShop2.Order.order); 391 $deliveryInputChecked.trigger('change'); 392 } 393 }, 394 updatePayments: function (payments) { 395 var $paymentInputs = $(miniShop2.Order.paymentInput, miniShop2.Order.order); 396 $paymentInputs.attr('disabled', true).prop('disabled', true).closest(miniShop2.Order.inputParent).hide(); 397 if (payments.length > 0) { 398 for (var i in payments) { 399 if (payments.hasOwnProperty(i)) { 400 $paymentInputs.filter(miniShop2.Order.paymentInputUniquePrefix + payments[i]).attr('disabled', false).prop('disabled', false).closest(miniShop2.Order.inputParent).show(); 401 } 402 } 403 } 404 if ($paymentInputs.filter(':visible:checked').length == 0) { 405 $paymentInputs.filter(':visible:first').trigger('click'); 406 } 407 }, 408 add: function (key, value) { 409 var callbacks = miniShop2.Order.callbacks; 410 var old_value = value; 411 callbacks.add.response.success = function (response) { 412 (function (key, value, old_value) { 413 var $field = $('[name="' + key + '"]', miniShop2.Order.order); 414 switch (key) { 415 case 'delivery': 416 $field = $(miniShop2.Order.deliveryInputUniquePrefix + response.data[key]); 417 if (response.data[key] != old_value) { 418 $field.trigger('click'); 419 } else { 420 miniShop2.Order.getrequired(value); 421 miniShop2.Order.updatePayments($field.data('payments')); 422 miniShop2.Order.getcost(); 423 } 424 break; 425 case 'payment': 426 $field = $(miniShop2.Order.paymentInputUniquePrefix + response.data[key]); 427 if (response.data[key] != old_value) { 428 $field.trigger('click'); 429 } else { 430 miniShop2.Order.getcost(); 431 } 432 break; 433 //default: 434 } 435 $field.val(response.data[key]).removeClass('error').closest(miniShop2.Order.inputParent).removeClass('error'); 436 })(key, value, old_value); 437 }; 438 callbacks.add.response.error = function () { 439 (function (key) { 440 var $field = $('[name="' + key + '"]', miniShop2.Order.order); 441 if ($field.attr('type') == 'checkbox' || $field.attr('type') == 'radio') { 442 $field.closest(miniShop2.Order.inputParent).addClass('error'); 443 } else { 444 $field.addClass('error'); 445 } 446 })(key); 447 }; 448 449 var data = { 450 key: key, 451 value: value 452 }; 453 data[miniShop2.actionName] = 'order/add'; 454 miniShop2.send(data, miniShop2.Order.callbacks.add, miniShop2.Callbacks.Order.add); 455 }, 456 getcost: function () { 457 var callbacks = miniShop2.Order.callbacks; 458 callbacks.getcost.response.success = function (response) { 459 $(miniShop2.Order.orderCost, miniShop2.Order.order).text(miniShop2.Utils.formatPrice(response.data['cost'])); 460 $(miniShop2.Order.cartCost, miniShop2.Order.order).text(miniShop2.Utils.formatPrice(response.data['cart_cost'])); 461 $(miniShop2.Order.deliveryCost, miniShop2.Order.order).text(miniShop2.Utils.formatPrice(response.data['delivery_cost'])); 462 }; 463 var data = {}; 464 data[miniShop2.actionName] = 'order/getcost'; 465 miniShop2.send(data, miniShop2.Order.callbacks.getcost, miniShop2.Callbacks.Order.getcost); 466 }, 467 clean: function () { 468 var callbacks = miniShop2.Order.callbacks; 469 callbacks.clean.response.success = function () { 470 location.reload(); 471 }; 472 473 var data = {}; 474 data[miniShop2.actionName] = 'order/clean'; 475 miniShop2.send(data, miniShop2.Order.callbacks.clean, miniShop2.Callbacks.Order.clean); 476 }, 477 submit: function () { 478 miniShop2.Message.close(); 479 480 // Checking for active ajax request 481 if (miniShop2.ajaxProgress) { 482 //noinspection JSUnresolvedFunction 483 miniShop2.$doc.ajaxComplete(function () { 484 miniShop2.ajaxProgress = false; 485 miniShop2.$doc.unbind('ajaxComplete'); 486 miniShop2.Order.submit(); 487 }); 488 return false; 489 } 490 491 var callbacks = miniShop2.Order.callbacks; 492 callbacks.submit.before = function () { 493 $(':button, a', miniShop2.Order.order).attr('disabled', true).prop('disabled', true); 494 }; 495
495 callbacks.submit.response.success = function (response) { 496 if (response.data['redirect']) { 497 document.location.href = response.data['redirect']; 498 } else if (response.data['msorder']) { 499 document.location.href = document.location.origin + document.location.pathname 500 + (document.location.search ? document.location.search + '&' : '?') 501 + 'msorder=' + response.data['msorder']; 502 } else { 503 location.reload(); 504 } 505 }; 506 callbacks.submit.response.error = function (response) { 507 setTimeout((function () { 508 $(':button, a', miniShop2.Order.order).attr('disabled', false).prop('disabled', false); 509 }.bind(this)), 3 * miniShop2.timeout); 510 $('[name]', miniShop2.Order.order).removeClass('error').closest(miniShop2.Order.inputParent).removeClass('error'); 511 for (var i in response.data) { 512 if (response.data.hasOwnProperty(i)) { 513 var key = response.data[i]; 514 //var $field = $('[name="' + response.data[i] + '"]', miniShop2.Order.order); 515 //$field.addClass('error').closest(miniShop2.Order.inputParent).addClass('error'); 516 var $field = $('[name="' + key + '"]', miniShop2.Order.order); 517 if ($field.attr('type') == 'checkbox' || $field.attr('type') == 'radio') { 518 $field.closest(miniShop2.Order.inputParent).addClass('error'); 519 } else { 520 $field.addClass('error'); 521 } 522 } 523 } 524 }; 525 return miniShop2.send(miniShop2.sendData.formData, miniShop2.Order.callbacks.submit, miniShop2.Callbacks.Order.submit); 526 }, 527 getrequired: function (value) { 528 var callbacks = miniShop2.Order.callbacks; 529 callbacks.getrequired.response.success = function (response) { 530 $('[name]', miniShop2.Order.order).removeClass('required').closest(miniShop2.Order.inputParent).removeClass('required'); 531 var requires = response.data['requires']; 532 for (var i = 0, length = requires.length; i < length; i++) { 533 $('[name=' + requires[i] + ']', miniShop2.Order.order).addClass('required').closest(miniShop2.Order.inputParent).addClass('required'); 534 } 535 }; 536 callbacks.getrequired.response.error = function () { 537 $('[name]', miniShop2.Order.order).removeClass('required').closest(miniShop2.Order.inputParent).removeClass('required'); 538 }; 539 540 var data = { 541 id: value 542 }; 543 data[miniShop2.actionName] = 'order/getrequired'; 544 miniShop2.send(data, miniShop2.Order.callbacks.getrequired, miniShop2.Callbacks.Order.getrequired); 545 } 546 }; 547 548 miniShop2.Message = { 549 initialize: function () { 550 }, 551 close: function () { 552 }, 553 show: function (message) { 554 if (message != '') { 555 alert(message); 556 } 557 }, 558 success: function (message) { 559 }, 560 error: function (message) { 561 }, 562 info: function (message) { 563 } 564 }; 565 566 miniShop2.Utils = { 567 empty: function (val) { 568 return (typeof (val) == 'undefined' || val == 0 || val === null || val === false || (typeof (val) == 'string' && val.replace(/\s+/g, '') == '') || (typeof (val) == 'object' && val.length == 0)); 569 }, 570 formatPrice: function (price) { 571 var pf = miniShop2Config.price_format; 572 price = this.number_format(price, pf[0], pf[1], pf[2]); 573 574 if (miniShop2Config.price_format_no_zeros && pf[0] > 0) { 575 price = price.replace(/(0+)$/, ''); 576 price = price.replace(/[^0-9]$/, ''); 577 } 578 579 return price; 580 }, 581 formatWeight: function (weight) { 582 var wf = miniShop2Config.weight_format; 583 weight = this.number_format(weight, wf[0], wf[1], wf[2]); 584 585 if (miniShop2Config.weight_format_no_zeros && wf[0] > 0) { 586 weight = weight.replace(/(0+)$/, ''); 587 weight = weight.replace(/[^0-9]$/, ''); 588 } 589 590 return weight; 591 }, 592 // Format a number with grouped thousands, 593 number_format: function (number, decimals, dec_point, thousands_sep) { 594 // original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com) 595 // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) 596 // bugfix by: Michael White (http://crestidg.com) 597 var i, j, kw, kd, km; 598 599 // input sanitation & defaults 600 if (isNaN(decimals = Math.abs(decimals))) { 601 decimals = 2; 602 } 603 if (dec_point == undefined) { 604 dec_point = ','; 605 } 606 if (thousands_sep == undefined) { 607 thousands_sep = '.'; 608 } 609 610 i = parseInt(number = (+number || 0).toFixed(decimals)) + ''; 611 612 if ((j = i.length) > 3) { 613 j = j % 3; 614 } else { 615 j = 0; 616 } 617 618 km = j 619 ? i.substr(0, j) + thousands_sep 620 : ''; 621 kw = i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousands_sep); 622 kd = (decimals 623 ? dec_point + Math.abs(number - i).toFixed(decimals).replace(/-/, '0').slice(2) 624 : ''); 625 626 return km + kw + kd; 627 }, 628 getValueFromSerializedArray: function (name, arr) { 629 if (!$.isArray(arr)) { 630 arr = miniShop2.sendData.formData; 631 } 632 for (var i = 0, length = arr.length; i < length; i++) { 633 if (arr[i].name == name) { 634 return arr[i].value; 635 } 636 } 637 return null; 638 } 639 }; 640 641 $(document).ready(function ($) { 642 miniShop2.initialize(); 643 var html = $('html'); 644 html.removeClass('no-js'); 645 if (!html.hasClass('js')) { 646 html.addClass('js'); 647 } 648 });
649 650 window.miniShop2 = miniShop2; 651})(window, document, jQuery, miniShop2Config);
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.