1/** 2 * 2007-2024 PrestaShop 3 * 4 * NOTICE OF LICENSE 5 * 6 * This source file is subject to the Academic Free License (AFL 3.0) 7 * that is bundled with this package in the file LICENSE.txt. 8 * It is also available through the world-wide-web at this URL: 9 * http://opensource.org/licenses/afl-3.0.php 10 * If you did not receive a copy of the license and are unable to 11 * obtain it through the world-wide-web, please send an email 12 * to [email protected] so we can send you a copy immediately. 13 * 14 * DISCLAIMER 15 * 16 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer 17 * versions in the future. If you wish to customize PrestaShop for your 18 * needs please refer to http://www.prestashop.com for more information. 19 * 20 * @author PrestaShop SA <[email protected]> 21 * @copyright 2007-2024 PrestaShop SA 22 * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) 23 * International Registered Trademark & Property of PrestaShop SA 24 * 25 * Don't forget to prefix your containers with your own identifier 26 * to avoid any conflicts with others containers. 27 */ 28 29$(document).ready(() => { 30 initSlickGift(); 31 32 $(document).on('click', '.quantity-selector .increase', function (event) { 33 event.preventDefault(); 34 event.stopPropagation(); 35 36 let remaining = parseInt($(this).closest('.gift-rule-products').data('remaining')); 37 let added = parseInt($(this).closest('.gift-rule-products').data('added')); 38 39 if (remaining <= 0) { 40 return false; 41 } 42 43 let input = $(this).parent().find('input'); 44 let value = parseInt(input.val()); 45 input.val(value + 1); 46 47 $(this).closest('.gift-rule-products').data('remaining', remaining - 1); 48 $(this).closest('.gift-rule-products').data('added', added + 1); 49 50 $(this).closest('.gift-rule-card').find('.gift-rule-remaining-count').text(remaining - 1); 51 if ((remaining - 1) <= 0) { 52 $(this).closest('.gift-rule-card').find('.all_selected').show(); 53 $(this).closest('.gift-rule-card').find('.more_than_one').hide(); 54 } 55 $(this).parent().addClass('selected'); 56 57 applyGifts(); 58 }); 59 60 $(document).on('click', '.quantity-selector .decrease', function (event) { 61 event.preventDefault(); 62 event.stopPropagation(); 63 let input = $(this).parent().find('input'); 64 let value = parseInt(input.val()); 65 if (value > 0) { 66 input.val(value - 1); 67 68 let remaining = parseInt($(this).closest('.gift-rule-products').data('remaining')); 69 let added = parseInt($(this).closest('.gift-rule-products').data('added')); 70 $(this).closest('.gift-rule-products').data('remaining', remaining + 1); 71 $(this).closest('.gift-rule-products').data('added', added - 1); 72 73 $(this).closest('.gift-rule-card').find('.gift-rule-remaining-count').text(remaining + 1); 74 $(this).closest('.gift-rule-card').find('.all_selected').hide(); 75 $(this).closest('.gift-rule-card').find('.more_than_one').show(); 76 77 applyGifts(); 78 } 79 value = parseInt(input.val()); 80 if (value <= 0) { 81 $(this).parent().removeClass('selected'); 82 } 83 }); 84 85 // Toggle handler for single-select gifts (qty_gifted == 1) 86 $(document).on('click', '.single-select .select-gift-btn', function (event) { 87 event.preventDefault(); 88 event.stopPropagation(); 89 const container = $(this).closest('.product-details'); 90 const input = container.find('input.quantity-input'); 91 let value = parseInt(input.val()); 92 93 let giftProducts = $(this).closest('.gift-rule-products'); 94 let remaining = parseInt(giftProducts.data('remaining')); 95 let added = parseInt(giftProducts.data('added')); 96 97 if (value === 0) { 98 // select if there's remaining capacity 99 if (remaining <= 0) { 100 return false; 101 } 102 input.val(1); 103 giftProducts.data('remaining', remaining - 1); 104 giftProducts.data('added', added + 1); 105 $(this).addClass('selected'); 106 $(this).closest('.product-block').addClass('selected'); 107 108 $(this).closest('.gift-rule-card').find('.gift-rule-remaining-count').text(remaining - 1); 109 if ((remaining - 1) <= 0) { 110 $(this).closest('.gift-rule-card').find('.all_selected').show(); 111 $(this).closest('.gift-rule-card').find('.more_than_one').hide(); 112 } 113 } else { 114 // deselect 115 input.val(0); 116 giftProducts.data('remaining', remaining + 1); 117 giftProducts.data('added', added - 1); 118 $(this).removeClass('selected'); 119 $(this).closest('.product-block').removeClass('selected'); 120 121 $(this).closest('.gift-rule-card').find('.gift-rule-remaining-count').text(remaining + 1); 122 $(this).closest('.gift-rule-card').find('.all_selected').hide(); 123 $(this).closest('.gift-rule-card').find('.more_than_one').show(); 124 } 125 126 applyGifts(); 127 }); 128 129 $(document).on('click', '#gift-rules-block .gift-rule-products .product-block', function (event) { 130 if ($(event.target).closest('.select-gift-btn').length) { 131 return; 132 } 133 const group = $(this).closest('.gift-rule-products'); 134 if (group.hasClass('disabled')) { 135 return; 136 } 137 const btn = $(this).find('.single-select .select-gift-btn'); 138 if (btn.length) { 139 btn.trigger('click'); 140 } 141 }); 142 143 if ($('#gift-rules-block').length) { 144 updateGiftRules(); 145 } 146 147 prestashop.on('updateCart', function (event) { 148 if (event.reason !== 'refreshGifts') { 149 refreshGiftBlock(); 150 } 151 }); 152 153 if (typeof freebies_warning_missing_select !== 'undefined' && freebies_warning_missing_select) { 154 $(document).on('click', 'a[href="' + prestashop.urls.pages.order + '"]:not(#proceed_anyway)', function (event) { 155 let missingSelect = false;
156 $('.gift-rule-card').each(function () { 157 let remaining = parseInt($(this).find('.gift-rule-products:not(.disabled)').data('remaining')); 158 if (remaining > 0) { 159 missingSelect = true; 160 return false; 161 } 162 }); 163 if (missingSelect) { 164 event.preventDefault(); 165 $('#gift-missing-popup').show(); 166 } 167 }); 168 169 $(document).on('click', '#back_to_gifts', function (event) { 170 event.preventDefault(); 171 $('#gift-missing-popup').hide(); 172 $("html, body").animate({ scrollTop: $('#gift-rules-block').offset().top - $('header').height() }, 500); 173 }); 174 } 175}); 176 177function refreshGiftBlock() { 178 $.ajax({ 179 type: 'GET', 180 url: freebies_controller_link + '?ajax=1&action=RefreshGiftBlock', 181 success: function (data) { 182 let response = JSON.parse(data); 183 if (response.success) { 184 $('#gift-rules-block').replaceWith(response.giftBlock); 185 initSlickGift(); 186 updateGiftRules(); 187 } 188 } 189 }); 190} 191 192function updateGiftRules() { 193 $.ajax({ 194 type: 'GET', 195 url: freebies_controller_link + '?ajax=1&action=GetGiftsInCart', 196 success: function (data) { 197 let response = JSON.parse(data); 198 if (response.success) { 199 for (let giftRuleInCart in response.giftRulesInCart) { 200 let ruleInCart = response.giftRulesInCart[giftRuleInCart]; 201 let ruleId = ruleInCart.id_giftrule; 202 let ruleCard = $('#gift-rules-block .gift-rule-card[data-rule="' + ruleId + '"]'); 203 let remaining = ruleInCart.giftRule.qty_gifted; 204 let added = 0; 205 let products = JSON.parse(ruleInCart.products); 206 for (let product in products) { 207 let productId = products[product].product; 208 let quantity = products[product].quantity; 209 let input = ruleCard.find('.gift-rule-products input.quantity-input[data-rule="' + ruleId + '"][data-product="' + productId + '"]'); 210 input.val(quantity); 211 remaining -= quantity; 212 added += quantity; 213 // Mark appropriate UI as selected 214 const qtySelector = input.closest('.quantity-selector'); 215 const singleSelect = input.closest('.product-details'); 216 if (quantity > 0) { 217 if (qtySelector.length) { 218 qtySelector.addClass('selected'); 219 } 220 if (singleSelect.length) { 221 singleSelect.find('.select-gift-btn').addClass('selected'); 222 singleSelect.closest('.product-block').addClass('selected'); 223 } 224 } else { 225 if (qtySelector.length) { 226 qtySelector.removeClass('selected'); 227 } 228 if (singleSelect.length) { 229 singleSelect.find('.select-gift-btn').removeClass('selected'); 230 } 231 } 232 } 233 ruleCard.find('.gift-rule-products').data('remaining', remaining); 234 ruleCard.find('.gift-rule-products').data('added', added); 235 ruleCard.find('.gift-rule-remaining-count').text(remaining); 236 if (remaining <= 0) { 237 ruleCard.find('.all_selected').show(); 238 ruleCard.find('.more_than_one').hide(); 239 } 240 } 241 } 242 } 243 }); 244} 245 246function applyGifts() { 247 let products = []; 248 $('.gift-rule-card').each(function () { 249 let productsForRule = { 250 'ruleId': $(this).data('rule'), 251 'products': [] 252 }; 253 254 $(this).find('input.quantity-input').each(function () { 255 if ($(this).val() > 0) { 256 let productId = $(this).data('product'); 257 let quantity = $(this).val(); 258 productsForRule.products.push({ 259 'product': productId, 260 'quantity': quantity, 261 }); 262 } 263 }); 264 products.push(productsForRule); 265 }); 266 $.ajax({ 267 type: 'POST', 268 url: freebies_controller_link + '?ajax=1&action=ApplyGifts', 269 data: { 270 'products': products 271 }, 272 success: function (data) { 273 let response = JSON.parse(data); 274 if (!response.success) { 275 $('#gift_rule_error_message').text(response.message).show(); 276 setTimeout(() => { 277 $('#gift_rule_error_message').fadeOut(); 278 }, 4000); 279 } 280 prestashop.emit('updateCart', { 281 reason: 'refreshGifts', 282 resp: response 283 }); 284 } 285 }); 286} 287 288function initSlickGift() { 289 $('#gift-rules-block .gift-rule-products').slick({ 290 'slidesToShow': 3, 291 'slidesToScroll': 2, 292 'arrows': true, 293 'dots': false, 294 'infinite': false, 295 'autoplay': false, 296 'responsive': [ 297 { 298 'breakpoint': 992, 299 'settings': { 300 'slidesToShow': 2, 301 'slidesToScroll': 1 302 } 303 }, 304 { 305 'breakpoint': 768, 306 'settings': { 307 'slidesToShow': 1, 308 'slidesToScroll': 1 309 } 310 } 311 ] 312 }); 313}
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.