PageSourceSearch

https://www.soho-paper.com/mm5/json.mvc?Store_Code=S&Function=Java…=site-scripts&T=44ed17f5

js soho-paper.com collected 2026-10-09 18:27:41 UTC 20,254 bytes, 710 lines download raw bytes

1/**
2 * Check if Cash has been replaced by jQuery. If it has not, set jQuery
3 * as a `window` element.
4 */
5 if (typeof jQuery === 'undefined') {
6	window.jQuery = cash = $;
7}
8
9
10(function (mivaJS) {}(window.mivaJS || (window.mivaJS = {})));
11
12/**
13 *    Cash/jQuery Extensions
14 */
15$.extend({
16	debounced: function (fn, timeout, invokeAsap, ctx) {
17		/**
18		 * Custom function to allow us to delay events until after the
19		 * trigger has ended.
20		 *
21		 * Example: $(window).on('resize', $.debounced(function () {...DO SOMETHING...}, 100));
22		 */
23		if (arguments.length === 3 && typeof invokeAsap !== 'boolean') {
24			ctx = invokeAsap;
25			invokeAsap = false;
26		}
27		var timer;
28
29		return function () {
30			var args = arguments;
31
32			ctx = ctx || this;
33			invokeAsap && !timer && fn.apply(ctx, args);
34			clearTimeout(timer);
35			timer = setTimeout(function () {
36				invokeAsap || fn.apply(ctx, args);
37				timer = null;
38			}, timeout);
39		};
40	},
41	hook: function (hookName) {
42		/**
43		 * Custom function to allow us to unify event triggers/binding
44		 * using `data-` elements.
45		 *
46		 * Usage: $.hook('HOOK NAME')...
47		 * Example: $.hook('open-menu').on('click', function (e) {e.preventDefault(); ELEMENT.show();});
48		 */
49		var selector;
50
51		if (!hookName || hookName === '*') {
52			// select all data-hooks
53			selector = '[data-hook]';
54		}
55		else {
56			// select specific data-hook
57			selector = '[data-hook~="' + hookName + '"]';
58		}
59		return $(selector);
60	},
61	loadScript: function (url, callback) {
62		/**
63		 * Loads a JavaScript file asynchronously with a callback, like
64		 * jQuery's `$.getScript()` except without jQuery.
65		 *
66		 * Usage:
67		 * $.loadScript(FILE_PATH, function () {
68		 * 		DO SOMETHING...
69		 * });
70		 */
71		var head = document.getElementsByTagName('head')[0];
72		var scriptCalled = document.createElement('script');
73
74		scriptCalled.async = true;
75		scriptCalled.src = url;
76		scriptCalled.onload = scriptCalled.onreadystatechange = function () {
77			if (!scriptCalled.readyState || /loaded|complete/.test(scriptCalled.readyState)) {
78				scriptCalled.onload = scriptCalled.onreadystatechange = null;
79
80				if (head && scriptCalled.parentNode) {
81					head.removeChild(scriptCalled)
82				}
83
84				scriptCalled = undefined;
85
86				if (callback) {
87					callback();
88				}
89			}
90		};
91		//head.insertBefore(scriptCalled, head.firstChild);
92		head.appendChild(scriptCalled)
93	}
94});
95
96
97/**
98 *    HTML Class Name
99 *    This function will check if JavaScript is enabled, detect touch and hover
100 *    capabilities, and modify the class list as needed.
101 */
102(function () {
103	'use strict';
104
105	var html = document.documentElement;
106
107	html.classList.remove('no-js');
108	html.classList.add('js');
109
110	/**
111	 * Detect if the user is utilizing a touch interface.
112	 */
113	window.addEventListener('touchstart', function onFirstTouch() {
114		html.classList.add('touch');
115		html.setAttribute('data-touch', '');
116		window.USER_IS_TOUCHING = true;
117		sessionStorage.setItem('USER_IS_TOUCHING', true);
118		window.USER_CAN_HOVER = false;
119		sessionStorage.setItem('USER_CAN_HOVER', false);
120		window.removeEventListener('touchstart', onFirstTouch, false);
121	}, false);
122
123	/**
124	 * Detect if the user can hover over elements.
125	 */
126	window.addEventListener('mouseover', function onFirstHover() {
127		window.USER_CAN_HOVER = true;
128		sessionStorage.setItem('USER_CAN_HOVER', true);
129		html.classList.remove('touch');
130		html.removeAttribute('data-touch');
131		window.USER_IS_TOUCHING = false;
132		sessionStorage.setItem('USER_IS_TOUCHING', false);
133		window.removeEventListener('mouseover', onFirstHover, false);
134	}, false);
135}());
136
137
138/**
139 * Breakpoints
140 * This function will retrieve the breakpoint value set via CSS. You can use
141 * this to trigger a function based on the predefined breakpoints rather than
142 * a randomly chosen one.
143 *
144 * Usage:
145 * if (breakpoint === 'medium') {
146 *     yourFunctionCall();
147 * }
148 */
149// Setup the breakpoint variable
150var breakpoint;
151
152// Get the current breakpoint
153var getBreakpoint = function () {
154	return window.getComputedStyle(document.body, '::before').content.replace(/\"/g, '');
155};
156
157// Setup a timer
158var timeout;
159
160// Calculate breakpoint on page load
161breakpoint = getBreakpoint();
162
163// Listen for resize events
164window.addEventListener('resize', function (event) {
165	// If there's a timer, cancel it
166	if (timeout) {
167		window.cancelAnimationFrame(timeout);
168	}
169
170	// Setup the new requestAnimationFrame()
171	timeout = window.requestAnimationFrame(function () {
172		breakpoint = getBreakpoint();
173	});
174
175}, false);
176
177
178/**
179 * CSS Feature Detect - Used in place of Modernizr
180 * Returns true or false depending on your browser. Let's hope it's true.
181 * NOTE: This may be removed in future versions of the framework as
182 * browser compatibility and support changes.
183 *
184 * Usage: detectCSSFeature('transition');
185 */
186function detectCSSFeature(featureName) {
187	'use strict';
188
189	var feature = false,
190		domPrefixes = 'Moz ms Webkit'.split(' '),
191		elm = document.createElement('div'),
192		featureNameCapital = null;
193
194	featureName = featureName.toLowerCase();
195	if (elm.style[featureName] !== undefined) {
196		feature = true;
197	}
198	if (feature === false) {
199		featureNameCapital = featureName.charAt(0).toUpperCase() + featureName.substr(1);
200		for (var i = 0; i < domPrefixes.length; i++) {
201			if (elm.style[domPrefixes[i] + featureNameCapital] !== undefined) {
202				feature = true;
203				break;
204			}
205		}
206	}
207	return feature;
208}
209
210
211/**
212 * A complete cookies reader/writer framework with full unicode support.
213 *
214 * Revision #1 - September 4, 2014
215 * https://developer.mozilla.org/en-US/docs/Web/API/document.cookie
216 * https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie/Simple_document.cookie_framework
217 * https://developer.mozilla.org/User:fusionchess
218 * https://github.com/madmurphy/cookies.js
219 *
220 * This framework is released under the GNU Public License, version 3 or later.
221 * http://www.gnu.org/licenses/gpl-3.0-standalone.html
222 *
223 * Syntax:
224 * docCookies.setItem(name, value[, end[, path[, domain[, secure]]]]);
225 * docCookies.getItem(name);
226 * docCookies.removeItem(name[, path[, domain]]);
227 * docCookies.hasItem(name);
228 * docCookies.keys();
229 */
230var docCookies = {
231	getItem: function (sKey) {
232		if (!sKey) {
233			return null;
234		}
235		return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
236	},
237	setItem: function (sKey, sValue, vEnd, sPath, sDomain, bSecure) {
238		if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) {
239			return false;
240		}
241		var sExpires = "";
242		if (vEnd) {
243			switch (vEnd.constructor) {
244				case Number:
245					sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
246					break;
247				case String:
248					sExpires = "; expires=" + vEnd;
249					break;
250				case Date:
251					sExpires = "; expires=" + vEnd.toUTCString();
252					break;
253			}
254		}
255		document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");
256		return true;
257	},
258	removeItem: function (sKey, sPath, sDomain) {
259		if (!this.hasItem(sKey)) {
260			return false;
261		}
262		document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "");
263		return true;
264	},
265	hasItem: function (sKey) {
266		if (!sKey) {
267			return false;
268		}
269		return (new RegExp("(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
270	},
271	keys: function () {
272		var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);
273		for (var nLen = aKeys.length, nIdx = 0; nIdx < nLen; nIdx++) {
274			aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]);
275		}
276		return aKeys;
277	}
278};
279
280
281var elementsUI = {
282	site: function () {
283		/**
284		 * Load the `polyfills.js` file and initialise functions.
285		 * NOTE: This may be removed in future versions of the framework as
286		 * browser compatibility and support changes.
287		 */
288		if (!window.CSS || !window.CSS.supports('(--foo: red)')) {
289			$.loadScript(theme_path + 'core/js/polyfills.js', function () {
290				sessionStorage.setItem('outdated', true);
291				cssCapabilities.init();
292			});
293		}
294
295
296		/**
297		 * Load the `mini-modal.js` file and initialize functions if modal elements exist.
298		 * This is the default set of modal/light box functionality supplied with the framework.
299		 */
300		var targets = document.querySelectorAll('[data-mini-modal]');
301
302		if (targets.length) {
303			$.loadScript(theme_path + 'core/js/mini-modal.js', function () {
304				for (var i = 0; i < targets.length; i += 1) {
305					var modal = minimodal(targets[i], {
306						// If you would like a global onLoaded callback, add your function here
307						//onLoaded: function () {},
308						// If you would like a global onClosed callback, add your function here
309						//onClosed: function () {},
310						// If you are using, and have, a Google Maps API Key, enter it here.
311						googleMapsAPIKey: ''
312					});
313
314					if (!targets[i].id) {
315						targets[i].id = 'miniModal_' + i;
316					}
317					modal.init();
318				}
319			});
320		}
321
322
323		/**
324		 * Although NodeList is not an Array, it is possible to iterate on it using forEach().
325		 * It can also be converted to an Array using Array.from().
326		 * However some older browsers have not yet implemented NodeList.forEach() nor Array.from().
327		 * But those limitations can be circumvented by using Array.prototype.forEach().
328		 * This polyfill adds compatibility to browsers which do not support NodeList.forEach(). [IE11]
329		 */
330		if (window.NodeList && !NodeList.prototype.forEach) {
331			NodeList.prototype.forEach = function (callback, thisArg) {
332				thisArg = thisArg || window;
333				for (var i = 0; i < this.length; i++) {
334					callback.call(thisArg, this[i], i, this);
335				}
336			};
337		}
338
339	},
340
341	pages: {
342		/* ----------
343		 Common :
344		 ---------- */
345		common: function () {
346			/**
347			 * Add `ID` and `CLASS` attributes to `INPUT` and `SELECT` elements
348			 * dynamically created by Miva.
349			 */
350			var mvtInputWraps = document.querySelectorAll('[data-hook~="mvt-input"]');
351			var mvtSelectWraps = document.querySelectorAll('[data-hook~="mvt-select"]');
352
353			mvtInputWraps.forEach(function (element) {
354				var classes = element.getAttribute('data-classlist');
355				var id = element.getAttribute('data-id');
356				var mvtInputs = element.querySelectorAll('input');
357
358				mvtInputs.forEach(function (mvtInput) {
359					if (mvtInput.getAttribute('type') !== 'hidden') {
360						mvtInput.setAttribute('class', classes);
361						mvtInput.setAttribute('id', id);
362					}
363				});
364			});
365
366			mvtSelectWraps.forEach(function (element) {
367				var classes = element.getAttribute('data-classlist');
368				var id = element.getAttribute('data-id');
369				var mvtSelects = element.querySelectorAll('select');
370
371				mvtSelects.forEach(function (mvtSelect) {
372					mvtSelect.setAttribute('class', classes);
373					mvtSelect.setAttribute('id', id);
374				});
375			});
376
377		},
378
379		jsSFNT: function () {
380		},
381
382		jsCTGY: function () {
383		},
384
385		jsPROD: function () {
386			/**
387			 * This removes the default Miva `closeup_backing` container.
388			 */
389			var closeupBacking = document.querySelector('div.closeup_backing');
390
391			window.addEventListener('load', function () {
392				if (closeupBacking) {
393					closeupBacking.parentNode.removeChild(document.querySelector('div.closeup_backing'));
394				}
395			});
396
397		},
398
399		jsPATR: function () {
400		},
401
402		jsBASK: function () {
403			/**
404			 * Estimate Shipping
405			 */
406			mivaJS.estimateShipping = function (element) {
407				'use strict';
408
409				var currentModal = document.querySelector('[data-hook="' + element + '"]');
410				var formElement = currentModal.querySelector('[data-hook="shipping-estimate-form"]');
411				var formButton = formElement.querySelector('[data-hook="calculate-shipping-estimate"]');
412
413				function createCalculation () {
414					var processor = document.createElement('iframe');
415
416					processor.id = 'calculate-shipping';
417					processor.name = 'calculate-shipping';
418					processor.style.display = 'none';
419					formElement.before(processor);
420					processor.addEventListener('load', function () {
421						displayResults(processor);
422					});
423					formElement.submit();
424				}
425
426				function displayResults (source) {
427					var content = source.contentWindow.document.body.innerHTML;
428
429					formElement.querySelector('[data-hook="shipping-estimate-fields"]').classList.add('u-hidden');
430					formElement.querySelector('[data-hook="shipping-estimate-results"]').innerHTML = content;
431					formElement.setAttribute('data-status', 'idle');
432
433					formElement.querySelector('[data-hook="shipping-estimate-recalculate"]').addEventListener('click', function () {
434						formElement.querySelector('[data-hook="shipping-estimate-results"]').innerHTML = '';
435						formElement.querySelector('[data-hook="shipping-estimate-fields"]').classList.remove('u-hidden');
436					});
437
438					setTimeout(
439						function () {
440							source.parentNode.removeChild(source);
441						}, 1
442					);
443				}
444
445				formButton.addEventListener('click', function (event) {
446					event.preventDefault();
447					createCalculation();
448				}, false);
449			};
450
451		},
452
453		jsORDL: function () {
454		},
455
456		jsOCST: function () {
457			/**
458			 * Use AJAX for coupon form to prevent page refresh.
459			 * https://github.com/mivaecommerce/readytheme-shadows/issues/54
460			 */
461			(function (document) {
462				'use strict';
463
464				document.addEventListener('click', function (evt) {
465					var submitButton = document.querySelector('[data-hook="basket__coupon-form-submit"]');
466					var submitButtonText = ((submitButton.nodeName.toLowerCase() === 'input') ? submitButton.value : submitButton.textContent);
467					var ajaxForm = document.querySelector('[data-hook="basket__coupon-form"]');
468
469					if (evt.target.matches('[data-hook="basket__coupon-form-submit"]')) {
470						evt.preventDefault();
471						evt.stopImmediatePropagation();
472
473						var data = new FormData(ajaxForm);
474						var request = new XMLHttpRequest(); // Set up our HTTP request
475
476						ajaxForm.setAttribute('data-status', 'idle');
477
478						if (ajaxForm.getAttribute('data-status') !== 'submitting') {
479							ajaxForm.setAttribute('data-status', 'submitting');
480							submitButton.setAttribute('disabled', 'disabled');
481
482							if (submitButton.nodeName.toLowerCase() === 'input') {
483								submitButton.value = 'Processing...';
484							}
485							else {
486								submitButton.textContent = 'Processing...';
487							}
488
489							document.querySelector('#messages').parentNode.removeChild(document.querySelector('#messages'));
490
491							// Setup our listener to process completed requests
492							request.onreadystatechange = function () {
493								// Only run if the request is complete
494								if (request.readyState !== 4) {
495									return;
496								}
497
498								// Process our return data
499								if (request.status === 200) {
500									// What do when the request is successful
501									var response = request.response;
502									var basketSummary = response.querySelector('#checkout_basket_summary');
503									var responseMessage = response.querySelector('#messages');
504
505									response.querySelector('[data-hook="basket__coupon-form"]').parentElement.prepe
505nd(responseMessage);
506									document.querySelector('#checkout_basket_summary').innerHTML = basketSummary.innerHTML;
507
508
509									// Reset button text and form status
510									submitButton.removeAttribute('disabled');
511
512									if (submitButton.nodeName.toLowerCase() === 'input') {
513										submitButton.value = submitButtonText;
514									}
515									else {
516										submitButton.textContent = submitButtonText;
517									}
518
519									ajaxForm.setAttribute('data-status', 'idle');
520								}
521								else {
522									// What do when the request fails
523									console.warn('The request failed!');
524									ajaxForm.setAttribute('data-status', 'idle');
525								}
526							};
527
528							/**
529							 * Create and send a request
530							 * The first argument is the post type (GET, POST, PUT, DELETE, etc.)
531							 * The second argument is the endpoint URL
532							 */
533							request.open(ajaxForm.method, ajaxForm.action, true);
534							request.responseType = 'document';
535							request.send(data);
536						}
537					}
538				}, false);
539
540			}(document));
541
542		},
543
544		jsOSEL: function () {
545		},
546
547		jsOPAY: function () {
548			/**
549			 * Credit Card Detection
550			 */
551			$.loadScript(theme_path + 'core/js/payment-method.js', function () {
552				$.hook('detect-card').on('input paste', function () {
553					var cardInput = this;
554
555					if (isNaN(this.value)) {
556						this.classList.add('has-error');
557					}
558					paymentMethod(this, function (paymentDetected) {
559						if (paymentDetected) {
560							cardInput.classList.remove('has-error');
561							$.hook('payment-method-display').text(paymentDetected.display);
562							$.hook('payment-method').val(supportedPaymentMethods.findPaymentMethod(paymentDetected.name));
563						}
564					});
565				});
566			});
567
568			/**
569			 * Added functionality to help style the default Miva output payment
570			 * fields.
571			 */
572			$.hook('mvt-input').each(function () {
573				var dataHook = $(this).attr('data-datahook');
574
575				if (dataHook) {
576					$(this).find('input').attr('data-hook', dataHook);
577				}
578
579				Array.prototype.forEach.call($(this), function (el) {
580					el.innerHTML = el.innerHTML.replace(/&nbsp;/gi, '');
581				});
582			});
583
584			$.hook('detect-card').attr('type', 'tel');
585
586			$('[data-id="cvv"]').find('input').attr('type', 'tel');
587
588			/**$.hook('mvt-select').find('select').each(function () {
589				var wrapDiv = document.createElement('div');
590				var select = this;
591
592				select.attr('data-no-custom', '');
593				wrapDiv.classList.add('c-form-select');
594				select.parentNode.insertBefore(wrapDiv, select);
595				wrapDiv.appendChild(select);
596			});*/
597
598		},
599
600		jsINVC: function () {
601			/**
602			 *  Launch Printer Dialog
603			 */
604			$.hook('print-invoice').on('click', function (element) {
605				element.preventDefault();
606				window.print();
607			});
608		},
609
610		jsORDS: function () {
611			/**
612			 *  Launch Printer Dialog
613			 */
614			$.hook('print-invoice').on('click', function (element) {
615				element.preventDefault();
616				window.print();
617			});
618		},
619
620		jsLOGN: function () {
621		},
622
623		jsACAD: function () {
624		},
625
626		jsACED: function () {
627		},
628
629		jsCABK: function () {
630		},
631
632		jsCADA: function () {
633		},
634
635		jsCADE: function () {
636		},
637
638		jsAFCL: function () {
639		},
640
641		jsAFAD: function () {
642		},
643
644		jsAFED: function () {
645		},
646
647		jsORHL: function () {
648		},
649
650		jsCTUS: function () {
651		}
652	},
653
654	theme: function (pageID) {
655		if (pageID.toLowerCase() === 'jsprodquick' ) {
656			$.loadScript(theme_path + 'ui/js/theme_quickview.js');
657			return;
658		}
659
660		/**
661		 * Call in additional functions as developed for theme.
662		 */
663		$.loadScript(theme_path + 'ui/js/theme.js', function () {
664			window.addEventListener('load',
665				$.debounced(function () {
666					themeFunctionality.init();
667
668					if (themeFunctionality[pageID]) {
669						themeFunctionality[pageID]();
670					}
671				}, 300),
672				false
673			);
674		});
675	}
676};
677
678
679(function () {
680	String.prototype.toCamelCase = function (cap1st) {
681		'use strict';
682
683		return ((cap1st ? '-' : '') + this).replace(/-+([^-])/g, function (a, b) {
684			return b.toUpperCase();
685		});
686	};
687	var pageID = document.body.id.toCamelCase();
688
689	/**
690	 * Initialize Global Site Functions
691	 */
692	elementsUI.site();
693
694	/**
695	 * Initialize Common Page Functions
696	 */
697	elementsUI.pages.common();
698
699	/**
700	 * Initialize Page Specific Functions
701	 */
702	if (elementsUI.pages[pageID]) {
703		elementsUI.pages[pageID]();
704	}
705
706	/**
707	 * Initialize Theme Specific Function
708	 */
709	elementsUI.theme(pageID);
710}());

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.