PageSourceSearch

https://merchr.com/wp-content/plugins/merchr-print-on-demand/resources/js/merchrcust-public.js?ver=18

js merchr.com collected 2026-10-02 06:27:33 UTC 18,404 bytes, 582 lines download raw bytes

1
2jQuery(function($){
3	merchrcustPublic.init(jQuery);
4});
5
6jQuery(window).on("load", function(){
7	merchrcustPublic.initAfterWindowLoad();
8});
9
10const merchrcustPublic = {
11	
12	// - Text Stuff ------------------------------------------------------------
13
14	local_storage_custom_key: 'merchrcust_customtext',
15    local_storage_custom_colour_key: 'merchrcust_customtext_colour',
16    local_storage_custom_font_key: 'merchrcust_customtext_font',
17	cart_thumbnail_timer: false,
18	querystring_custom_key: 'mctext',
19	storage: {
20		add_to_cart_triggered: false,
21		add_to_cart_thumbnail_needs_updating: true, 
22		customisation_on: null,
23	},
24
25	init($){
26		var self = this;
27		self.jQuery = $;
28		self.hideCustomisationBeforeLoad();
29		self.resetToDefaultTextButton();
30		self.copyToClipboard();
31		//self.moveQty();
32	},
33	
34	initAfterWindowLoad(){
35		// Variations load after page load, so we need to defer some things
36		var self = this;
37		self.createHiddenThumbnail();
38		self.initCustomisationOption();
39		self.initTextInput();
40		self.initTextColorChange();
41		self.initFontFamilyChange();
42		self.initPlaceImage();
43		self.showCustomisation();
44		//self.addToCartHook();
45		// don't need this. things are updated on load that trigger this self.restartCartThumbnailUpdateTask();
46	},
47	
48	// TODO: change thumbnail image on variation change
49	// TODO: sync thumbnail data every update, apart from size and background
50	
51	createHiddenThumbnail(){
52		const $ = this.jQuery;
53	},
54	
55	restartCartThumbnailUpdateTask(){
56		const self = this;
57		const $ = jQuery;
58		self.storage.add_to_cart_thumbnail_needs_updating = true;
59		// don't set a time out, just allow add to cart button to create the image. the creation doesn't take long.
60		//$('.single_add_to_cart_button').prop('disabled', true);
61		//clearTimeout(this.cart_thumbnail_timer);
62		//this.cart_thumbnail_timer = setTimeout(function(){
63		//	self.pushThumbnailToCartForm();
64		//}, 500);
65	},
66	
67	pushThumbnailToCartForm(target){
68		const $ = jQuery;
69		const self = this;
70		$('.single_add_to_cart_button').prop('disabled', true);
71		var thumb_id = 'merchr_customised_thumbnail';
72		var callback = function(){
73			var $field = $('#merchrcust_thumbnail_field');
74			var stored = $field.val();
75			var latest;
76			if (!self.storage.customisation_on){
77				// if no customisation set it to empty
78				latest = '';
79			}else{
80				latest = $('#' + thumb_id).get(0).toDataURL('image/jpg');
81			}
82			if (!self.storage.customisation_on || stored !== latest){
83				if($('#merchrcust_thumbnail_field').length > 0) {
84					$('#merchrcust_thumbnail_field').one('triggerAddToCart', function(){
85						if (self.storage.add_to_cart_triggered){
86							self.storage.add_to_cart_triggered = false;
87							self.storage.add_to_cart_thumbnail_needs_updating = false;
88							setTimeout(function(){
89								$('.single_add_to_cart_button').prop('disabled', false).trigger('click');
90							}, 1);
91						}
92					}).val(latest).trigger('triggerAddToCart');
93				} else {
94					self.storage.add_to_cart_triggered = false;
95					self.storage.add_to_cart_thumbnail_needs_updating = false;
96					setTimeout(function(){
97						$('.single_add_to_cart_button').prop('disabled', false).trigger('click');
98					}, 1);
99				}
100			}
101			self.storage.add_to_cart_thumbnail_needs_updating = false;
102			$('.single_add_to_cart_button').prop('disabled', false);
103		};
104		
105		
106		var $prodcanvas = self.productDetailCanvas();
107		if ($prodcanvas){
108			var size = 250;
109			$('#' + thumb_id).remove();
110			var $thumb = $('<canvas>', {
111				id: thumb_id,
112			}).attr({
113				width: size,
114				height: size,
115			}).css({
116				width: size,
117				height: size,
118			}).hide().appendTo('form.cart');
119
120			if (!self.storage.customisation_on){
121				// if no customisation do no more
122				return callback();
123			}
124			
125			var ctx = $thumb.get(0).getContext('2d');
126
127			var img = new Image;
128			img.onload = function(){
129				ctx.drawImage(this, 0, 0, size, size);
130				var fcanvas = $prodcanvas.get(0).fcanvas;
131				var img2 = new Image;
132				img2.src = fcanvas.toDataURL('image/png');
133				ctx.drawImage(img2, 0, 0, size, size);
134				callback();
135			};
136			img.src = self.productDetailImage().src;
137		} else {
138			// if no customisation do no more
139			return callback();
140		}
141		
142	},
143	
144	addToCartHook(){
145		const $ = jQuery;
146		const self = this;
147		$('form.cart').on('submit', function(e){
148			if (self.storage.add_to_cart_thumbnail_needs_updating){
149				self.storage.add_to_cart_triggered = true;
150				e.preventDefault();
151				self.pushThumbnailToCartForm();
152			}
153		});
154	},
155	
156	hideCustomisationBeforeLoad(){
157		const $ = jQuery;
158		$('#merchrcust-fields-wrapper').hide();
159		$('#merchrcust-fields-loading').show();
160	},
161	
162	showCustomisation(){
163		setTimeout(function() {
164			const $ = jQuery;
165			$('#merchrcust-fields-wrapper').show();
166			$('#merchrcust-fields-loading').hide();
167		}, 1);
168	},
169
170	moveQty(){
171		const $ = jQuery;
172		if (!$('body.single-product').length){
173			return;
174		}
175		$('.quantity input').addClass('input-qty').appendTo('.js__merchrProductQtyInputHere');
176	},
177
178	onFontsLoaded(){
179		//this.productDetailFabricText();
180		this.detectVariationChange();
181	},
182
183	// get Product detail canvas 
184	productDetailCanvas(){
185		const self = this;
186		const $ = jQuery;
187		var prodcanvas = $('#' + self.product_image_canvas_id); // this ID is saved by merchrcustFlatCanvas.showTextOnAllImages
188		if (prodcanvas.length){
189			return prodcanvas;
190		}
191		return null;
192		//return $('.js__merchrProductImage .merchrcanvas');
193	},
194	
195	// get Product detail image 
196	productDetailImage(){
197		const $ = jQuery;
198		var $images = $('.woocommerce-product-gallery__image img:not(.zoomImg)');
199		if ($images.length === 1){
200			return $images.get(0);
201		}
202		return $('.woocommerce-product-gallery__image.flex-active-slide img:not(.zoomImg)').get(0);
203	},
204	
205	initPlaceImage(){
206		const self = this;
207		const $ = jQuery;
208		$('#merchrcust-image-modal-button').on('click', function(e){
209			e.preventDefault();
210			self.openImageModal();
211		});
212		$('#merchrcust-image-place-button').on('click', function(e){
213			e.preventDefault();
214			merchrcustFlatCanvas.setPlacedImage(self.productDetailCanvas(), $('#merchrcust_image_to_place').val());
215		});
216		$('#merchrcust-remove-white-button').on('click', function(e){
217			e.preventDefault();
218			self.openRemoveWhiteModal();
219		});
220		$('#merchrcust-remove-white-none').on('click', function(e){
221			e.preventDefault();
222			merchrcustFlatCanvas.setPlacedImage(self.productDetailCanvas(), self.storage.placed_image_wrnone_url);
223			$('#merchrcust_custom_image_whiteremove').val('none');
224			self.closeRemoveWhiteModal();
225		});
226		$('#merchrcust-remove-white-edges').on('click', function(e){
227			e.preventDefault();
228			merchrcustFlatCanvas.setPlacedImage(self.productDetailCanvas(), self.storage.placed_image_wredges_url);
229			$('#merchrcust_custom_image_whiteremove').val('edges');
230			self.closeRemoveWhiteModal();
231		});
232		$('#merchrcust-remove-white-all').on('click', function(e){
233			e.preventDefault();
234			merchrcustFlatCanvas.setPlacedImage(self.productDetailCanvas(), self.storage.placed_image_wrall_url);
235			$('#merchrcust_custom_image_whiteremove').val('all');
236			self.closeRemoveWhiteModal();
237		});
238		$('.merchrcust-rwm-image-wrapper').on('click', function(e){
239			e.preventDefault();
240			$(this).parent().find('button').trigger('click');
241		});
242		window.addEventListener('message', self.receiveMessageFromIframe, false);
243	},
244	
245	openImageModal(){
246		const $ = jQuery;
247		const self = this;
248		self.workingShow();
249		$('body').addClass('nobodyscroll');
250		self.iframe_callback_id = 'merchr' + Math.floor( Math.random() * 99999999 ) + '' + Math.floor( Math.random() * 99999999 );
251		var url = `${window.merchrcust_ext_images_url}&callback_id=${merchrcustPublic.iframe_callback_id}`;
252		$('<iframe>', {
253			id: 'merchrcust-image-handler-modal',
254			src: url
255		}).addClass('merchrcust-modal').appendTo('body').show();
256	},
257	
258	openRemoveWhiteModal(){
259		const $ = jQuery;
260		const self = this;
261		$('body').addClass('nobodyscroll');
262		$('#merchrcust-white-removal-modal').show();
263		$('.merchrcust-rwm-image-wrapper').empty();
264		$('<img>', {
265			src: self.storage.placed_image_wrnone_url
266		}).appendTo('#merchrcust-remove-white-none-image');
267		$('<img>', {
268			src: self.storage.placed_image_wrall_url
269		}).appendTo('#merchrcust-remove-white-all-image');
270		$('<img>', {
271			src: self.storage.placed_image_wredges_url
272		}).appendTo('#merchrcust-remove-white-edges-image');
273	},
274	
275	closeRemoveWhiteModal(){
276		const $ = jQuery;
277		const self = this;
278		$('body').removeClass('nobodyscroll');
279		$('#merchrcust-white-removal-modal').hide();
280	},
281	
282	workingShow(){
283		const $ = jQuery;
284		const self = this;
285		$('<div>', {
286			id: 'merchrcust-working'
287		}).appendTo('body').append('<div>Working...</div>');
288	},
289	
290	workingHide(){
291		const $ = jQuery;
292		const self = this;
293		$('#merchrcust-working').remove();
294	},
295	
296	imageModalLoaded(){
297		const $ = jQuery;
298		const self = this;
299		self.workingHide();
300		$('#merchrcust-image-handler-modal').show();
301	},
302	
303	closeImageModal(){
304		const $ = jQuery;
305		$('#merchrcust-image-handler-modal').remove();
306		$('body').removeClass('nobodyscroll');
307	},
308	
309	receiveMessageFromIframe(event){
310		// nope const self = this;
311		const self = merchrcustPublic;
312		const $ = jQuery;
313		if (typeof event.data.message_from !== 'undefined' && event.data.message_from !== 'merchrhub_image_handler'){
314			//console.log('not my message');
315			return;
316		}
317		// check id matches
318		if (event.data.callback_id !== merchrcustPublic.iframe_callback_id){
319			//console.log('not my callback_id', merchrcustPublic.iframe_callback_id, event.data.callback_id);
320			return;
321		}
322		switch (event.data.action){
323			case 'place_image':
324				self.placeImageFromIframe(event);
325				break;
326			case 'close_modal':
327				self.closeImageModal();
328				break;
329			case 'modal_loaded':
330				self.imageModalLoaded();
331				break;
332		}
333	},
334	
335	placeImageFromIframe(event){
336		const self = merchrcustPublic;
337		const $ = jQuery;
338		self.storage.placed_image_wrnone_url = event.data.data.thumbnail_abs_url;
339		self.storage.placed_image_wrall_url = event.data.data.thumbnail_wrall_abs_url;
340		self.storage.placed_image_wredges_url = event.data.data.thumbnail_wredges_abs_url;
341		self.storage.placed_image_id = event.data.data.upload_id;
342
343		var image_src = self.storage.placed_image_wrnone_url;
344
345		$('#merchrcust_custom_image').val(event.data.data.upload_id + '|' + image_src);
346		merchrcustFlatCanvas.setPlacedImage(self.productDetailCanvas(), image_src);
347		self.storage.placed_image_url = image_src;
348		self.closeImageModal();
349		if (!event.data.data.has_transparency){
350			self.showWhiteRemovalOptions();
351		}else{
352			self.hideWhiteRemovalOptions();
353		}
354	},
355	
356	initTextColorChange(){
357		const self = this;
358		const $ = jQuery;
359		const current = localStorage.getItem(self.local_storage_custom_colour_key);
360        
361        $('input[name="merchrcust_text_color"]').on('change', function(){
362			const val = $(this).val();
363            merchrcustFlatCanvas.setTextColor(self.productDetailCanvas(), val);
364            localStorage.setItem(self.local_storage_custom_colour_key, val);
365		});
366        
367        if (current !== null) {
368            //$('input[name="merchrcust_text_color"]').val(current).trigger("change");
369        }
370	},
371
372	/*
373	 * When a variation is changed it updates the image, and we need to react to that
374	 * Change the canvas
375	 * Change the text colour on the product iomage canvas
376	 * @returns {undefined} 
377	 */
378	detectVariationChange(){
379		return;
380		const self = this;
381		const $ = jQuery;
382		$('input.variation_id').on('change', function(){
383			//self.productDetailFabricText();
384			//var text_color = self.getVariationTextColor();
385			//var font_family = self.getCurrentFontFamily();
386			//merchrcustFlatCanvas.setTextColor(self.productDetailCanvas(), text_color);
387			//merchrcustFlatCanvas.setFontFamily(self.productDetailCanvas(), font_family);
388		});
389	},
390	
391	getVariationTextColor(){
392		const self = this;
393		const $ = jQuery;
394		var variation_id = $('input.variation_id').val();
395		// get the colour from the merchcust data if it exists ( set in product detail > variations ) 
396		var data = $('#merchrcust_data').data('merchrcust');
397		if (variation_id in data.variation_colors){
398			return data.variation_colors[variation_id];
399		}
400		// otherwise return the default that's set on product detail > customisation
401		return data.text_color;
402	},
403	
404	getCurrentFontFamily(){
405		const $ = jQuery;
406        return $('#merchrcust_fontfamily_select').val();
407	},
408
409	/*
410	 * Textarea fits to width and centres text but it allows line breaks
411	 * Text doesn't allow line breaks, but doesn't centre itself
412	 * 
413	 * Create a div with its background as the original product image and plop the canvas with text inside that
414	 * 
415	 */
416	//productDetailFabricText(){
417	//	return;
418	//	const $ = jQuery;
419	//	if (!$('body.single-product').length){
420	//		return;
421	//	}
422	//
423	//	var data = $('#merchrcust_data').data('merchrcust');
424	//	if (!data){
425	//		return;
426	//	}
427	//	// get the image
428	//	var $img = $('.woocommerce-product-gallery__wrapper .wp-post-image');
429	//	var $gallery = $('.woocommerce-product-gallery');
430	//	// don't put it as the background data.img_src = $img.attr('src');
431	//	data.size = parseInt($gallery.width());
432	//	$gallery.hide();
433	//	var merchrgalleryid = 'merchr-product-gallery';
434	//	$('#' + merchrgalleryid).remove();
435	//	var $merchrgallery = $('<div>', {
436	//		id: merchrgalleryid
437	//	}).addClass('woocommerce-product-gallery').insertBefore($gallery);
438	//	var $imgwrapper = $('<div>').addClass('merchrcust-image-canvas-wrapper').css({backgroundImage: 'url(' + $img.attr('src') + ')', height: data.size, width: data.size}).appendTo($merchrgallery);
439	//	var $image = $('<img>').appendTo($imgwrapper);
440	//	merchrcustFlatCanvas.overlayFabricText($image, data);
441	//},
442	
443	initTextInput(){
444		const $ = jQuery;
445		const self = this;
446		$('.js__merchrcustCustomTextInput').on('keyup change blur', function(e){
447			var val = $(this).val();
448			localStorage.setItem(self.local_storage_custom_key, val);
449			if (e.type !== 'keydown' && e.type !=='keyup'){
450				// trim but not while typing
451				val = $.trim(val);
452			}else{
453				self.updateQueryString();
454			}
455			merchrcustFlatCanvas.setText(val);
456		});
457		
458		var current = localStorage.getItem(self.local_storage_custom_key);
459		if (current !== '') {
460			$('.js__merchrcustCustomTextInput').val(current);
461		}
462	},
463	
464	initCustomisationOption(){
465		const self = this;
466		const $ = jQuery;
467		$('#merchrcust-customisation-select input').on('click onInit', function(){
468			var checked = $('#merchrcust-customisation-select input:checked').val();
469			$('.merchrcust-fields').toggle(checked !== 'none');
470			$('.merchrcust-fields-customisation').hide();
471			$('.merchrcust-fields-customisation__' + checked).show();
472			var prodcanvas = self.productDetailCanvas();
473			if (prodcanvas){
474				var fcanvas = prodcanvas.get(0).fcanvas;
475				if (checked !== 'none'){
476					self.storage.customisation_on = true;
477					merchrcustFlatCanvas.updateCanvasToImage(fcanvas);
478					if (checked === 'image'){
479						merchrcustFlatCanvas.hideTextInFCanvas(fcanvas);
480						merchrcustFlatCanvas.showImagesInFCanvas(fcanvas);
481					}else{
482						merchrcustFlatCanvas.hideImagesInFCanvas(fcanvas);
483						merchrcustFlatCanvas.showTextInFCanvas(fcanvas);
484					}
485				}else{
486					merchrcustFlatCanvas.hideCanvasPreview(fcanvas);
487					self.storage.customisation_on = false;
488				}
489			}
490		}).trigger('onInit');
491	},
492	
493	initFontFamilyChange(){
494		const self = this;
495		const $ = jQuery;
496		const current = localStorage.getItem(self.local_storage_custom_font_key);
497        
498        if (current !== null) {
499            $('#merchrcust_fontfamily_select').val(current);
500            merchrcustFlatCanvas.setFontFamily(self.productDetailCanvas(), current);
501        }
502        
503        $('#merchrcust_fontfamily_select').on('change',function(){
504			var prodcanvas = self.productDetailCanvas();
505			var style = $(this).find('option:selected').attr('style');
506			$(this).attr('style', style);
507			if (prodcanvas){
508				merchrcustFlatCanvas.setFontFamily(self.productDetailCanvas(), $(this).val());
509                localStorage.setItem(self.local_storage_custom_font_key, $(this).val());
510			}
511		}).trigger('change');
512	},
513	
514	updateQueryString(){
515		const self = this;
516		var text = localStorage.getItem(self.local_storage_custom_key);
517		var newurl = replaceUrlParam(window.location.href, self.querystring_custom_key, text);
518		history.replaceState({}, '', newurl);
519	},
520	
521	resetToDefaultTextButton(){
522		const $ = jQuery;
523		const self = this;
524		$('.js__merchrcustResetText').on('click', function(e){
525			e.preventDefault();
526			self.resetCustomTextInput();
527		});
528	},
529	
530	resetCustomTextInput(){
531		const $ = jQuery;
532		const self = this;
533		localStorage.setItem(self.local_storage_custom_key, '');
534		self.updateQueryString();
535		window.location.reload();
536	},
537	
538	copyToClipboard(){
539		const $ = jQuery;
540		const self = this;
541		$('.js__copyToClipboardFromUrl').on('click', function(e){
542			e.preventDefault();
543			copyTextToClipboard(window.location.href);
544			self.tinyNotice(e, 'Copied');
545		});
546	},
547	
548	showWhiteRemovalOptions(){
549		const $ = jQuery;
550		$('#merchrcust-remove-white-button').show();
551	},
552	
553	hideWhiteRemovalOptions(){
554		const $ = jQuery;
555		$('#merchrcust-remove-white-button').hide();
556	},
557
558	// -------------------------------------------------------------------------
559	
560	tinyNotice(e, text){
561		const $ = jQuery;
562		var $notice = $('<div>').addClass('tinynotice').text(text).appendTo('body').css({position: 'absolute', top: e.pageY - 30, left: e.pageX, zIndex:9999});
563		setTimeout(function(){
564			$notice.remove();
565		}, 1000);
566	}
567	
568};
569
570if (typeof 'copyTextToClipboard' !== 'function'){
571	function copyTextToClipboard(text) {
572		const el = document.createElement('textarea');
573		el.value = text;
574		el.setAttribute('readonly', '');
575		el.style.position = 'absolute';
576		el.style.left = '-9999px';
577		document.body.appendChild(el);
578		el.select();
579		document.execCommand('copy');
580		document.body.removeChild(el);
581	}
582}

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.