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.