PageSourceSearch

https://shop.skinnyraven.com/assets/admin/scripts/cart.js?v=1.2.0

js skinnyraven.com collected 2026-09-26 01:39:46 UTC 17,156 bytes, 514 lines download raw bytes

1
2var cart = {
3	data: [],
4	shipping: 0.00,
5	giftCard: 0.00,
6	how: "",
7	lastAdd: null,
8	statusId: null,
9	init: function() {
10		cart.get();
11	},
12	events: function() {
13		$(".cart").click(function() { window.location = "/cart"; });
14	},
15	getAddy: function() {
16		service.call("addys", { }, cart.addy, "GET");
17	},
18	addy: function(e) {
19
20	},
21	get: function() {
22		service.call("cart", { }, cart.getReturned, "GET");
23	},
24	getShippoRates: function(zip,callback) {
25		service.call("shipping/check-rates", {zipcode: zip}, callback);
26	},
27	getCosts: function(zip,state,country) {
28		service.call("costs", {zip: zip, state: state, country, country}, cart.costsReturned);
29	},
30	costsReturned: function(e) {
31		if (e.error) growler.error(e.error);
32		else {
33			context.set("cartCosts", e);
34			try {
35				page.updateTotals();
36			} catch (e) {
37	
38			}
39		}
40	},
41	getReturned: function(e) {
42		cart.data = e;
43		context.set("cart", cart.data);
44	},
45	canIncreaseItemQuantity: function(item) {
46		if (!item || item.type !== "product") return false;
47		const quantity = Number(item.quantity || 0);
48		// eslint-disable-next-line eqeqeq
49		if (item.lastKnownAvailableQty != null && item.lastKnownAvailableQty !== "") {
50			const lastKnownAvailableQty = Number(item.lastKnownAvailableQty);
51			if (Number.isFinite(lastKnownAvailableQty)) return lastKnownAvailableQty > quantity;
52		}
53		return item.canIncreaseQuantity !== false;
54	},
55	add: function(product, quantity, pickup, options, store, address, external, relay, inventoryId, oPickup, details) {
56		if (product.isInStorePurchaseOnly) growler.error("This product is only available for in-store purchase.");
57		else {
58			$(".fullLoading").addClass("open");
59			if (product.markdown!=null && product.markdown>0 && product.markdown<product.cost && product.isAuto) product.cost = product.markdown;
60			var column = '';
61			var row = '';
62			var opts = options.split('~');
63			if (opts.length==2) {
64				column = opts[0];
65				row = opts[1]
66			} else if (opts.length==1) {
67				column = opts[0];
68			}
69			var total = 0;
70			if (quantity<=0) {
71				$(".fullLoading").removeClass("open");
72				return;
73			}
74			cart.data.push({
75				type: "product",
76				product: product,
77				sku: product.sku, 
78				quantity: quantity, 
79				options: options,
80				pickup: pickup,
81				store: store,
82				address: address,
83				external: external,
84				column: column,
85				row: row,
86				relay: relay,
87				inventoryId: inventoryId,
88				details: details
89			});
90			var item = cart.data[cart.data.length - 1];
91			trackEvent('add_to_cart', {
92				"items": [
93					{
94						"id": item.product.productId,
95						"name": item.product.name,
96						"list_name": "Cart/Checkout",
97						"brand": item.product.brandName,
98						"category": item.product.categories && item.product.categories[0] ? item.product.categories[0].name : 'All Categories',
99						"variant": item.product.color,
100						"list_position": cart.data.indexOf(item),
101						"quantity": item.quantity,
102						"price": item.product.cost
103					}
104				]
105			});
106			try {
107				fbq('track', 'AddToCart', { 
108					"id": item.product.productId,
109					"name": item.product.name,
110					"list_name": "Cart/Checkout",
111					"brand": item.product.brandName,
112					"category": item.product.categories && item.product.categories[0] ? item.product.categories[0].name : 'All Categories',
113					"variant": item.product.color,
114					"list_position": cart.data.indexOf(item),
115					"quantity": item.quantity,
116					"price": item.product.cost
117				});
118			} catch (e) {}
119			try {
120				let names = [];
121				let items = [];
122				let cats = [];
123				for (let i=0; i<cart.data.length; i++) {
124					var product = cart.data[i].product;
125					if (cart.data[i].type=="giftcard") total += cart.data[i].quantity*cart.data[i].amount;
126					else total += cart.data[i].quantity*product.cost;
127					if (cart.data[i].type!="giftcard") {
128						names.push(product.name.trim());
129						let itemCats = [];
130						for (let j=0; j<product.categories.length; j++) {
131							cats.push(product.categories[j].name.trim());
132							itemCats.push(product.categories[j].name.trim());
133						}
134						items.push({
135							ProductID: product.productId,
136							SKU: product.sku,
137							ProductName: product.name.trim(),
138							Quantity: cart.data[i].quantity,
139							ItemPrice: product.cost,
140							RowTotal: cart.data[i].quantity*product.cost,
141							ProductURL: window.location.href,
142							ImageURL: window.location.protocol+"//"+window.location.host+product.imageUrl,
143							ProductCategories: itemCats
144						}); 
145					}
146				} 
147				if (_learnq!=null) {
148				// Build shareable cart URL for easy recovery
149				var recoverCartUrl = window.location.origin + "/cart?products=";
150				for (var k = 0; k < cart.data.length; k++) {
151					if (cart.data[k].type !== "giftcard" && cart.data[k].inventoryId) {
152						recoverCartUrl += (k > 0 ? "%2C" : "") + cart.data[k].inventoryId + "%3A" + cart.data[k].quantity;
153					}
154				}
155				
156				var klaviyoData = {
157					$value: total.toFixed(2),
158					AddedItemProductName: item.product.name.trim(),
159					AddedItemProductID: item.product.productId,
160					AddedItemSKU: item.product.sku,
161					AddedItemCategories: cats,
162					AddedItemImageURL: window.location.protocol+"//"+window.location.host+product.imageUrl,
163					AddedItemURL: window.location.href,
164					AddedItemPrice: item.product.cost.toFixed(2),
165					AddedItemQuantity: quantity,
166					ItemNames: names,
167					CheckoutURL: "https://"+window.location.host+"/checkout",
168					RecoverCartURL: recoverCartUrl,
169					Items: items
170				};
171				_learnq.push(["track", "Added to Cart", klaviyoData]);
172				}
173				if (window.blueshift!=null) {
174					blueshift.track("add_to_cart", {product_id: item.product.sku});
175				}
176			} catch (e) {
177				console.error("Klaviyo Error", e);
178			}
179			service.call("cart", { items: cart.data, sku: product.sku, quantity: quantity, column: column, row: row, pickup: oPickup, id: product.productId, external: external, relay: relay }, cart.addComplete);
180			
181		}
182	},
183	addGiftCard: function(amount, to, email, message, senderName, phone, physical, award, dateToSend) { 
184		service.call("cart/giftcard", { amount: amount, to: to, email: email, message: message, senderName: senderName, phone: phone, physical: physical, award: award, dateToSend: dateToSend }, cart.addComplete);
185	},
186	addComplete: function(e) {
187		$(".fullLoading").removeClass("open");
188		if (e.error) {
189			if (cart.data.length>0) cart.data.pop();
190			growler.error(e.error);
191		} else {
192			if (window.location && window.location.pathname==="/cart") {
193				cart.getReturned(e);
194			} else window.location = "/cart";
195		}
196	},
197	getDiscount: function() {
198		service.call("appliedDiscount", {}, cart.discountApplied);
199	},
200	applyDiscount: function(code) {
201		service.call("applyDiscount", {code: code}, cart.discountApplied);
202	},
203	discountApplied: function(e) {
204		if (e.error) growler.error(e.error);
205		else {
206			if (e.type) context.set("cartDiscount", e);
207		}
208	},
209	getGiftCard: function() {
210		service.call("appliedGiftCard", {}, cart.giftCardApplied);
211	}, 
212	applyGiftCard: function(code) {
213		service.call("applygiftCard", {card: code}, cart.giftCardReturned);
214	},
215	giftCardApplied: function(e) {
216		if (e.value>0) {
217			cart.giftCard = e.value;
218			context.set("giftCard", e.value);
219			if (e.cards) {
220				if (e.card?.value) {
221					cart.giftCard = e.card.value;
222					context.set("giftCard", e.card.value);
223				}
224				cart.multipleGiftCards = e.cards;
225				context.set("multipleGiftCards", e.cards);
226			} 
227			if (page && page.updateTotals) page.updateTotals();
228		}
229	},
230	giftCardReturned: function(e) {
231		if (e.value>0) {
232			cart.giftCard = e.value;
233			context.set("giftCard", e.value);
234			if (e.cards) {
235				if (e.card?.value) {
236					cart.giftCard = e.card.value;
237					context.set("giftCard", e.card.value);
238				}
239				cart.multipleGiftCards = e.cards;
240				context.set("multipleGiftCards", e.cards);
241			} 
242			if (page && page.updateTotals) page.updateTotals();
243		} else {
244			growler.info("The Gift Card entered does not have a balance.")
245		}
246	},
247	setAddress: function(e) {
248		cart.getAddy();
249		service.call("cartAddress", { addresses: e }, cart.setAddressReturned);
250	},
251	setAddressReturned: function(e) {
252		cart.getCosts(e.szipCode, e.sstate, e.scountry);
253	},
254	change: function(product, quantity) {
255		
256	},
257	remove: function(index) {
258		var items = [];
259		for (var i=0; i<cart.data.length; i++) {
260			if (i!=index) {
261				items[items.length] = cart.data[i];
262			} if (i === index) {
263				var item = cart.data[i];
264				if (item.type!="giftcard") {
265					trackEvent('remove_from_cart', {
266						"items": [
267							{
268								"id": item.product.productId,
269								"name": item.product.name,
270								"list_name": "Cart/Checkout",
271								"brand": item.product.brandName,
272								"category": item.product.categories && item.product.categories[0] ? item.product.categories[0].name : 'All Categories',
273								"variant": item.product.color,
274								"list_position": i,
275								"quantity": item.quantity,
276								"price": item.product.cost
277							}
278						]
279					});
280					if (window.blueshift!=null) {
281						blueshift.track("remove_from_cart", {product_id: item.product.sku});
282					}
283				}
284			}
285		}
286		service.call("cart/remove", { items: items }, cart.getReturned);
287	},
288	updateQuantity: function(index, newQuantity) {
289		var item = cart.data[index];
290		if (!item || item.type=="giftcard") return;
291		if (!item.product) return;
292		if (newQuantity<0 || newQuantity===item.quantity) return;
293		if (newQuantity>item.quantity) {
294			var difference = newQuantity - item.quantity;
295			cart.add(item.product, difference, item.pickup, item.options, item.store, item.address, item.external, item.relay, item.inventoryId, item.pickup, item.details);
296		} else {
297			var updatedItems = [];
298			for (var i=0; i<cart.data.length; i++) {
299				if (i===index) {
300					var updatedItem = $.extend(true, {}, cart.data[i]);
301					updatedItem.quantity = newQuantity;
302					updatedItems.push(updatedItem);
303				} else updatedItems.push(cart.data[i]);
304			}
305			cart.data = updatedItems;
306			context.set("cart", cart.data);
307			service.call("cart/remove", { items: cart.data }, cart.getReturned);
308		}
309	},
310	clear: function() {
311		cart.data = [];
312		context.set("cart", cart.data);
313		service.call("cart", { }
313, cart.getReturned, "DELETE"); 
314	},
315	process: function(how, params, confirm) {
316		cart.how = how;
317		if (params.afterpay || params.stripeCheckout) {
318			service.call("process", params, e => {
319				// Store purchase data in sessionStorage for GA4 tracking on ordersuccess page
320				try {
321					var gTagItems = [];
322					for (var i = 0; i < cart.data.length; i++) {
323						var item = cart.data[i];
324						if (item.type === "giftcard") continue;
325						var storeDetails = item.store && typeof store !== 'undefined' ? store.detailsFromCode(item.store) : null;
326						gTagItems.push({
327							id: item.product.productId,
328							name: item.product.name,
329							list_name: "Cart/Checkout",
330							brand: item.product.brandName,
331							category: item.product.categories && item.product.categories[0] ? item.product.categories[0].name : 'All Categories',
332							variant: item.product.color,
333							list_position: i,
334							quantity: item.quantity,
335							price: item.product.cost,
336							affiliation: storeDetails && storeDetails.name ? storeDetails.name : ""
337						});
338					}
339					sessionStorage.setItem('_rfPurchaseEvent', JSON.stringify({
340						order: e.order,
341						subtotal: e.subtotal,
342						currency: e.currency,
343						tax: e.tax,
344						shipping: e.shipping,
345						couponCode: e.couponCode,
346						items: gTagItems
347					}));
348				} catch (ex) {}
349				if (params.afterpay) {
350					confirm(e.intent);
351				} else {
352					confirm(e.session);
353				}
354			});
355		} else {
356			service.log({isAt:"cart.process", data: params});
357			service.call("process", params, cart.complete);
358		}
359		cart.pollStatus();
360		if (cart.statusId) clearInterval(cart.statusId);
361		cart.statusId = setInterval(cart.pollStatus, 1000);
362	},
363	pollStatus: function() {
364		service.call("checkout/status", {}, (e) => {
365			try {
366				$("#CheckoutStatus").html(e.data);
367			} catch (e) {}
368		});
369	},
370	complete: function(e) {
371		$(window).off('beforeunload');
372		if (e.error) {
373			clearInterval(cart.statusId);
374			$(".fullLoadingOrders").removeClass("open");
375			$(".fullLoading").removeClass("open");
376			$("#ActionButton").prop("disabled", false);
377			if (cart.how=="heartland") $("#HeartButton").show(); 
378			var error = "Card Declined";
379			if (e.error.raw != null && e.error.message !=null && e.error.message.length>0) error = e.error.message;
380			else {
381				if (typeof e.error === "string") error = e.error;
382			}
383			growler.error(error);
384		} else {
385			cart.orderNumber = e.order;
386			try {
387				var gTagItems = [];
388				var bsProducts = [];
389				for (var i=0; i<cart.data.length; i++) {
390				  var item = cart.data[i];
391				  var imageUrl = '';
392				  if (item.product.images && item.product.images.length>0) {
393					imageUrl = products.getSize(600, item.product.images[i].url);
394				  }
395				  var categoryList = [];
396				  for (let g=0; g<item.product.categories.length; g++) categoryList.push(item.product.categories[g].name);
397				  var storeDetails = item.store ? store.detailsFromCode(item.store) : null;
398				  var gTagItem = {
399					"id": item.product.productId,
400					"name": item.product.name,
401					"list_name": "Cart/Checkout",
402					"brand": item.product.brandName,
403					"category": item.product.categories && item.product.categories[0] ? item.product.categories[0].name : 'All Categories',
404					"variant": item.product.color,
405					"list_position": i,
406					"quantity": item.quantity,
407					"price": item.product.cost,
408					"affiliation": storeDetails && storeDetails.name ? storeDetails.name : ""
409				  }
410				  gTagItems.push(gTagItem);
411				  bsProducts.push({
412					sku: item.product.sku,
413					price: item.product.cost,
414					quantity: item.quantity,
415					title: item.product.name.trim(),
416					brand: item.product.brandName,
417					store_id: item.store,
418					product_sku: item.product.sku,
419					image: imageUrl,
420					size: item.column,
421					width: item.row,
422					color: item.product.color,
423					web_link: "https://"+window.location.hostname+products.getCanonical( item.product ),
424					category: categoryList
425				  });
426				}
427				trackEvent('purchase', {
428				  "transaction_id": '' + e.order,
429				  "value": e.subtotal,
430				  "currency": e.currency,
431				  "tax": e.tax,
432				  "shipping": e.shipping,
433				  "coupon": e.couponCode || "",
434				  "items": gTagItems
435				});
436                                            
437				if (window.blueshift!=null) {
438					blueshift.track("purchase", {
439						email: user.data.emailAddress,
440						order_id: e.order,
441						total: e.subtotal + e.shipping + e.tax,
442						revenue: e.subtotal,
443						shipping: e.shipping,
444						tax: e.tax,
445						discount: e.coupon,
446						coupon: e.couponCode,
447						products: bsProducts,
448						source: "Run Free"
449					});
450				}
451
452				if (_learnq!=null) {
453					let names = [];
454					let items = [];
455					let cats = [];
456					for (let i=0; i<cart.data.length; i++) {
457						var product = cart.data[i].product;
458						names.push(product.name.trim());
459						let itemCats = [];
460						for (let j=0; j<product.categories.length; j++) {
461							cats.push(product.categories[j].name.trim());
462							itemCats.push(product.categories[j].name.trim());
463						}
464						items.push({
465							ProductID: product.productId,
466							SKU: product.sku,
467							ProductName: product.name.trim(),
468							Quantity: cart.data[i].quantity,
469							ItemPrice: product.cost,
470							RowTotal: cart.data[i].quantity*product.cost,
471							ProductURL: window.location.href,
472							ImageURL: window.location.protocol+"//"+window.location.host+product.imageUrl,
473							ProductCategories: itemCats
474						}); 
475					} 
476					var klaviyoData = {
477						$event_id: moment().unix(),
478						$value: e.subtotal + e.shipping + e.tax,
479						ItemNames: names,
480						Categories: cats,
481						Items: items,
482						DiscountCode: e.couponCode,
483						DiscountValue: e.coupon,
484						BillingAddress: {
485							FirstName: user.data.firstName,
486							LastName: user.data.lastNAme,
487							Address1: user.data.street,
488							City: user.data.city,
489							RegionCode: user.data.state,
490							CountryCode: user.data.country,
491							Zip: user.data.postalCode,
492							Phone: user.data.phone
493						},
494						ShippingAddress: {
495							FirstName: user.data.firstName,
496							LastName: user.data.lastNAme,
497							Address1: user.data.sstreet,
498							City: user.data.scity,
499							RegionCode: user.data.sstate,
500							CountryCode: user.data.scountry,
501							Zip: user.data.spostalCode,
502							Phone: user.data.phone
503						}
504					};
505					_learnq.push(["track", "Placed Order", klaviyoData]);
506				}
507			} catch (e) {}
508			window.location = "/success";
509		}
510	},
511	logCart(type) {
512		service.call("cart/log", {cartData: cart.data, type: type}, (e) => { });
513	}
514}

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.