PageSourceSearch

https://www.gallerycolor.nl/themes/gallerycolor16/js/modules/blockcart/ajax-cart.js?js_v=1775116328

js gallerycolor.nl collected 2026-10-08 17:07:46 UTC 31,488 bytes, 814 lines download raw bytes

1/* global generated_date, baseDir, contentOnly, fieldRequired, freeProductTranslation, delete_txt,
2 orderProcess, CUSTOMIZE_TEXTFIELD, customizationIdMessage, freeShippingTranslation, toBeDetermined */
3$(function() {
4
5  ajaxCart.overrideButtonsInThePage();
6
7  var current_timestamp = parseInt(new Date().getTime() / 1000);
8
9  if (typeof $('.ajax_cart_quantity').html() == 'undefined' || (typeof generated_date != 'undefined' && generated_date != null && (parseInt(generated_date) + 30) < current_timestamp))
10    ajaxCart.refresh();
11
12  /** Hover observers */
13  var oBlockcartDropDown = new HoverWatcher('#blockcart-dropdown');
14  var oBlockcart         = new HoverWatcher('#blockcart');
15  var $cartDropDown      = $('#blockcart-dropdown');
16  var $cartHeader        = $('#blockcart-header');
17  var is_touch_enabled   = ('ontouchstart' in document.documentElement);
18
19  var hoverCollapseTimeout = 200;
20
21  $cartHeader.on({
22    mouseenter: function() {
23      if (ajaxCart.nb_total_products > 0 || parseInt($('.ajax_cart_quantity').html()) > 0)
24        $cartDropDown.stop(true, true).slideDown();
25    },
26    mouseleave: function() {
27      setTimeout(function() {
28        if (!oBlockcart.isHoveringOver() && !oBlockcartDropDown.isHoveringOver())
29          $cartDropDown.stop(true, true).slideUp();
30      }, hoverCollapseTimeout);
31    },
32    click: function(e) {
33      e.preventDefault();
34      e.stopPropagation();
35
36      // Simulate hover when browser says device is touch based
37      if (is_touch_enabled) {
38        if ($(this).next('.cart_block:visible').length && !oBlockcartDropDown.isHoveringOver()) {
39          $cartDropDown.stop(true, true).slideUp();
40        } else if (ajaxCart.nb_total_products > 0 || parseInt($('.ajax_cart_quantity').html()) > 0) {
41          $cartDropDown.stop(true, true).slideDown();
42        }
43        return false;
44      } else {
45        window.location.href = $(this).attr('href');
46      }
47    }
48  });
49
50  $cartDropDown.on('mouseleave', function() {
51    setTimeout(function() {
52      if (!oBlockcart.isHoveringOver()) {
53        $cartDropDown.stop(true, true).slideUp();
54      }
55    }, hoverCollapseTimeout);
56  });
57
58  $(document).on('click', '.delete_voucher', function(e) {
59    e.preventDefault();
60    $.ajax({
61      type: 'POST',
62      headers: {'cache-control': 'no-cache'},
63      async: true,
64      cache: false,
65      url: $(this).attr('href') + '?rand=' + new Date().getTime()
66    });
67    $(this).parent().parent().remove();
68    ajaxCart.refresh();
69    var bodyId = $('body').attr('id');
70    if (bodyId == 'order' || bodyId == 'order-opc') {
71      if (typeof(updateAddressSelection) != 'undefined') {
72        updateAddressSelection();
73      } else {
74        window.location.reload();
75      }
76    }
77  });
78
79  $(document).on('click', '#cart_navigation input', function() {
80    $(this).prop('disabled', 'disabled').addClass('disabled');
81    $(this).closest('form').get(0).submit();
82  });
83
84  $(document).on('click', '#layer_cart .cross, #layer_cart .continue, .layer_cart_overlay', function(e) {
85    e.preventDefault();
86    $('.layer_cart_overlay').hide();
87    $('#layer_cart').fadeOut('fast');
88  });
89
90  $('#columns #layer_cart, #columns .layer_cart_overlay').detach().prependTo('#columns');
91});
92
93//JS Object : update the cart by ajax actions
94var ajaxCart = {
95
96  nb_total_products: 0,
97
98  //override every button in the page in relation to the cart
99  overrideButtonsInThePage: function() {
100    //for every 'add' buttons...
101    $(document).off('click', '.ajax_add_to_cart_button').on('click', '.ajax_add_to_cart_button', function(e) {
102      e.preventDefault();
103      var idProduct          = parseInt($(this).data('id-product'));
104      var idProductAttribute = parseInt($(this).data('id-product-attribute'));
105      var minimalQuantity    = parseInt($(this).data('minimal_quantity')) || 1;
106
107      if ($(this).prop('disabled') != 'disabled')
108        ajaxCart.add(idProduct, idProductAttribute, false, this, minimalQuantity);
109    });
110    //for product page 'add' button...
111    //if ($('.cart_block').length) {
112      $(document).off('click', '#add_to_cart button').on('click', '#add_to_cart button', function(e) {
113        e.preventDefault();
114        ajaxCart.add($('#product_page_product_id').val(), $('#idCombination').val(), true, null, $('#quantity_wanted').val(), null);
115      });
116    //}
117
118    //for 'delete' buttons in the cart block...
119    $(document).off('click', '.cart_block_list .ajax_cart_block_remove_link').on('click', '.cart_block_list .ajax_cart_block_remove_link', function(e) {
120      e.preventDefault();
121      // Customized product management
122      var customizationId = 0;
123      var productId = 0;
124      var productAttributeId = 0;
125      var customizableProductDiv = $($(this).parent().parent()).find('div[data-id^=deleteCustomizableProduct_]');
126      var idAddressDelivery = false;
127
128      if (customizableProductDiv && $(customizableProductDiv).length) {
129        var ids = customizableProductDiv.data('id').split('_');
130        if (typeof(ids[1]) != 'undefined') {
131          customizationId = parseInt(ids[1]);
132          productId = parseInt(ids[2]);
133          if (typeof(ids[3]) != 'undefined')
134            productAttributeId = parseInt(ids[3]);
135          if (typeof(ids[4]) != 'undefined')
136            idAddressDelivery = parseInt(ids[4]);
137        }
138      }
139
140      // Common product management
141      if (!customizationId) {
142        //retrieve idProduct and idCombination from the displayed product in the block cart
143        var firstCut = $(this).parent().parent().data('id').replace('cart_block_product_', '');
144        firstCut = firstCut.replace('deleteCustomizableProduct_', '');
145        ids = firstCut.split('_');
146        productId = parseInt(ids[0]);
147
148        if (typeof(ids[1]) != 'undefined')
149          productAttributeId = parseInt(ids[1]);
150        if (typeof(ids[2]) != 'undefined')
151          idAddressDelivery = parseInt(ids[2]);
152      }
153
154      // Removing product from the cart
155      ajaxCart.remove(productId, productAttributeId, customizationId, idAddressDelivery);
156    });
157  },
158
159  // try to expand the cart
160  expand: function() {
161    // disabled
162  },
163
164  // try to collapse the cart
165  collapse: function() {
166    // disabled
167  },
168  // Fix display when using back and previous browsers buttons
169  refresh: function() {
170    $.ajax({
171      type: 'POST',
172      headers: {'cache-control': 'no-cache'},
173      url: (typeof(baseUri) !== 'undefined') ? baseUri + '?rand=' + new Date().getTime() : '',
174      async: true,
175      cache: false,
176      dataType: 'json',
177      data: (typeof(static_token) !== 'undefined') ? 'controller=cart&ajax=true&token=' + static_token : '',
178      success: function(jsonData) {
179        ajaxCart.updateCart(jsonData);
180      }
181    });
182  },
183
184  // Update the cart information
185  updateCartInformation: function(jsonData, addedFromProductPage) {
186    ajaxCart.updateCart(jsonData);
187    var $productPageBtn = $('#add_to_cart').find('button');
188    // reactive the button when adding has finished
189    if (addedFromProductPage) {
190      $productPageBtn.removeProp('disabled').removeClass('disabled');
191      $productPageBtn.toggleClass('added', !jsonData.hasError || jsonData.hasError == false);
192    } else
193      $('.ajax_add_to_cart_button').removeProp('disabled');
194  },
195
196  // close fancybox
197  updateFancyBox: function() {},
198
199  // add a product in the cart via ajax
200  add: function(idProduct, idCombination, addedFromProductPage, callerElement, quantity, whishlist) {
201
202    if (addedFromProductPage && !checkCustomizations()) {
203      if (contentOnly) {
204        window.parent.location.href = window.location.href.replace('content_only=1', '');
205        return;
206      }
207      PrestaShop.showError(fieldRequired);
208      return;
209    }
210
211    var $productPageBtn = $('#add_to_cart').find('button');
212
213    //disabled the button when adding to not double add if user double click
214    if (addedFromProductPage) {
215      $productPageBtn.prop('disabled', 'disabled').addClass('disabled');
216      $('.filled').removeClass('filled');
217    } else
218      $(callerElement).prop('disabled', 'disabled');
219
220    //send the ajax request to the server
221
222    $.ajax({
223      type: 'POST',
224      headers: {'cache-control': 'no-cache'},
225      url: baseUri + '?rand=' + new Date().getTime(),
226      async: true,
227      cache: false,
228      dataType: 'json',
229      data: 'controller=cart&add=1&ajax=true&qty=' + ((quantity && quantity != null) ? quantity : '1') + '&id_product=' +
230      idProduct + '&token=' + static_token + ((parseInt(idCombination) && idCombination != null) ? '&ipa=' +
231      parseInt(idCombination) : '' + '&id_customization=' + ((typeof customizationId !== 'undefined') ? customizationId : 0)),
232
233      /**
234       * @param {{ errors, hasError, crossSelling, products }} jsonData
235       */
236      success: function(jsonData) {
237        // add appliance to wishlist module
238        if (whishlist && !jsonData.errors) {
239          WishlistAddProductCart(whishlist[0], idProduct, idCombination, whishlist[1]);
240        }
241
242        if (!jsonData.hasError) {
243          if (contentOnly) {
244            window.parent.ajaxCart.updateCartInformation(jsonData, addedFromProductPage);
245          } else {
246            ajaxCart.updateCartInformation(jsonData, addedFromProductPage);
247          }
248
249          if (jsonData.crossSelling) {
250            $('.crossseling').html(jsonData.crossSelling);
251          }
252
253          if (idCombination) {
254            $(jsonData.products).each(function() {
255              if (this.id != undefined && this.id == parseInt(idProduct) && this.idCombination == parseInt(idCombination)) {
256                if (contentOnly) {
257                  window.parent.ajaxCart.updateLayer(this);
258                } else {
259                  ajaxCart.updateLayer(this);
260                }
261              }
262            });
263          } else {
264            $(jsonData.products).each(function() {
265              if (this.id != undefined && this.id == parseInt(idProduct)) {
266                if (contentOnly) {
267                  window.parent.ajaxCart.updateLayer(this);
268                } else {
269                  ajaxCart.updateLayer(this);
270                }
271              }
272            });
273          }
274
275          if (contentOnly) {
276            parent.$.fancybox.close();
277          }
278
279        } else {
280          if (contentOnly) {
281            window.parent.ajaxCart.updateCart(jsonData);
282          } else {
283            ajaxCart.updateCart(jsonData);
284          }
285
286          if (addedFromProductPage) {
287            $productPageBtn.removeProp('disabled').removeClass('disabled');
288          } else {
289            $(callerElement).removeProp('disabled');
290          }
291        }
292
293        emptyCustomizations();
294
295      },
296      error: function(XMLHttpRequest, textStatus, errorThrown) {
297        PrestaShop.showError(
298          'Impossible to add the product to the cart.<br/>textStatus: \'' + textStatus + '\'<br/>errorThrown: \'' +
299          errorThrown + '\'<br/>responseText:<br/>' + XMLHttpRequest.responseText
300        );
301        // Reactivate the button when adding has finished
302        if (addedFromProductPage) {
303          $productPageBtn.removeProp('disabled').removeClass('disabled');
304        } else {
305          $(callerElement).removeProp('disabled');
306        }
307      }
308    });
309  },
310
311  //remove a product from the cart via ajax
312  remove: function(idProduct, idCombination, customizationId, idAddressDelivery) {
313    //send the ajax request to the server
314    $.ajax({
315      type: 'POST',
316      headers: {'cache-control': 'no-cache'},
317      url: baseUri + '?rand=' + new Date().getTime(),
318      async: true,
319      cache: false,
320      dataType: 'json',
321      data: 'controller=cart&delete=1&id_product=' + idProduct + '&ipa=' + ((idCombination != null && parseInt(idCombination)) ? idCombination : '') +
322      ((customizationId && customizationId != null) ? '&id_customization=' + customizationId : '') + '&id_address_delivery=' +
323      idAddressDelivery + '&token=' + static_token + '&ajax=true',
324      success: function(jsonData) {
325        ajaxCart.updateCart(jsonData);
326        var bodyId = $('body').attr('id');
327        if (bodyId == 'order' || bodyId == 'order-opc') {
328          deleteProductFromSummary(idProduct + '_' + idCombination + '_' + customizationId + '_' + idAddressDelivery);
329        }
330      },
331      error: function() {
332        PrestaShop.showError('ERROR: unable to delete the product');
333      }
334    });
335  },
336
337  //hide the products displayed in the page but no more in the json data
338  hideOldProducts: function(jsonData) {
339    //delete an eventually removed product of the displayed cart (only if cart is not empty!)
340    if ($('.cart_block_list:first dl.products').length > 0) {
341      var removedProductId = null;
342
343      //look for a product to delete...
344      $('.cart_block_list:first dl.products dt').each(function() {
345        //retrieve idProduct and idCombination from the displayed product in the block cart
346        var domIdProduct = $(this).data('id');
347        var firstCut = domIdProduct.replace('cart_block_product_', '');
348        var ids = firstCut.split('_');
349
350        //try to know if the current product is still in the new list
351        var stayInTheCart = false;
352        for (var aProduct in jsonData.products) {
353          if (jsonData.products.hasOwnProperty(aProduct)) {
354            //we've called the variable aProduct because IE6 bug if this variable is called product
355            //if product has attributes
356            if (jsonData.products[aProduct]['id'] == ids[0] && (!ids[1] || jsonData.products[aProduct]['idCombination'] == ids[1])) {
357              stayInTheCart = true;
358              // update the product customization display (when the product is still in the cart)
359              ajaxCart.hideOldProductCustomizations(jsonData.products[aProduct], domIdProduct);
360            }
361          }
362        }
363        //remove product if it's no more in the cart
364        if (!stayInTheCart) {
365          removedProductId = $(this).data('id');
366          if (removedProductId != null) {
367            firstCut = removedProductId.replace('cart_block_product_', '');
368            ids = firstCut.split('_');
369
370            $('dt[data-id="' + removedProductId + '"]').addClass('strike').fadeTo('slow', 0, function() {
371              $(this).slideUp('slow', function() {
372                $(this).remove();
373                // If the cart is now empty, show the 'no product in the cart' message and close detail
374                if ($('.cart_block:first dl.products dt').length == 0) {
375                  $('.ajax_cart_quantity').html('0');
376                  $('#header .cart_block').stop(true, true).slideUp();
377                  $('.cart_block_no_products:hidden').slideDown();
378                  $('.cart_block dl.products').remove();
379                }
380              });
381            });
382
383            $('dd[data-id="cart_block_combination_of_' + ids[0] + (ids[1] ? '_' + ids[1] : '') + (ids[2] ? '_' + ids[2] : '') + '"]').fadeTo('fast', 0, function() {
384              $(this).slideUp('fast', function() {
385                $(this).remove();
386              });
387            });
388          }
389        }
390      });
391    }
392  },
393
394  /**
395   * @param {{ id, idCombination, hasCustomizedDatas, is_gift }} product
396   * @param domIdProduct
397   */
398  hideOldProductCustomizations: function(product, domIdProduct) {
399    var $customizationList = $('ul[data-id="customization_' + product['id'] + '_' + product['idCombination'] + '"]');
400    if ($customizationList.length > 0) {
401      $($customizationList).find('li').each(function() {
402        $(this).find('.deleteCustomizableProduct').each(function() {
403          var customizationDiv = $(this).data('id');
404          var tmp = customizationDiv.replace('deleteCustomizableProduct_', '');
405          var ids = tmp.split('_');
406          if ((parseInt(product.idCombination) == parseInt(ids[2])) && !ajaxCart.doesCustomizationStillExist(product, ids[0])) {
407            $('div[data-id="' + customizationDiv + '"]').parent().fadeTo('slow', 0, function() {
408              $(this).slideUp().remove();
409            });
410          }
411        });
412      });
413    }
414
415    var $removeLinks = $('.deleteCustomizableProduct[data-id="' + domIdProduct + '"]').find('.ajax_cart_block_remove_link');
416
417    // @TODO This is never called
418    if (!product.hasCustomizedDatas && !$removeLinks.length) {
419      $('div[data-id="' + domIdProduct + '"] span.remove_link').html('<a class="ajax_cart_block_remove_link" rel="nofollow" href="' +
420        baseUri + '?controller=cart&amp;delete=1&amp;id_product=' + product['id'] + '&amp;ipa=' + product['idCombination'] +
421        '&amp;
421token=' + static_token + '"><i class="icon icon-times"></i></a>');
422    }
423
424    // @TODO This is never called
425    if (product.is_gift) {
426      $('div[data-id="' + domIdProduct + '"] span.remove_link').html('');
427    }
428  },
429
430  /**
431   * @param {{ customizedDatas }} product
432   * @param customizationId
433   * @returns {boolean}
434   */
435  doesCustomizationStillExist: function(product, customizationId) {
436    var exists = false;
437
438    $(product.customizedDatas).each(function() {
439      if (this.customizationId == customizationId) {
440        exists = true;
441        // This return does not mean that we found nothing but simply break the loop
442        return false;
443      }
444    });
445    return exists;
446  },
447
448  /**
449   * Refresh display of vouchers (needed for vouchers in % of the total)
450   *
451   * @param {{ discounts }} jsonData
452   */
453  refreshVouchers: function(jsonData) {
454
455    var $vouchers      = $('.vouchers');
456    var $vouchersTbody = $vouchers.find('tbody');
457
458    if (typeof(jsonData.discounts) == 'undefined' || jsonData.discounts.length == 0) {
459      $vouchers.hide();
460    } else {
461      $vouchersTbody.html('');
462
463      for (var i = 0; i < jsonData.discounts.length; i++) {
464        /** @var {{ price_float, code, link, description, name, price, id }} discount */
465        var discount = jsonData.discounts[i];
466
467        if (parseFloat(discount.price_float) > 0) {
468          var delete_link = '';
469          if (discount.code.length) {
470            delete_link = '<a class="delete_voucher" href="' + discount.link + '" title="' + delete_txt + '"><i class="icon icon-times"></i></a>';
471          }
472
473          $vouchersTbody.append($(
474            '<tr class="bloc_cart_voucher" data-id="bloc_cart_voucher_' + discount.id + '">' + ' <td class="quantity">1 x</td>' + ' <td class="name" title="' +
475            discount.description + '">' + discount.name + '</td>' + ' <td class="price">-' + discount.price + '</td>' +
476            ' <td class="delete">' + delete_link + '</td>' + '</tr>'
477          ));
478        }
479      }
480      $vouchers.show();
481    }
482  },
483
484  /**
485   * Update product quantity
486   *
487   * @param {{ id, idCombination, idAddressDelivery }} product
488   * @param quantity
489   */
490  updateProductQuantity: function(product, quantity) {
491    $('dt[data-id=cart_block_product_' + product.id + '_' + (product.idCombination ? product.idCombination : '0') + '_' +
492      (product.idAddressDelivery ? product.idAddressDelivery : '0') + '] .quantity').fadeTo('fast', 0, function() {
493      $(this).text(quantity);
494      $(this).fadeTo('fast', 1, function() {
495        $(this).fadeTo('fast', 0, function() {
496          $(this).fadeTo('fast', 1, function() {
497            $(this).fadeTo('fast', 0, function() {
498              $(this).fadeTo('fast', 1);
499            });
500          });
501        });
502      });
503    });
504  },
505
506  //display the products witch are in json data but not already displayed
507  displayNewProducts: function(jsonData) {
508    //add every new products or update displaying of every updated products
509
510    $(jsonData.products).each(
511      /**
512       * @param index
513       * @param {{ id, idCombination, idAddressDelivery, hasAttributes, attributes, image_cart, name, quantity, link,
514       * price_float, priceByLine, is_gift, hasCustomizedDatas }} p - Product object
515       */
516      function(index, p) {
517
518        //fix ie6 bug (one more item 'undefined' in IE6)
519        if (p.id != undefined) {
520          //create a container for listing the products and hide the 'no product in the cart' message (only if the cart was empty)
521
522          if ($('.cart_block:first dl.products').length == 0) {
523            $('.cart_block_no_products').before('<dl class="products"></dl>').hide();
524          }
525          //if product is not in the displayed cart, add a new product's line
526          var domIdProduct = p.id + '_' + (p.idCombination ? p.idCombination : '0') + '_' + (p.idAddressDelivery ? p.idAddressDelivery : '0');
527          var domIdProductAttribute = p.id + '_' + (p.idCombination ? p.idCombination : '0');
528
529          var $cartProductLine = $('dt[data-id="cart_block_product_' + domIdProduct + '"]');
530          if ($cartProductLine.length == 0) {
531
532            var productId = parseInt(p.id);
533
534            // var productAttributeId = (p.hasAttributes ? parseInt(p.attributes) : 0);
535
536            var content =  '<dt class="unvisible clearfix" data-id="cart_block_product_' + domIdProduct + '">';
537            var name = $.trim($('<span />').html(p.name).text());
538
539            name = (name.length > 12 ? name.substring(0, 10) + '...' : name);
540
541            content += '<a class="cart-images" href="' + p.link + '" title="' + name + '"><img  src="' + p.image_cart + '" alt="' + p.name + '"></a>';
542
543            content += '<div class="cart-info"><div class="product-name">' + '<span class="quantity-formatted"><span class="quantity">' +
544              p.quantity + '</span> &times;</span> <a href="' + p.link + '" title="' + p.name + '" class="cart_block_product_name">' + name + '</a></div>';
545
546            if (p.hasAttributes) {
547              content += '<div class="product-attributes"><a href="' + p.link + '" title="' + p.name + '">' + p.attributes + '</a></div>';
548            }
549
550            if (typeof(freeProductTranslation) != 'undefined') {
551              content += '<span class="price">' + (parseFloat(p.price_float) > 0 ? p.priceByLine : freeProductTranslation) + '</span>';
552            }
553
554            content += '</div>';
555
556            if (typeof(p.is_gift) == 'undefined' || p.is_gift == 0) {
557              content += '<span class="remove_link"><a rel="nofollow" class="ajax_cart_block_remove_link" href="' + baseUri +
558                '?controller=cart&amp;delete=1&amp;id_product=' + productId + '&amp;
558token=' + static_token +
559                (p.hasAttributes ? '&amp;ipa=' + parseInt(p.idCombination) : '') + '"><i class="icon icon-times"></i></a></span>';
560            } else {
561              content += '<span class="remove_link"><i class="icon icon-times"></i></span>';
562            }
563
564            content += '</dt>';
565
566            if (p.hasAttributes) {
567              content += '<dd data-id="cart_block_combination_of_' + domIdProduct + '" class="unvisible">';
568            }
569
570            if (p.hasCustomizedDatas) {
571              content += ajaxCart.displayNewCustomizedDatas(p);
572            }
573
574            if (p.hasAttributes) {
575              content += '</dd>';
576            }
577
578            $('.cart_block dl.products').append(content);
579
580          } else {
581            //else update the product's line
582
583            if ($.trim($cartProductLine.find('.quantity').html()) != p.quantity || $.trim($cartProductLine.find('.price').html()) != p.priceByLine) {
584              // Usual product
585              if (!p.is_gift) {
586                $cartProductLine.find('.price').text(p.priceByLine);
587              } else {
588                $cartProductLine.find('.price').html(freeProductTranslation);
589              }
590
591              ajaxCart.updateProductQuantity(p, p.quantity);
592
593              // Customized product
594              if (p.hasCustomizedDatas) {
595                var customizationFormatedDatas = ajaxCart.displayNewCustomizedDatas(p);
596
597                var $customizationList = $('ul[data-id="customization_' + domIdProductAttribute + '"]');
598                if (!$customizationList.length) {
599                  if (p.hasAttributes) {
600                    $('dd[data-id="cart_block_combination_of_' + domIdProduct + '"]').append(customizationFormatedDatas);
601                  } else {
602                    $('.cart_block dl.products').append(customizationFormatedDatas);
603                  }
604                } else {
605                  $customizationList.html('').append(customizationFormatedDatas);
606                }
607              }
608            }
609          }
610
611          $('.cart_block dl.products .unvisible').slideDown().removeClass('unvisible');
612
613          // Remove default product remove button, leave remove buttons on customized rows only
614          var $removeLinks = $cartProductLine.find('a.ajax_cart_block_remove_link');
615          if (p.hasCustomizedDatas && $removeLinks.length) {
616            $removeLinks.remove();
617          }
618        }
619      });
620  },
621
622  displayNewCustomizedDatas: function(product) {
623    var content = '';
624    var productId = parseInt(product.id);
625    var productAttributeId = typeof(product.idCombination) == 'undefined' ? 0 : parseInt(product.idCombination);
626    var $customizationList = $('ul[data-id="customization_' + productId + '_' + productAttributeId + '"]');
627    var hasAlreadyCustomizations = $customizationList.length > 0;
628
629    if (!hasAlreadyCustomizations) {
630      if (!product.hasAttributes) {
631        content += '<dd data-id="cart_block_combination_of_' + productId + '" class="unvisible">';
632      }
633      if ($customizationList.val() == undefined) {
634        content += '<ul class="cart_block_customizations list-unstyled" data-id="customization_' + productId + '_' + productAttributeId + '">';
635      }
636    }
637
638    $(product.customizedDatas).each(function() {
639      var done = 0;
640      var customizationId = parseInt(this.customizationId);
641
642      productAttributeId = typeof(product.idCombination) == 'undefined' ? 0 : parseInt(product.idCombination);
643
644      content += '<li name="customization"><div class="deleteCustomizableProduct" data-id="deleteCustomizableProduct_' +
645        customizationId + '_' + productId + '_' + (productAttributeId ?  productAttributeId : '0') +
646        '"><a rel="nofollow" class="ajax_cart_block_remove_link" href="' + baseUri + '?controller=cart&amp;delete=1&amp;id_product=' +
647        productId + '&amp;ipa=' + productAttributeId + '&amp;id_customization=' + customizationId + '&amp;
647token=' + static_token +
648        '"><i class="icon icon-times"></i></a></div>';
649
650      // Give to the customized product the first textfield value as name
651      $(this.datas).each(function() {
652        if (this['type'] == CUSTOMIZE_TEXTFIELD) {
653          $(this.datas).each(function() {
654            if (this['index'] == 0) {
655              content += ' ' + this.truncatedValue.replace(/<br \/>/g, ' ');
656              done = 1;
657              return false;
658            }
659          });
660        }
661      });
662
663      // If the customized product did not have any textfield, it will have the customizationId as name
664      if (!done) {
665        content += customizationIdMessage + customizationId;
666      }
667
668      if (!hasAlreadyCustomizations) {
669        content += '</li>';
670      }
671      // Field cleaning
672      if (customizationId) {
673        $('#uploadable_files').find('li div.customizationUploadBrowse img').remove();
674        $('#text_fields').find('input').attr('value', '');
675      }
676    });
677
678    if (!hasAlreadyCustomizations) {
679      content += '</ul>';
680      if (!product.hasAttributes) {
681        content += '</dd>';
682      }
683    }
684
685    return content;
686  },
687
688  updateLayer: function(product) {
689    window.location.href = order_page; // Because we do not want do display "layer_cart"
690
691    /*
692    // Because we do not want do display "layer_cart"
693    var $attributes = $('#layer_cart_product_attributes');
694
695    $('#layer_cart_product_title').text(product.name);
696    $attributes.text('');
697    if (product.hasAttributes && product.hasAttributes == true) {
698      $attributes.html(product.attributes);
699    }
700
701    $('#layer_cart_product_price').text(product.price);
702    $('#layer_cart_product_quantity').text(product.quantity);
703    $('.layer_cart_img').html('<img class="layer_cart_img img-responsive" src="' + product.image + '" alt="' + product.name + '" title="' + product.name + '" />');
704
705    var n = parseInt($(window).scrollTop()) + 'px';
706
707    $('.layer_cart_overlay').css({'width': '100%', 'height': '100%'}).show();
708    $('#layer_cart').css({'top': n}).fadeIn('fast');
709    */
710  },
711
712  // General update of the cart display
713  updateCart: function(jsonData) {
714    //user errors display
715    if (jsonData.hasError) {
716      PrestaShop.showError(jsonData.errors);
717    } else {
718      ajaxCart.updateCartEverywhere(jsonData);
719      ajaxCart.hideOldProducts(jsonData);
720      ajaxCart.displayNewProducts(jsonData);
721      ajaxCart.refreshVouchers(jsonData);
722    }
723  },
724
725  /**
726   * Update general cart information everywhere in the page
727   *
728   * @param {{ productTotal, shippingCostFloat, shippingCost, free_ship, isVirtualCart, taxCost, wrappingCost,
729    *          total, total_price_wt, freeShipping, freeShippingFloat, nbTotalProducts }} cart
730   */
731  updateCartEverywhere: function(cart) {
732
733    var $total           = $('.ajax_cart_total');
734    var $shippingCost    = $('.ajax_cart_shipping_cost');
735    var $shippingCostRow = $shippingCost.closest('.cart-prices-line');
736    var $freeShipping    = $('.freeshipping');
737    var $quantity        = $('.ajax_cart_quantity');
738    var $productTxt      = $('.ajax_cart_product_txt');
739    var $productTxtS     = $('.ajax_cart_product_txt_s');
740    var $noProduct       = $('.ajax_cart_no_product');
741
742    $total.text($.trim(cart.productTotal));
743
744    if (typeof hasDeliveryAddress == 'undefined') {
745      window.hasDeliveryAddress = false;
746    }
747
748    if (parseFloat(cart.shippingCostFloat) > 0) {
749      $shippingCost.text(cart.shippingCost);
750      $shippingCostRow.show();
751    } else if ((hasDeliveryAddress || typeof(orderProcess) !== 'undefined' && orderProcess == 'order-opc') && typeof(freeShippingTranslation) != 'undefined') {
752      $shippingCost.html(freeShippingTranslation);
753    } else if ((typeof toBeDetermined !== 'undefined') && !hasDeliveryAddress) {
754      $shippingCost.html(toBeDetermined);
755    }
756
757    if (!cart.shippingCostFloat && !cart.free_ship) {
758      $shippingCostRow.hide();
759    } else if (hasDeliveryAddress && !cart.isVirtualCart) {
760      $shippingCostRow.show();
761    }
762
763    $('.ajax_cart_tax_cost').text(cart.taxCost);
764    $('.ajax_block_wrapping_cost').text(cart.wrappingCost);
765    $('.ajax_block_cart_total').text(cart.total);
766    $('.ajax_block_products_total').text(cart.productTotal);
767    $('.ajax_total_price_wt').text(cart.total_price_wt);
768
769    if (parseFloat(cart.freeShippingFloat) > 0) {
770      $('.ajax_cart_free_shipping').html(cart.freeShipping);
771      $freeShipping.fadeIn(0);
772    } else if (parseFloat(cart.freeShippingFloat) == 0) {
773      $freeShipping.fadeOut(0);
774    }
775
776    this.nb_total_products = cart.nbTotalProducts;
777
778    if (parseInt(cart.nbTotalProducts) > 0) {
779
780      var multipleProducts = parseInt(cart.nbTotalProducts) > 1;
781
782      $noProduct.hide();
783      $quantity.text(cart.nbTotalProducts).fadeIn();
784      $total.fadeIn();
785      $productTxt.toggle(!multipleProducts);
786      $productTxtS.toggle(multipleProducts);
787
788    } else {
789      $total.hide();
790      $quantity.hide();
791      $productTxt.hide();
792      $productTxtS.hide();
793      $noProduct.show();
794    }
795  }
796};
797
798function HoverWatcher(selector) {
799  this.hovering = false;
800  var self = this;
801
802  this.isHoveringOver = function() {
803    return self.hovering;
804  };
805
806  $(selector).on({
807    mouseenter: function() {
808      self.hovering = true;
809    },
810    mouseleave: function() {
811      self.hovering = false;
812    }
813  });
814}

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.