1var CustomCart = (function ($) { 2 3 var _state = { 4 removeItemId: null 5 }; 6 7 var _defaults = { 8 templates: { 9 custom: [], 10 summary: 11 { 12 ref: "summary", 13 template: "#CartSummaryTemplate", 14 target: _SF('cartSummary') 15 }, 16 cartProduct: 17 { 18 ref: "cartProduct", 19 template: "#cartProductTemplate", 20 target: _SF('cartItemList') 21 }, 22 cartGiftCard: 23 { 24 ref: "cartGiftCard", 25 template: "#cartGiftCardTemplate", 26 target: _SF('cartItemList') 27 }, 28 cartHamper: 29 { 30 ref: "cartHamper", 31 template: "#cartHamperTemplate", 32 target: _SF('cartItemList') 33 }, 34 cartConfiguration: 35 { 36 ref: "cartConfiguration", 37 template: "#cartConfigurationTemplate", 38 target: _SF('cartItemList') 39 }, 40 cartBatch: 41 { 42 ref: "cartBatch", 43 template: "#cartBatchTemplate", 44 target: _SF('cartItemList') 45 }, 46 cartBranding: 47 { 48 ref: "cartBranding", 49 template: "#cartBrandingTemplate", 50 target: _SF('cartItemList') 51 }, 52 removeItem: { 53 ref: "removeItem", 54 template: "#removeItemTemplate", 55 target: _SF('removeItem') 56 }, 57 mobile: { 58 mobileProduct: 59 { 60 ref: "mobileProduct", 61 template: "#cartProductMobileTemplate", 62 target: _SF('fauxTable') 63 }, 64 mobileGiftCard: 65 { 66 ref: "mobileGiftCard", 67 template: "#cartGiftCardMobileTemplate", 68 target: _SF('fauxTable') 69 }, 70 mobileHamper: 71 { 72 ref: "mobileHamper", 73 template: "#cartHamperMobileTemplate", 74 target: _SF('fauxTable') 75 }, 76 mobileConfiguration: 77 { 78 ref: "mobileConfiguration", 79 template: "#cartConfigurationMobileTemplate", 80 target: _SF('fauxTable') 81 }, 82 mobileBatch: 83 { 84 ref: "mobileBatch", 85 template: "#cartBatchMobileTemplate", 86 target: _SF('fauxTable') 87 }, 88 mobileBranding: 89 { 90 ref: "mobileBranding", 91 template: "#cartBrandingMobileTemplate", 92 target: _SF('fauxTable') 93 }, 94 } 95 }, 96 _events: { 97 onBeforeLoad: null, 98 onAfterLoad: null 99 } 100 } 101 102 var _ready = () => { 103 // Render Custom Templates 104 _SFJS.render.templates(_defaults.templates.custom, _state); 105 // Prep _plugins 106 $('[data-toggle="tooltip"]').tooltip(); 107 // Do ready callback 108 _SFJS.utils.handleCallback(_defaults._events.onAfterLoad, _state); 109 // Remove placeholders 110 _SFJS.utils.removePlaceholders(); 111 } 112 113 var _render = () => { 114 // Get data via SDK 115 sdk.cart.get({ 116 requires: [ 117 { 118 endpoint: sdk.store.getInfo, 119 ref: "Store" 120 }, 121 { 122 endpoint: sdk.cart.validate, 123 ref: "Validation" 124 } 125 ], 126 success: function (response) { 127 $.extend(SFUI, { store: response.requirements.Store }); // register in SFUI library 128 $.extend(true, _state, { cart: response.data }, { cart: response.requirements }); // push data to local _state 129 130 _state.cart.TotalText = _SFJS.currency.parse(_state.cart.Total); 131 132 if (!_state.cart.Validation.Valid) { 133 $.each(_state.cart.Validation.Issues, function (idx, issue) { 134 $.each(issue.LineIds, function (idx, id) { 135 var item = _state.cart.Items.find(item => item.ItemId === id); 136 if (item) { 137 item['HasErrors'] = true; 138 item['Issues'] = issue; 139 } 140 }); 141 }); 142 } 143 144 $.each(_state.cart.Items, (i, item) => { 145 item['Picture'] = item.Pictures[0]; 146 item['PriceText'] = _SFJS.currency.parse(item.Price); 147 item['SubTotalText'] = _SFJS.currency.parse(item.SubTotal); 148 149 _functions.parseChildCurrencyValues(item); 150 151 if (item.Children) { 152 item['HasViewMore'] = item.Children.length > 2 ? true : false; 153 } 154 if (item.ItemType === 'Hamper') { 155 _SFJS.render.template(_defaults.templates.cartHamper, item); 156 _SFJS.render.template(_defaults.templates.mobile.mobileHamper, item); 157 } else if (item.ItemType === 'GiftCard') { 158 _SFJS.render.template(_defaults.templates.cartGiftCard, item); 159 _SFJS.render.template(_defaults.templates.mobile.mobileGiftCard, item); 160 } else if (item.ItemType === 'Configuration') { 161 _SFJS.render.template(_defaults.templates.cartConfiguration, item); 162 _SFJS.render.template(_defaults.templates.mobile.mobileConfiguration, item); 163 } else if (item.ItemType === 'Batch') { 164 _SFJS.render.template(_defaults.templates.cartBatch, item); 165 _SFJS.render.template(_defaults.templates.mobile.mobileBatch, item); 166 } else if (item.ItemType === 'Branding') { 167 item['CartId'] = _state.cart.CartId; 168 _SFJS.render.template(_defaults.templates.cartBranding, item); 169 _SFJS.render.template(_defaults.templates.mobile.mobileBranding, item); 170 } else { 171 _SFJS.render.template(_defaults.templates.cartProduct, item); 172 _SFJS.render.template(_defaults.templates.mobile.mobileProduct, item); 173 } 174 }); 175 176 _functions.reloadSummary(); 177 _SFJS.render.template(_defaults.templates.removeItem, _state.cart); 178 _ready(); 179 } 180 }); 181 } 182 183 var _functions = { 184 init: function (props) { 185 // update _defaults with potential custom values from view 186 $.extend(true, _defaults, props); 187 // Do init callback 188 _SFJS.utils.handleCallback(_defaults._events.onBeforeLoad, _state); 189 // Render View 190 _render(); 191 192 //Custom trigger GA4 event due to timing issue. 193 setTimeout(() => { 194 if (window.SFGA) { 195 console.log("view_cart"); 196 SFGA.Event('view_cart', null, '/ajax/google-analytics-4/cart') 197 } 198 }, 2000); 199 }, 200 201 parseChildCurrencyValues: function (item) { 202 // recursively parses child currency values 203 if (item?.Children && item?.Children.length) { 204 $.each(item.Children, function (idx, child) { 205 child['PriceText'] = _SFJS.currency.parse(child.Price); 206 child['SubTotalText'] = _SFJS.currency.parse(child.SubTotal); 207 child['TotalText'] = _SFJS.currency.parse(child.Total); 208 209 _functions.parseChildCurrencyValues(child) 210 }); 211 } else { 212 return false; 213 } 214 }, 215 216 updateCartItemValues: function (data) { 217 sdk.cart.updateItemQty({ 218 success: function (response) { 219 var data = response.data; 220 data.TotalText = _SFJS.currency.parse(data.Total); 221 // update line items with new values, it's easier to just do them all instead of just the one that was updated 222 $.each(data.Items, (i, item) => { 223 item.SubTotalText = _SFJS.currency.parse(item.SubTotal); 224 $('[sfTarget="cartItem"][data-id="' + item.ItemId + '"]').find('[sfTarget-itemTotal]').html(item.SubTotalText); 225 });
226 _functions.reloadSummary(); 227 }, 228 data: data 229 }); 230 }, 231 232 increment: function (id) { 233 var input = $('[sfTarget-updateQty="' + id + '"]').find('input'); 234 input.val(parseInt(input.val()) + 1); 235 var data = { 236 "Id": id, 237 "Qty": input.val() 238 } 239 _functions.updateCartItemValues(data); 240 }, 241 242 decrement: function (id) { 243 var input = $('[sfTarget-updateQty="' + id + '"]').find('input'); 244 input.val(parseInt(input.val()) - 1); 245 var qty = input.val(); 246 247 if (parseInt(qty) <= 0) { 248 _functions.removeItem(id); 249 return; 250 } 251 252 var data = { 253 "Id": id, 254 "Qty": qty 255 } 256 _functions.updateCartItemValues(data); 257 }, 258 259 updateQty: function (id) { 260 var qty = $('[name="qty"][data-itemid="' + id + '"]').val(); 261 262 if (parseInt(qty) <= 0) { 263 _functions.removeItem(id); 264 return; 265 } 266 267 var data = { 268 "Id": id, 269 "Qty": qty 270 } 271 _functions.updateCartItemValues(data); 272 }, 273 274 removeItem: function (id) { 275 _SF('removeItemModal').modal('show'); 276 _state.removeItemId = id; 277 }, 278 279 cancelRemoveItem: function () { 280 281 var item = $('[name="qty"][data-itemid="' + _state.removeItemId + '"]:visible'); 282 283 //No need to update cart as you cancelled the remove 284 if (item.val() <= 0) item.val(1); 285 286 _state.removeItemId = null; 287 $('[sf-target-removeitemmodal]').modal('hide'); 288 }, 289 290 confirmRemoveItem: function () { 291 if (window.SFGA) SFGA.Event('remove_from_cart', null, '/ajax/google-analytics-4/cart/item?itemId=' + _state.removeItemId); 292 sdk.cart.removeItem({ 293 success: function (response) { 294 $('[sfTarget="cartItem"][data-id="' + _state.removeItemId + '"]').remove(); 295 $('[sfTarget="itemError"][data-id="' + _state.removeItemId + '"]').remove(); 296 $('[sfTarget="viewMore"][data-id="' + _state.removeItemId + '"]').remove(); 297 _functions.reloadSummary(); 298 _state.removeItemId = null; 299 }, 300 itemId: _state.removeItemId, 301 }); 302 _SF('removeItemModal').modal('hide'); 303 }, 304 305 addPromocode: function () { 306 if (_SF('promocodeValue').val()) { 307 sdk.cart.addPromocode({ 308 data: { Code: _SF('promocodeValue').val() }, 309 success: function (response) { 310 var data = response.data; 311 if (data.Success) { 312 _functions.reloadSummary(); 313 _SF('promocodeAction').attr('data-type', 'remove'); 314 _SF('promocodeValue').attr('disabled', true); 315 } else { 316 Utils.Notify({ 317 style: "error", 318 message: response.data.Warnings[0] 319 }); 320 _SF('promocodeValue').val(''); 321 } 322 } 323 }); 324 325 } 326 }, 327 328 removePromocode: function () { 329 var code = _SF('promocodeValue').val() 330 var encodedCode = encodeURIComponent(code); 331 sdk.cart.removePromocode({ 332 code: encodedCode, 333 success: function (response) { 334 if (response.data.Success) { 335 _functions.reloadSummary(); 336 } else { 337 Utils.Notify({ 338 style: "error", 339 message: 'Unable to remove promocode "' + _SF('promocodeValue').val() + '"' 340 }); 341 } 342 } 343 }); 344 _SF('promocodeValue').val(''); 345 _SF('promocodeAction').attr('data-type', 'apply'); 346 _SF('promocodeValue').removeAttr('disabled'); 347 }, 348 349 reloadSummary: function () { 350 sdk.cart.get({ 351 success: function (response) { 352 var data = response.data; 353 console.log(!data); 354 $.extend(true, _state, { cart: data }); // push data to local state 355 if (!data || data.ItemCount === 0) { 356 _SF('cartItems').addClass('hide'); 357 _SF('noItemsInCart').removeClass('hide'); 358 } else { 359 data.SubTotalText = _SFJS.currency.parse(data.SubTotal); 360 data.DiscountText = _SFJS.currency.parse(data.Discount); 361 data.ShippingText = _SFJS.currency.parse(data.Shipping); 362 data.GiftCardPaymentText = _SFJS.currency.parse(data.GiftCardPayment); 363 data.WalletPaymentText = _SFJS.currency.parse(data.WalletPayment); 364 data.TaxText = _SFJS.currency.parse(data.Tax); 365 data.TotalText = _SFJS.currency.parse(data.Total); 366 data.TotalDueText = _SFJS.currency.parse(data.TotalDue); 367 368 369 _SFJS.render.template(_defaults.templates.summary, data, true); 370 } 371 }, 372 }); 373 }, 374 375 revealMore: function (itemId) { 376 var viewMore = $('[sfTarget="viewMore"][data-id="' + itemId + '"]'); 377 if (viewMore.hasClass('full')) { 378 viewMore.removeClass('full'); 379 $('[sftarget="cartItem"][data-id="' + itemId + '"] .wrap').removeClass('full'); 380 } else { 381 viewMore.addClass('full'); 382 $('[sftarget="cartItem"][data-id="' + itemId + '"] .wrap').addClass('full'); 383 } 384 }, 385 386 reject: function (event) { 387 console.log(event); 388 return event.charCode >= 48 && event.charCode <= 57; 389 } 390 } 391 392 return _functions; 393})(jQuery); 394 395$.extend(SFUI, { CustomCart }); // register in SFUI library
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.