customizer-base.js (203735B)
1 (function ($) { 2 if (!Element.prototype.scrollIntoViewIfNeeded) { 3 Element.prototype.scrollIntoViewIfNeeded = function (centerIfNeeded) { 4 centerIfNeeded = arguments.length === 0 ? true : !!centerIfNeeded; 5 6 var parent = this.parentNode, 7 parentComputedStyle = window.getComputedStyle(parent, null), 8 parentBorderTopWidth = parseInt(parentComputedStyle.getPropertyValue('border-top-width')), 9 parentBorderLeftWidth = parseInt(parentComputedStyle.getPropertyValue('border-left-width')), 10 overTop = this.offsetTop - parent.offsetTop < parent.scrollTop, 11 overBottom = (this.offsetTop - parent.offsetTop + this.clientHeight - parentBorderTopWidth) > (parent.scrollTop + parent.clientHeight), 12 overLeft = this.offsetLeft - parent.offsetLeft < parent.scrollLeft, 13 overRight = (this.offsetLeft - parent.offsetLeft + this.clientWidth - parentBorderLeftWidth) > (parent.scrollLeft + parent.clientWidth), 14 alignWithTop = overTop && !overBottom; 15 16 if ((overTop || overBottom) && centerIfNeeded) { 17 parent.scrollTop = this.offsetTop - parent.offsetTop - parent.clientHeight / 2 - parentBorderTopWidth + this.clientHeight / 2; 18 } 19 20 if ((overLeft || overRight) && centerIfNeeded) { 21 parent.scrollLeft = this.offsetLeft - parent.offsetLeft - parent.clientWidth / 2 - parentBorderLeftWidth + this.clientWidth / 2; 22 } 23 24 if ((overTop || overBottom || overLeft || overRight) && !centerIfNeeded) { 25 this.scrollIntoView(alignWithTop); 26 } 27 }; 28 } 29 30 $.fn.tagName = function () { 31 if (!this[0]) 32 return null; 33 if (this[0] && this[0].nodeName) { 34 return this[0].nodeName.toLowerCase(); 35 } 36 return null; 37 }; 38 39 $.fn.insertAt = function (index, $parent) { 40 return this.each(function () { 41 if ($(this).parent().is($parent)) { 42 var siblings = $(this).siblings(); 43 if (index < siblings.length) { 44 siblings.eq(index).before(this); 45 } else { 46 siblings.last().after(this); 47 } 48 } else { 49 if (index === 0 || !$parent.children().length) { 50 $parent.prepend(this); 51 } else { 52 if (index >= $parent.children().length) { 53 $parent.append(this); 54 } else { 55 $parent.children().eq(index - 1).after(this); 56 } 57 } 58 } 59 }); 60 }; 61 62 63 if (!NodeList.prototype.forEach) { 64 NodeList.prototype.forEach = Array.prototype.forEach; 65 HTMLCollection.prototype.forEach = Array.prototype.forEach; // Because of https://bugzilla.mozilla.org/show_bug.cgi?id=14869 66 67 } 68 69 if (!Array.from) { 70 Array.from = function (object) { 71 return [].slice.call(object); 72 }; 73 } 74 75 76 })(jQuery); 77 78 (function ($, root) { 79 80 wp.customize.bind("save-request-params", function (query) { 81 query.customize_post_id = CP_Customizer.preview.data().pageID; 82 if (CP_Customizer && CP_Customizer.hooks) { 83 query = CP_Customizer.hooks.applyFilters('save-request-params', query); 84 } 85 return query; 86 }); 87 88 function translateCompanionString(text) { 89 90 if (!text || !_.isString(text)) { 91 return text; 92 } 93 94 if (root.__materialisCustomizerStrings[text] !== undefined) { 95 return root.__materialisCustomizerStrings[text]; 96 } else { 97 //in debug mode 98 if (CP_Customizer.options('SCRIPT_DEBUG')) { 99 console.warn("[Not translated] " + text); 100 } 101 return text; 102 } 103 } 104 105 var CP_Customizer = { 106 events: { 107 "PREVIEW_LOADED": "PREVIEW_LOADED", 108 "ADD_FIXED_OVERLAYS": "ADD_FIXED_OVERLAYS", 109 "RIGHT_SECTION_CLOSED": "RIGHT_SECTION_CLOSED", 110 "ELEMENT_DECORATED": "ELEMENT_DECORATED", 111 "CONTENT_ROW_REMOVED": "CONTENT_ROW_REMOVED", 112 "DOCUMENT_READY": "DOCUMENT_READY", 113 "STATE_UPDATED": "STATE_UPDATED", 114 "FOCUS_CONTROL": "FOCUS_CONTROL" 115 }, 116 117 getSlug: window.getSlug, 118 119 wpApi: wp.customize, 120 121 MAX_SAFE_INTEGER: Number.MAX_SAFE_INTEGER ? Number.MAX_SAFE_INTEGER : 9007199254740991, 122 123 hooks: window.hooksManager, 124 125 CONTENT_ELEMENTS: 'p,h1,h2,h3,h4,h5,h6,a,span,i,hr,img,ul,div.spacer', 126 TEXT_ELEMENTS: "p,h1,h2,h3,h4,h5,h6,span", 127 THEME_MOD_NODES: '[data-theme],[data-theme-src],[data-theme-mdi]', 128 129 translateCompanionString: translateCompanionString, 130 131 data: function () { 132 return root.cpCustomizerGlobal.pluginOptions.data; 133 }, 134 135 addContentElementsSelectors: function (selectors) { 136 if (!_.isArray(selectors)) { 137 selectors = [selectors] 138 } 139 140 this.CONTENT_ELEMENTS = this.CONTENT_ELEMENTS.split(',').concat(selectors).join(',') 141 }, 142 143 IO: { 144 get: function (action, data) { 145 return this.send({ 146 data: _.isObject(action) ? action : _.extend(data || {}, {action: action}), 147 type: 'GET' 148 }); 149 }, 150 post: function (action, data) { 151 return this.send({ 152 data: _.isObject(action) ? action : _.extend(data || {}, {action: action}) 153 }); 154 }, 155 156 157 customGet: function (url, data) { 158 data = _.isObject(data) ? data : {}; 159 var options = { 160 type: "GET", 161 data: data 162 }; 163 164 165 return CP_Customizer.IO.customSend(url, options); 166 }, 167 customPost: function (url, data) { 168 data = _.isObject(data) ? data : {}; 169 var options = { 170 type: "POST", 171 data: data 172 }; 173 174 return CP_Customizer.IO.customSend(url, options); 175 }, 176 177 customSend: function (url, options) { 178 179 options = _.defaults(options || {}, { 180 type: 'POST', 181 url: url 182 }); 183 184 return CP_Customizer.IO.send(options); 185 }, 186 187 rest: { 188 get: function (route, data) { 189 data = _.isObject(data) ? data : {}; 190 var options = { 191 type: "GET", 192 data: data 193 }; 194 195 196 return CP_Customizer.IO.rest.send(route, options); 197 }, 198 post: function (route, data) { 199 data = _.isObject(data) ? data : {}; 200 var options = { 201 type: "POST", 202 data: data 203 }; 204 205 return CP_Customizer.IO.rest.send(route, options); 206 }, 207 208 send: function (route, options) { 209 var url = CP_Customizer.options('restURL'); 210 211 options = _.defaults(options || {}, { 212 type: 'POST', 213 url: CP_Customizer.utils.phpTrim(url, '/') + "/" + CP_Customizer.utils.phpTrim(route, '/') 214 }); 215 216 return CP_Customizer.IO.send(options); 217 } 218 }, 219 220 send: function (action, options) { 221 var promise, deferred; 222 if (_.isObject(action)) { 223 options = action; 224 } else { 225 options = options || {}; 226 options.data = _.extend(options.data || {}, {action: action}); 227 } 228 229 options = _.defaults(options || {}, { 230 type: 'POST', 231 url: wp.ajax.settings.url, 232 context: this, 233 _: Date.now(), 234 xhrFields: { 235 withCredentials: true 236 } 237 }); 238 239 deferred = $.Deferred(function (deferred) { 240 // Transfer success/error callbacks. 241 if (options.success) 242 deferred.done(options.success); 243 if (options.error) 244 deferred.fail(options.error); 245 246 delete options.success; 247 delete options.error; 248 249 deferred.jqXHR = $.ajax(options).done(function (response) { 250 deferred.resolveWith(this, [response, deferred.jqXHR]); 251 }).fail(function () { 252 deferred.rejectWith(this, arguments); 253 }); 254 }); 255 256 promise = deferred.promise(); 257 promise.abort = function () { 258 deferred.jqXHR.abort(); 259 return this; 260 }; 261 262 return promise; 263 } 264 }, 265 266 267 options: function (key, defaultValue) { 268 var result = root.cpCustomizerGlobal.pluginOptions; 269 270 if (key) { 271 var keyParts = key.split(':'); 272 for (var i = 0; i < keyParts.length; i++) { 273 var part = keyParts[i]; 274 275 if (!_.isUndefined(result[part])) { 276 result = result[part]; 277 } else { 278 result = defaultValue; 279 break; 280 } 281 } 282 } 283 284 return result; 285 }, 286 287 __exportsCache: {}, 288 getSectionExports: function (sectionId) { 289 290 if (sectionId.jquery) { 291 sectionId = sectionId.attr('data-export-id'); 292 } 293 294 if (this.__exportsCache[sectionId]) { 295 return this.__exportsCache[sectionId]; 296 } 297 298 var sectionData = CP_Customizer.options('data:sections', []).filter(function (s) { 299 return s.id === sectionId 300 }).pop(); 301 302 var modules = {}, 303 module = {}, 304 exports = {}; 305 306 if (sectionData && sectionData.export) { 307 try { 308 eval(sectionData.export); 309 310 if (!_.isUndefined(modules.export)) { 311 exports = modules.export; 312 } else { 313 if (!_.isUndefined(module.exports)) { 314 exports = module.exports; 315 } 316 } 317 } catch (e) { 318 console.warn('invalid section ' + sectionId + ' exports'); 319 } 320 321 } 322 323 this.__exportsCache[sectionId] = exports; 324 return exports || {}; 325 }, 326 327 328 slugPrefix: function () { 329 return root.cpCustomizerGlobal.pluginOptions.slugPrefix; 330 }, 331 332 333 log: function (name, data, type) { 334 335 if (!CP_Customizer.options('SCRIPT_DEBUG', false) && !top.SCRIPT_DEBUG) { 336 return; 337 } 338 339 type = type || 'log'; 340 341 var colors = { 342 'log': 'background-color:#03a9f4; color:#ffffff', 343 'error': 'background-color:#ff0000; color:#ffffff' 344 }; 345 346 if (!data) { 347 data = 'NO DATA'; 348 } 349 350 console.groupCollapsed('%c ' + name + ' ', colors[type]); 351 console[type](data); 352 console.groupEnd(); 353 }, 354 355 356 logError: function (name, data) { 357 this.log(name, data, 'error'); 358 }, 359 360 361 bind: function (event, callback) { 362 this.on(event, callback, false); 363 }, 364 unbind: function (event, callback) { 365 this.off(event, callback); 366 }, 367 368 on: function (event, callback, async) { 369 370 event = event.split(' ').map(function (ev) { 371 return 'cp_customizer.' + ev; 372 }).join(' '); 373 374 if (async) { 375 var originalCallback = callback; 376 377 callback = function () { 378 var args = Array.from(arguments); 379 var cb = this.callback; 380 381 setTimeout(function () { 382 cb.apply(this, args); 383 }, 0); 384 385 }.bind({ 386 callback: originalCallback 387 }); 388 } 389 390 $(window).bind(event, callback); 391 }, 392 393 off: function (event, callback) { 394 event = event.split(' ').map(function (ev) { 395 return 'cp_customizer.' + ev; 396 }).join(' '); 397 $(window).unbind(event, callback); 398 }, 399 400 one: function (event, callback) { 401 event = event.split(' ').map(function (ev) { 402 return 'cp_customizer.' + ev; 403 }).join(' '); 404 $(window).one(event, callback); 405 }, 406 407 408 trigger: function (event, data) { 409 $(window).trigger('cp_customizer.' + event, data); 410 }, 411 412 showLoader: function () { 413 $('div#cp-full-screen-loader').addClass('active'); 414 jQuery('select').each(function () { 415 var $select = $(this); 416 if ($select.data() && $select.data().selectize) { 417 $select.data().selectize.blur(); 418 } 419 }); 420 }, 421 422 hideLoader: function () { 423 $('div#cp-full-screen-loader').removeClass('active'); 424 }, 425 426 jsTPL: {}, 427 428 __containerDataHandlers: {}, 429 430 addContainerDataHandler: function (selector, getter, setter) { 431 this.__containerDataHandlers[selector] = { 432 getter: getter, 433 setter: setter 434 }; 435 }, 436 437 __containerDataFilters: [], 438 439 addContainerDataFilter: function (callback) { 440 this.__containerDataFilters.push(callback); 441 }, 442 443 444 __modules: [], 445 __modulesLoaded: false, 446 addModule: function (callback) { 447 var self = this; 448 449 if (this.__modulesLoaded) { 450 callback(this); 451 } else { 452 this.__modules.push(callback); 453 } 454 }, 455 456 popUp: function (title, elementID, data) { 457 var selector = "#TB_inline?inlineId=" + elementID; 458 var query = []; 459 460 461 $.each(data || {}, function (key, value) { 462 query.push(key + "=" + value); 463 }); 464 465 selector = query.length ? selector + "&" : selector + ""; 466 selector += query.join("&"); 467 468 root.tb_show(title, selector); 469 470 root.jQuery('#TB_window').css({ 471 'z-index': '5000001', 472 'transform': 'opacity .4s', 473 'opacity': 0 474 }); 475 476 root.jQuery('#TB_overlay').css({ 477 'z-index': '5000000' 478 }); 479 480 481 setTimeout(function () { 482 root.jQuery('#TB_window').css({ 483 'margin-top': -1 * ((root.jQuery('#TB_window').outerHeight() + 50) / 2), 484 'opacity': 1 485 }); 486 root.jQuery('#TB_window').find('#cp-item-ok').focus(); 487 }, 0); 488 489 if (data && data.class) { 490 root.jQuery('#TB_window').addClass(data.class); 491 } 492 493 return root.jQuery('#TB_window'); 494 }, 495 496 497 popUpInfo: function (title, content, data) { 498 var id = _.uniqueId('temp-popup-text'); 499 500 var tempContainer = $('<div id="' + id + '" />').hide(); 501 tempContainer.appendTo($('body')); 502 tempContainer.append('<div>' + content + '</div>'); 503 504 return this.popUp(title, id, data); 505 506 }, 507 508 popupPrompt: function (title, text, value, callback, extraHTML) { 509 510 if (extraHTML) { 511 extraHTML = '<div class="prompt-extra">' + extraHTML + '</div>'; 512 } else { 513 extraHTML = ''; 514 } 515 516 var content = '' + 517 '<div class="prompt-wrapper">' + 518 ' <h4 class="prompt-title">' + text + '</h4>' + 519 ' <div class="prompt-content">' + 520 ' <input value="' + CP_Customizer.utils.htmlEscape(value) + '" type="text">' + 521 ' </div>' + 522 ' ' + extraHTML + 523 ' <div class="prompt-footer">' + 524 ' <button class="submit button button-primary"> ' + root.CP_Customizer.translateCompanionString("OK") + '</button>' + 525 ' <button class="cancel button button-secondary">' + root.CP_Customizer.translateCompanionString("Cancel") + '</button>' + 526 ' </div>' + 527 '</div>'; 528 529 var data = { 530 width: "400", 531 class: "popup-400" 532 }; 533 534 var $content = this.popUpInfo(title, content, data); 535 536 function onClose(canceled) { 537 var newValue = $content.find('input').val().trim(); 538 539 if (canceled) { 540 newValue = null; 541 } 542 543 if (_.isFunction(callback)) { 544 callback(newValue, value) 545 } 546 CP_Customizer.closePopUps(); 547 } 548 549 $content.on('keypress', 'input', function () { 550 if (event.which !== 13) { 551 return true; 552 } 553 onClose(); 554 }); 555 556 $content.on('click', 'button.submit', function () { 557 onClose(); 558 }); 559 560 561 $content.on('click', 'button.cancel', function () { 562 onClose(true); 563 }); 564 565 }, 566 567 popupSelectPrompt: function (title, text, value, options, callback, emptySelection, extraHTML) { 568 var select = '<select>'; 569 570 571 if (emptySelection) { 572 select += "<option value='' >" + emptySelection + "</option>"; 573 } 574 575 for (var i in options) { 576 var selectedAttr = (i === value) ? "selected" : ""; 577 select += "<option " + CP_Customizer.utils.htmlEscape(selectedAttr) + " value='" + i + "' >" + options[i] + "</option>"; 578 } 579 580 select += '</select>'; 581 if (extraHTML) { 582 extraHTML = '<div class="prompt-extra">' + extraHTML + '</div>'; 583 } else { 584 extraHTML = ''; 585 } 586 587 var content = '' + 588 '<div class="prompt-wrapper">' + 589 ' <h4 class="prompt-title">' + text + '</h4>' + 590 ' <div class="prompt-content">' + 591 ' ' + select + 592 ' </div>' + 593 ' ' + extraHTML + 594 ' <div class="prompt-footer">' + 595 ' <button class="submit button button-primary"> ' + root.CP_Customizer.translateCompanionString("OK") + '</button>' + 596 ' <button class="cancel button button-secondary">' + root.CP_Customizer.translateCompanionString("Cancel") + '</button>' + 597 ' </div>' + 598 '</div>'; 599 600 var data = { 601 width: "400", 602 class: "popup-400" 603 }; 604 605 var $content = this.popUpInfo(title, content, data); 606 607 function onClose(canceled) { 608 var newValue = $content.find('select').val(); 609 610 if (canceled) { 611 newValue = null; 612 } 613 614 if (_.isFunction(callback)) { 615 callback(newValue, value) 616 } 617 CP_Customizer.closePopUps(); 618 } 619 620 $content.on('click', 'button.submit', function () { 621 onClose(); 622 }); 623 624 625 $content.on('click', 'button.cancel', function () { 626 onClose(true); 627 }); 628 629 return $content; 630 631 }, 632 633 closePopUps: function () { 634 root.tb_remove(); 635 root.jQuery('#TB_overlay').css({ 636 'z-index': '-1' 637 }); 638 }, 639 640 openMultiImageManager: function (title, callback, single) { 641 var node = false; 642 var interestWindow = root; 643 custom_uploader = interestWindow.wp.media.frames.file_frame = interestWindow.wp.media({ 644 title: title, 645 button: { 646 text: root.CP_Customizer.translateCompanionString('Choose Images') 647 }, 648 multiple: !single 649 }); 650 //When a file is selected, grab the URL and set it as the text field's value 651 custom_uploader.on('select', function () { 652 var attachment = custom_uploader.state().get('selection').toJSON(); 653 callback(attachment); 654 }); 655 custom_uploader.off('close.cp').on('close.cp', function () { 656 callback(false); 657 }); 658 //Open the uploader dialog 659 custom_uploader.open(); 660 661 custom_uploader.content.mode('browse'); 662 // Show Dialog over layouts frame 663 interestWindow.jQuery(interestWindow.wp.media.frame.views.selector).parent().css({ 664 'z-index': '16000000' 665 }); 666 }, 667 668 openImageManager: function (callback, multi) { 669 this.openMultiImageManager('Image Manager', function (obj) { 670 if ($('iframe').length) { 671 $('iframe').get(0).focus(); 672 } 673 if (!obj) { 674 return; 675 } 676 for (var i = 0; i < obj.length; i++) { 677 var link = obj[i].url; 678 callback(link); 679 } 680 }, !multi); 681 }, 682 683 openMediaCustomFrame: function (extender, mode, title, single, callback) { 684 var interestWindow = root; 685 686 var frame = extender(interestWindow.wp.media.view.MediaFrame.Select); 687 688 var custom_uploader = new frame({ 689 title: title, 690 button: { 691 text: title 692 }, 693 multiple: !single 694 }); 695 696 697 //When a file is selected, grab the URL and set it as the text field's value 698 custom_uploader.on('select', function () { 699 attachment = custom_uploader.state().get('selection').toJSON(); 700 custom_uploader.content.mode('browse'); 701 callback(attachment); 702 }); 703 704 705 custom_uploader.on('close', function () { 706 custom_uploader.content.mode('browse'); 707 callback(false); 708 }); 709 710 //Open the uploader dialog 711 custom_uploader.open(); 712 custom_uploader.content.mode(mode); 713 // Show Dialog over layouts frame 714 interestWindow.jQuery(custom_uploader.views.selector).parent().css({ 715 'z-index': '16000000' 716 }); 717 718 }, 719 720 openMIManager: function (title, callback, single) { 721 var node = false; 722 var interestWindow = root; 723 724 // if (!interestWindow.wp.media.cp.FAFrame) { 725 var frame = interestWindow.wp.media.cp.extendFrameWithMDI(interestWindow.wp.media.view.MediaFrame.Select); 726 var custom_uploader = new frame({ 727 title: title, 728 button: { 729 text: root.CP_Customizer.translateCompanionString('Choose Icon') 730 }, 731 multiple: !single 732 }); 733 interestWindow.wp.media.cp.MIFrame = custom_uploader; 734 735 // } 736 737 738 //When a file is selected, grab the URL and set it as the text field's value 739 interestWindow.wp.media.cp.MIFrame.on('select', function () { 740 attachment = custom_uploader.state().get('selection').toJSON(); 741 interestWindow.wp.media.cp.MIFrame.content.mode('browse'); 742 callback(attachment); 743 }); 744 interestWindow.wp.media.cp.MIFrame.on('close', function () { 745 interestWindow.wp.media.cp.MIFrame.content.mode('browse'); 746 callback(false); 747 }); 748 749 //Open the uploader dialog 750 interestWindow.wp.media.cp.MIFrame.open(); 751 interestWindow.wp.media.cp.MIFrame.content.mode('cp_material_icons'); 752 // Show Dialog over layouts frame 753 interestWindow.jQuery(custom_uploader.views.selector).parent().css({ 754 'z-index': '16000000' 755 }); 756 757 }, 758 759 openCropableImageManager: function (width, height, flexible, callback) { 760 var control = new root.wp.customize.CroppedImageControl('custom_image_cropper[' + Date.now() + ']', 761 {params: {}}); 762 763 control.params = { 764 button_labels: { 765 frame_title: root.CP_Customizer.translateCompanionString("Select Image") 766 }, 767 height: height, 768 width: width 769 770 }; 771 772 flexible = _.isUndefined(flexible) ? true : flexible; 773 774 if (flexible) { 775 control.params = _.extend(control.params, { 776 flex_width: width, 777 flex_height: height 778 }); 779 } 780 781 control.initFrame(); 782 control.frame.setState('library').open(); 783 control.frame.content.mode('browse'); 784 785 function fixCropKeyPressBug() { 786 setTimeout(function () { 787 root.jQuery(top.document).unbind(root.jQuery.imgAreaSelect.keyPress); 788 }, 100); 789 } 790 791 control.setImageFromAttachment = function (attachment) { 792 callback([attachment]); 793 fixCropKeyPressBug(); 794 }; 795 796 control.frame.on('close', function () { 797 fixCropKeyPressBug(); 798 }); 799 800 801 root.jQuery(control.frame.views.selector).parent().css({ 802 'z-index': '16000000' 803 }); 804 805 root.jQuery(control.frame.views.selector).find('.instructions').remove(); 806 807 808 control.frame.on('content:create:crop', function () { 809 var c = control; 810 var state = c.frame.state(); 811 var __createCropToolbar = state.createCropToolbar; 812 state.createCropToolbar = function () { 813 state.set('canSkipCrop', true); 814 __createCropToolbar.apply(state, arguments); 815 }; 816 817 }); 818 }, 819 820 openGalleryImageManager: function (options, callback) { 821 var interestWindow = root; 822 options = _.extend({ 823 "shortocode": false, 824 "ids": [], 825 "columns": "5", 826 "state": 'gallery-edit', 827 "size": "medium", 828 "link": "file" 829 }, options); 830 831 832 if (_.isArray(options.ids)) { 833 options.ids = options.ids.join(","); 834 } 835 836 if (_.isEmpty(options.ids.trim())) { 837 options.ids = 'fake-' + Date.now(); 838 } 839 840 var shortcode = "[gallery"; 841 $.each(options, function (index, val) { 842 shortcode += " " + index + '="' + val + '"'; 843 }); 844 shortcode += "]"; 845 846 var gallery = interestWindow.wp.media.gallery; 847 var frame = gallery.edit(shortcode); 848 849 850 frame.state(options.state).on('update', function (selection) { 851 var ids = selection.map(function (model) { 852 return model.id 853 }); 854 callback(selection, ids); 855 }); 856 857 858 // if (options.mediaSidebar === false) { 859 // frame.$el.find('.media-sidebar').hide(); 860 // frame.$el.find('.media-sidebar').siblings('.media-toolbar ul').css('right', '0px'); 861 // } else { 862 // frame.$el.find('.media-sidebar').siblings('.media-toolbar ul').css('right', ''); 863 // frame.$el.find('.media-sidebar').show(); 864 // } 865 866 interestWindow.jQuery(frame.views.selector).parent().css({ 867 'z-index': '16000000' 868 }); 869 870 if (options.ids.match(/fake-\d+/)) { 871 frame.setState('gallery-library') 872 } 873 }, 874 875 openMediaBrowser: function (type, callback, data) { 876 var cb; 877 if (callback instanceof jQuery) { 878 cb = function (response) { 879 880 if (!response) { 881 return; 882 } 883 884 var value = response[0].url; 885 if (data !== "multiple") { 886 if (type == "icon") { 887 value = response[0].mdi; 888 } 889 callback.val(value).trigger('change'); 890 } 891 }; 892 } else { 893 cb = function () { 894 callback.apply(this, arguments); 895 CP_Customizer.preview.blur(); 896 } 897 } 898 899 switch (type) { 900 case "image": 901 // this.openMultiImageManager('Change image', cb, data); 902 this.openCropableImageManager(data.width || this.MAX_SAFE_INTEGER, data.height || this.MAX_SAFE_INTEGER, true, cb); 903 break; 904 case "cropable": 905 this.openCropableImageManager(data.width, data.height, data.flexible, cb); 906 break; 907 case "icon": 908 this.openMIManager(root.CP_Customizer.translateCompanionString('Change Material Icon'), cb); 909 break; 910 case "gallery": 911 this.openGalleryImageManager(data, cb); 912 break; 913 } 914 }, 915 916 getCustomizerRootEl: function () { 917 return root.jQuery(root.document.body).find('form#customize-controls'); 918 }, 919 920 openRightSidebar: function (elementId, options) { 921 options = options || {}; 922 this.hideRightSidebar(); 923 var $form = this.getCustomizerRootEl(); 924 var $container = $form.find('#' + elementId + '-popup'); 925 926 $('body').addClass('cp-right-section-opened'); 927 if ($container.length) { 928 $container.addClass('active'); 929 930 if (options.floating && !_(options.y).isUndefined()) { 931 $container.css({ 932 top: options.y 933 }); 934 } 935 } else { 936 $container = $('<li id="' + elementId + '-popup" class="customizer-right-section active"> <span data-close-right-sidebar="true" title="' + root.CP_Customizer.translateCompanionString("Close Panel") + '" class="close-panel"></span> </li>'); 937 938 if (options.floating) { 939 $container.addClass('floating'); 940 } 941 942 $toAppend = $form.find('li#accordion-section-' + elementId + ' > ul'); 943 944 if ($toAppend.length === 0) { 945 $toAppend = $form.find('#sub-accordion-section-' + elementId); 946 } 947 948 949 if ($toAppend.length === 0) { 950 $toAppend = $('<div class="control-wrapper" />'); 951 $toAppend.append($form.find('#customize-control-' + elementId).children()); 952 } 953 954 $form.append($container); 955 $container.append($toAppend); 956 957 if (options.floating && !_(options.y).isUndefined()) { 958 $container.css({ 959 top: options.y 960 }); 961 } 962 963 964 $container.find('span.close-panel').click(CP_Customizer.hideRightSidebar); 965 966 } 967 968 if (options.focus) { 969 $container.find(options.focus)[0].scrollIntoViewIfNeeded(); 970 } 971 972 $container.css('left', jQuery('#customize-header-actions')[0].offsetWidth + 1); 973 974 CP_Customizer.hooks.doAction('right_sidebar_opened', elementId, options, $container); 975 976 $form.find('span[data-close-right-sidebar="true"]').click(function (event) { 977 event.preventDefault(); 978 event.stopPropagation(); 979 CP_Customizer.hideRightSidebar(); 980 }); 981 982 $form.find('li.accordion-section').unbind('click.right-section').bind('click.right-section', function (event) { 983 if ($(event.target).is('li') || $(event.target).is('.accordion-section-title')) { 984 if ($(event.target).closest('.customizer-right-section').length === 0) { 985 CP_Customizer.hideRightSidebar(); 986 } 987 } 988 }); 989 990 }, 991 992 hideRightSidebar: function () { 993 var $form = root.jQuery(root.document.body).find('#customize-controls'); 994 var $visibleSection = $form.find('.customizer-right-section.active'); 995 if ($visibleSection.length) { 996 $visibleSection.removeClass('active'); 997 root.CP_Customizer.trigger(root.CP_Customizer.events.RIGHT_SECTION_CLOSED, [$visibleSection]); 998 } 999 1000 }, 1001 1002 isRightSidebarVisible: function (sectionID) { 1003 var $form = root.jQuery(root.document.body).find('#customize-controls'); 1004 return $form.find('#' + sectionID + '-popup').hasClass('active'); 1005 }, 1006 1007 updateState: function (force, forceOverlays) { 1008 1009 function callback() { 1010 CP_Customizer.trigger('STATE_UPDATED'); 1011 } 1012 1013 if (force) { 1014 this._setContent(callback); 1015 } else { 1016 this.setContent(callback); 1017 } 1018 1019 this.overlays.hoverOverlay().hide(); 1020 this.overlays.updateAllOverlays(forceOverlays); 1021 }, 1022 1023 1024 __changesetUpdate: _.debounce(function (callback) { 1025 var changeSet = root.CP_Customizer.wpApi.requestChangesetUpdate.apply(root.CP_Customizer.wpApi); 1026 if (_.isFunction(callback)) { 1027 changeSet.then(callback); 1028 } 1029 }, 10), 1030 1031 __requestCachedCbs: [], 1032 requestChangesetUpdate: function (cb) { 1033 if (_.isFunction(cb)) { 1034 this.__requestCachedCbs.push(cb); 1035 } 1036 var self = this; 1037 this.__changesetUpdate(function () { 1038 while (self.__requestCachedCbs.length) { 1039 var cb = self.__requestCachedCbs.shift(); 1040 cb.call(self); 1041 } 1042 }); 1043 }, 1044 1045 // if the mod is not set create a dirty one 1046 __onSetForcedTransport: {}, 1047 setMod: function (mod, value, transport, reqCB) { 1048 1049 mod = CP_Customizer.utils.phpTrim(mod, "|"); 1050 1051 var initialMod = mod; 1052 var modParts = mod.split('|'); 1053 mod = modParts.shift(); 1054 1055 var setting = root.wp.customize(mod); 1056 value = _.clone(value); 1057 if (!setting) { 1058 mod = "CP_AUTO_SETTING[" + mod + "]"; 1059 setting = root.wp.customize(mod); 1060 if (!setting) { 1061 setting = wp.customize.create(mod, mod, {}, { 1062 type: 'theme_mod', 1063 transport: (transport || 'postMessage'), 1064 previewer: wp.customize.previewer 1065 }); 1066 } 1067 } 1068 1069 var oldTransport = setting.transport; 1070 if (!this.__onSetForcedTransport[setting.id]) { 1071 this.__onSetForcedTransport[setting.id] = oldTransport; 1072 } 1073 1074 if (transport) { 1075 setting.transport = transport; 1076 } 1077 1078 var oldValue = _.clone(setting._value); 1079 1080 var jsonEncoded = false; 1081 try { 1082 var parsed = decodeURI(oldValue); 1083 parsed = JSON.parse(parsed); 1084 1085 if (_.isObject(parsed) || _.isArray(parsed)) { 1086 oldValue = parsed; 1087 jsonEncoded = true; 1088 } 1089 } catch (e) { 1090 1091 } 1092 1093 if (_.isObject(oldValue)) { 1094 setting._value = undefined; // force no value before set( forces the setting to set the value ) 1095 } 1096 1097 if (modParts.length) { 1098 1099 if (!oldValue || _.isEmpty(oldValue)) { 1100 oldValue = CP_Customizer.preview.data('mod_defaults')[mod]; 1101 } 1102 1103 var path = modParts.join('.'); 1104 value = CP_Customizer.utils.setToPath(oldValue, path, value); 1105 } 1106 1107 var control = wp.customize.control(mod); 1108 1109 1110 if (jsonEncoded) { 1111 value = encodeURI(JSON.stringify(value)); 1112 } 1113 1114 if (_.isBoolean(oldValue)) { 1115 try { 1116 value = JSON.parse(value); 1117 } catch (e) { 1118 1119 } 1120 } 1121 1122 setting.set(value); 1123 1124 // update control 1125 1126 if (control) { 1127 var type = control.params.type; 1128 if (type === "radio-html") { 1129 jQuery(control.container.find('input[value="' + value + '"]')).prop('checked', true); 1130 } else { 1131 if (type === "kirki-spacing") { 1132 for (var prop in value) { 1133 if (value.hasOwnProperty(prop)) { 1134 jQuery(control.container.find('.' + prop + ' input')).prop('value', value[prop]); 1135 } 1136 } 1137 } else { 1138 if (type.match('kirki')) { 1139 kirkiSetSettingValue(mod, value); 1140 } else { 1141 if (type == "gradient-control-pro") { 1142 control.setValue(value); 1143 } else { 1144 if (type == "repeater") { 1145 control.setValue(value); 1146 } 1147 } 1148 } 1149 } 1150 } 1151 } 1152 1153 var self = this; 1154 var changeSetCB = function () { 1155 if (self.__onSetForcedTransport[setting.id]) { 1156 setting.transport = self.__onSetForcedTransport[setting.id]; 1157 self.__onSetForcedTransport[setting.id] = null; 1158 } 1159 1160 if (_.isFunction(reqCB)) { 1161 reqCB(initialMod, setting.id); 1162 } 1163 1164 }; 1165 1166 if (_.isFunction(reqCB)) { 1167 this.requestChangesetUpdate(changeSetCB); 1168 } else { 1169 setting.transport = oldTransport; 1170 } 1171 1172 }, 1173 1174 getMod: function (mod, defaultValue) { 1175 var setting = root.wp.customize(mod); 1176 if (!setting) { 1177 mod = "CP_AUTO_SETTING[" + mod + "]"; 1178 setting = root.wp.customize(mod); 1179 } 1180 1181 if (!setting) { 1182 return defaultValue; 1183 } 1184 1185 return _.clone(setting.get()); 1186 }, 1187 1188 cleanModValue: function (value) { 1189 1190 if (_.isString(value)) { 1191 1192 // remove extra mdi classes ( e.g. "mdi mdi mdi" ) 1193 value = value.replace(/(mdi\s(mdi\s)+)/ig, 'mdi '); 1194 1195 // trim all spaces 1196 value = value.trim(); 1197 } 1198 1199 return value; 1200 }, 1201 1202 onModChange: function (mod, callback) { 1203 var autoMod = "CP_AUTO_SETTING[" + mod + "]"; 1204 var modCallback = _.debounce(function (value) { 1205 if (_.isFunction(callback)) { 1206 value.bind(callback); 1207 } 1208 }, 100); 1209 1210 1211 CP_Customizer.wpApi(mod, modCallback); 1212 CP_Customizer.wpApi(autoMod, modCallback); 1213 1214 }, 1215 1216 setMultipleMods: function (mods, transport, finishCb) { 1217 1218 CP_Customizer.log('Set Multiple Mods', mods); 1219 1220 if (_.isEmpty(mods)) { 1221 if (finishCb) finishCb(); 1222 return; 1223 } 1224 1225 $(root).off('blur.wp-customize-changeset-update'); 1226 var modsIDs = Object.getOwnPropertyNames(mods); 1227 var modsDone = []; 1228 1229 var reqCB = function (mod) { 1230 if (modsDone.indexOf(mod) === -1) { 1231 modsDone.push(mod); 1232 } 1233 1234 if (_.difference(modsIDs, modsDone).length === 0) { 1235 if (_.isFunction(finishCb)) { 1236 finishCb(); 1237 } 1238 } 1239 }; 1240 1241 1242 _.each(mods, function (value, mod) { 1243 CP_Customizer.setMod(mod, value, transport, reqCB); 1244 }); 1245 }, 1246 1247 _currentContentValues: {}, 1248 _setContent: function (callback) { 1249 var previewJQuery = CP_Customizer.preview.jQuery(); 1250 1251 if (root.CP_Customizer.preview.data().maintainable) { 1252 var content = root.CP_Customizer.preview.getContent().trim(); 1253 var setting = root.wp.customize('page_content'); 1254 if (!setting) { 1255 return; 1256 } 1257 1258 var value = setting.get(); 1259 if (_.isString(value)) { 1260 value = JSON.parse(decodeURIComponent(value)); 1261 } 1262 1263 if (_.isArray(value) && _.isEmpty(value)) { 1264 value = {}; 1265 } 1266 1267 if (!value) { 1268 value = {}; 1269 } 1270 1271 value[root.CP_Customizer.preview.data().pageID] = content; 1272 1273 setting.set(encodeURIComponent(JSON.stringify(value))); 1274 } 1275 1276 var modsToSet = {}; 1277 1278 this.preview.find("[data-theme-href]").each(function () { 1279 var prop = jQuery(this).attr('data-theme-href'); 1280 var val = jQuery(this).attr('href').trim(); 1281 1282 modsToSet[prop] = CP_Customizer.preview.cleanURL(val); 1283 }); 1284 1285 this.preview.find("[data-theme-target]").each(function () { 1286 var prop = jQuery(this).attr('data-theme-target'); 1287 var val = jQuery(this).attr('target') || "_self"; 1288 1289 modsToSet[prop] = val.trim(); 1290 }); 1291 1292 1293 this.preview.find("[data-theme-src]").each(function () { 1294 var prop = jQuery(this).attr('data-theme-src'); 1295 var val = jQuery(this).attr('src'); 1296 // root.CP_Customizer.setMod(prop, val.trim()); 1297 modsToSet[prop] = val.trim(); 1298 }); 1299 1300 this.preview.find("[data-theme-mdi]").each(function () { 1301 var prop = jQuery(this).attr('data-theme-mdi'); 1302 var val = jQuery(this).attr('class').match(/mdi\-[a-z\-]+/ig).pop(); 1303 // root.CP_Customizer.setMod(prop, val.trim()); 1304 modsToSet[prop] = val.trim(); 1305 }); 1306 1307 if (root.CP_Customizer.options().mods) { 1308 for (var selector in root.CP_Customizer.options().mods) { 1309 var $el = this.preview.find(selector); 1310 var modData = root.CP_Customizer.options().mods[selector]; 1311 if (modData.atts) { 1312 for (var attr in modData.atts) { 1313 // $el.attr('data-theme-' + attr, modData.atts[attr]); 1314 var prop = $el.attr('data-theme-' + attr); 1315 var val = root.CP_Customizer.hooks.applyFilters('temp_attr_mod_value', $el.attr(attr) || "", attr, $el); 1316 // root.CP_Customizer.setMod(prop, val.trim()); 1317 modsToSet[prop] = val.trim(); 1318 } 1319 } 1320 1321 1322 } 1323 } 1324 1325 this.preview.find("[data-dynamic-mod='true'],[data-dynamic-mod='true'] *").each(function () { 1326 var atts = Array.from(this.attributes), 1327 $el = root.CP_Customizer.preview.find(this); 1328 1329 for (var i = 0; i < atts.length; i++) { 1330 var attr = atts[i].name, 1331 prop = atts[i].value; 1332 1333 if (attr.indexOf('data-theme-') === 0) { 1334 attr = attr.replace('data-theme-', ''); 1335 var fallback = ""; 1336 1337 var value = $el.attr(attr); 1338 1339 // logica inversa aici false daca exista, true daca nu 1340 if (attr === 'data-reiki-hidden') { 1341 fallback = "true"; 1342 1343 if (value) { 1344 value = 'false'; 1345 } 1346 1347 } 1348 1349 if (attr.trim() === 'href') { 1350 value = CP_Customizer.preview.cleanURL(value); 1351 } 1352 1353 var val = root.CP_Customizer.hooks.applyFilters('temp_attr_mod_value', _.isUndefined(value) ? fallback : value, attr, $el); 1354 1355 modsToSet[prop] = CP_Customizer.cleanModValue(val); 1356 } 1357 1358 } 1359 }); 1360 1361 this.preview.find("[data-theme]").each(function () { 1362 1363 var prop = jQuery(this).attr('data-theme'); 1364 1365 if (!previewJQuery(this).data('was-changed')) { 1366 if (previewJQuery('[data-theme="' + prop + '"]').length > 1) { 1367 return; 1368 } 1369 } 1370 1371 // root.CP_Customizer.preview.cleanNode(toSave); 1372 // var toSave = jQuery(this).clone(); 1373 1374 var toSave = jQuery(this).clone(); 1375 var val = root.CP_Customizer.preview.getContent($(this)); 1376 // root.CP_Customizer.setMod(prop, val); 1377 modsToSet[prop] = val.trim(); 1378 previewJQuery(this).data('was-changed', false); 1379 }); 1380 1381 root.CP_Customizer.cleanClose(); 1382 1383 // update only when you find a change 1384 var uniqueMods = {}; 1385 var self = this; 1386 _.each(modsToSet, function (value, mod) { 1387 if (self._currentContentValues[mod] !== value) { 1388 uniqueMods[mod] = value; 1389 self._currentContentValues[mod] = value; 1390 } 1391 }); 1392 1393 CP_Customizer.setMultipleMods(uniqueMods, 'postMessage', callback); 1394 1395 }, 1396 1397 setContent: _.debounce(function (callback) { 1398 this._setContent(callback); 1399 }, 200), 1400 1401 save: function () { 1402 1403 CP_Customizer.preview.blur(); 1404 1405 $(root.document).find('body').addClass('saving'); 1406 $(root.document).find('input#save').prop('disabled', true); 1407 1408 var self = this; 1409 var callback = function () { 1410 wp.customize.previewer.save(); 1411 }; 1412 self._setContent(callback); 1413 1414 }, 1415 1416 cleanClose: function () { 1417 1418 }, 1419 1420 __saveTimeout: false, 1421 1422 markSave: _.debounce(function () { 1423 var self = this; 1424 clearTimeout(self.__saveTimeout); 1425 1426 self.__saveTimeout = setTimeout(function () { 1427 self.setContent(); 1428 }, 500); 1429 }, 200), 1430 1431 1432 parseShortcode: function (shortcode) { 1433 shortcode = shortcode.replace('[', '').replace(']', ''); 1434 1435 var tag = shortcode.split(' ')[0].trim(); 1436 var shortcodeAttrs = shortcode.match(/(\s(.*?)=")(.*?)(")/ig); 1437 var response = { 1438 tag: tag, 1439 attrs: {} 1440 }; 1441 if (!shortcodeAttrs) { 1442 return response; 1443 } 1444 for (var i = 0; i < shortcodeAttrs.length; i++) { 1445 var attr = shortcodeAttrs[i].trim(); 1446 response.attrs[attr.split('=')[0]] = attr.split('="')[1].slice(0, -1) 1447 } 1448 return response; 1449 1450 }, 1451 1452 isShortcodeContent: function ($node) { 1453 return root.jQuery($node).closest('[data-content-shortcode]').length > 0; 1454 }, 1455 1456 isShortcodeEditable: function ($node) { 1457 var isEditableByTag = root.jQuery($node).closest('[data-content-shortcode][data-editable="true"]').length > 0; 1458 var tag = CP_Customizer.getNodeShortcode(root.jQuery($node).closest('[data-content-shortcode]')); 1459 1460 return CP_Customizer.hooks.applyFilters('is_shortcode_editable', isEditableByTag, tag); 1461 }, 1462 1463 isOnCanvasMod: function (node) { 1464 node = $(node)[0]; 1465 var hasThemeModAtt = Array.from(node.attributes).map(function (a) { 1466 1467 return (a.name.toLowerCase().indexOf('data-theme') !== -1); 1468 1469 }).reduce(function (a, b) { 1470 return a || b; 1471 }); 1472 1473 return hasThemeModAtt; 1474 }, 1475 1476 nodeWrapsShortcode: function ($node, tag) { 1477 var shortcode = this.getNodeShortcode($node); 1478 1479 if (shortcode) { 1480 return (shortcode.tag === tag.trim()); 1481 } 1482 1483 return false; 1484 }, 1485 1486 getNodeShortcode: function ($node) { 1487 if (!$node.attr('data-content-shortcode')) { 1488 return undefined; 1489 } 1490 1491 return this.parseShortcode($node.attr('data-content-shortcode')); 1492 }, 1493 1494 nodeContainsShortcode: function ($node, tag) { 1495 var $containers = $node.find('[data-content-shortcode]'); 1496 1497 for (var i = 0; i < $containers.length; i++) { 1498 if (CP_Customizer.nodeWrapsShortcode($containers.eq(i), tag)) { 1499 return true; 1500 } 1501 } 1502 1503 return false; 1504 }, 1505 1506 renderNodeShortcodes: function ($node) { 1507 $node = $($node); // make sure the node is wrapped with jqury 1508 var $nodes = $node.find('[data-content-shortcode]'); 1509 if ($node.is('[data-content-shortcode]')) { 1510 $nodes = $nodes.add($node); 1511 } 1512 var self = this; 1513 $nodes.each(function () { 1514 self.updateNodeShortcode($(this), "[" + $(this).attr('data-content-shortcode') + "]"); 1515 }) 1516 }, 1517 updateNodeShortcode: function ($node, shortcode, noRerender, context) { 1518 if (!$node.attr('data-content-shortcode')) { 1519 return undefined; 1520 } 1521 1522 var attrShortcode = CP_Customizer.utils.phpTrim(shortcode, '[]'); 1523 $node.attr('data-content-shortcode', attrShortcode); 1524 1525 if (noRerender !== true) { 1526 if (!context) { 1527 context = { 1528 query: CP_Customizer.preview.data().queryVars 1529 } 1530 } 1531 1532 (function ($node) { 1533 CP_Customizer.preview.pauseObserver(); 1534 CP_Customizer.preview.blur(); 1535 1536 var currentChangeset = CP_Customizer.utils.deepClone(wp.customize.previewer.query()); 1537 1538 var data = _.extend(currentChangeset, { 1539 action: 'cp_shortcode_refresh', 1540 shortcode: btoa(shortcode), 1541 context: context, 1542 _: Date.now() 1543 }); 1544 1545 $node.html('<div class="shortcode-temp-placeholder"></div>'); 1546 jQuery.ajax({ 1547 url: ajaxurl, 1548 method: 'POST', 1549 data: data 1550 }).done(function (response) { 1551 $node.empty(); 1552 $node.html(response); 1553 1554 CP_Customizer.hideLoader(); 1555 CP_Customizer.preview.decorateMods($node); 1556 CP_Customizer.preview.decorateElements($node); 1557 1558 _.delay(function () { 1559 root.CP_Customizer.hooks.doAction("shortcode_updated", $node, shortcode); 1560 root.CP_Customizer.updateState(); 1561 }, 0); 1562 }); 1563 CP_Customizer.preview.restartObserver(); 1564 })($node); 1565 } 1566 1567 CP_Customizer.updateState(); 1568 return true; 1569 }, 1570 1571 updateNodeFromShortcodeObject: function ($node, shortcodeObj, noRerender, context) { 1572 var shortcode = '[' + shortcodeObj.tag + ' '; 1573 1574 for (var a in shortcodeObj.attrs) { 1575 shortcode += a + '="' + shortcodeObj.attrs[a] + '" '; 1576 } 1577 1578 shortcode += ']'; 1579 1580 return this.updateNodeShortcode($node, shortcode, noRerender, context); 1581 }, 1582 1583 preview: { 1584 frame: function () { 1585 var frame = wp.customize.previewer.targetWindow.get(); 1586 1587 if (!frame) { 1588 frame = wp.customize.previewer.container.find('iframe')[0]; 1589 1590 if (frame) { 1591 frame = frame.contentWindow; 1592 } else { 1593 frame = null; 1594 } 1595 } 1596 1597 return frame; 1598 }, 1599 1600 currentDevice: function () { 1601 return jQuery('.active[data-device]').data('device'); 1602 }, 1603 1604 1605 __observerFunctionsToPause: ["prepareFormPreview", "prepareLinkPreview"], 1606 __observerOriginalFunctions: {}, 1607 1608 pauseObserver: function () { 1609 var previewApi = CP_Customizer.preview.frame().wp.customize; 1610 1611 this.__observerOriginalFunctions = {}; 1612 var self = CP_Customizer.preview; 1613 _.each(self.__observerFunctionsToPause, function (fn) { 1614 if (_.isFunction(previewApi[fn])) { 1615 self.__observerOriginalFunctions[fn] = previewApi[fn]; 1616 previewApi[fn] = function () { 1617 }; 1618 } 1619 }); 1620 }, 1621 1622 restartObserver: _.debounce(function () { 1623 var previewApi = CP_Customizer.preview.frame().wp.customize; 1624 1625 var self = CP_Customizer.preview; 1626 _.each(self.__observerFunctionsToPause, function (fn) { 1627 if (_.isFunction(previewApi[fn]) && _.isFunction(self.__observerOriginalFunctions[fn])) { 1628 previewApi[fn] = self.__observerOriginalFunctions[fn]; 1629 } 1630 }); 1631 }, 100), 1632 1633 1634 addSilentExecution: function (callback) { 1635 return _.compose(this.pauseObserver, callback, this.restartObserver); 1636 }, 1637 1638 silentCall: function (callback) { 1639 var args = arguments.length > 1 ? arguments[1] : undefined; 1640 var context = arguments.length > 2 ? arguments[2] : this; 1641 1642 callback = this.addSilentExecution(callback); 1643 1644 return callback.apply(context, arguments); 1645 }, 1646 1647 1648 refresh: _.throttle(function () { 1649 CP_Customizer.wpApi.previewer.refresh(); 1650 }, 100), 1651 1652 data: function (key, defaultValue) { 1653 1654 if (!this.frame()) { 1655 return {}; 1656 } 1657 1658 var result = this.frame().cpCustomizerPreview || {}; 1659 1660 if (key) { 1661 var keyParts = key.split(':'); 1662 for (var i = 0; i < keyParts.length; i++) { 1663 var part = keyParts[i]; 1664 1665 if (!_.isUndefined(result[part])) { 1666 result = result[part]; 1667 } else { 1668 result = defaultValue; 1669 break; 1670 } 1671 } 1672 } 1673 1674 return result; 1675 }, 1676 1677 getChangesetURL: function () { 1678 var changeset = wp.customize.settings.changeset.uuid ? "?changeset_uuid=" + wp.customize.settings.changeset.uuid : ""; 1679 1680 if (changeset) { 1681 changeset += "&cp__changeset__preview=" + Date.now(); 1682 } 1683 1684 return window.location.origin + window.location.pathname + changeset; 1685 }, 1686 1687 isPageMaintainable: function () { 1688 return this.data.maintainable; 1689 }, 1690 1691 // http://stackoverflow.com/questions/7451468/contenteditable-div-how-can-i-determine-if-the-cursor-is-at-the-start-or-end-o/7478420#7478420 1692 getSelectionTextInfo: function (el) { 1693 var atStart = false, atEnd = false; 1694 var window = this.frame(); 1695 var document = this.frame().document; 1696 var selRange, testRange; 1697 if (window.getSelection) { 1698 var sel = window.getSelection(); 1699 if (sel.rangeCount) { 1700 selRange = sel.getRangeAt(0); 1701 testRange = selRange.cloneRange(); 1702 1703 testRange.selectNodeContents(el); 1704 testRange.setEnd(selRange.startContainer, selRange.startOffset); 1705 atStart = (testRange.toString() == ""); 1706 1707 testRange.selectNodeContents(el); 1708 testRange.setStart(selRange.endContainer, selRange.endOffset); 1709 atEnd = (testRange.toString() == ""); 1710 } 1711 } else if (document.selection && document.selection.type != "Control") { 1712 selRange = document.selection.createRange(); 1713 testRange = selRange.duplicate(); 1714 1715 testRange.moveToElementText(el); 1716 testRange.setEndPoint("EndToStart", selRange); 1717 atStart = (testRange.text == ""); 1718 1719 testRange.moveToElementText(el); 1720 testRange.setEndPoint("StartToEnd", selRange); 1721 atEnd = (testRange.text == ""); 1722 } 1723 1724 return {atStart: atStart, atEnd: atEnd}; 1725 }, 1726 1727 isCustomFrontPage: function () { 1728 return this.data.isFrontPage; 1729 }, 1730 1731 jQuery: function (data) { 1732 if (data) { 1733 return this.frame().jQuery(data); 1734 } 1735 return this.frame().jQuery; 1736 }, 1737 1738 getPageContainerSelector: function () { 1739 1740 if (!root.CP_Customizer.preview.data().maintainable) { 1741 ''; 1742 } 1743 1744 var startSelector = "#cp_customizer_content_area_start"; 1745 1746 var attrName = 'data-cp-content-container-' + top.CP_Customizer.slugPrefix(); 1747 var $parent = this.jQuery(startSelector).parent(); 1748 if (!$parent.attr(attrName)) { 1749 $parent.attr(attrName, _.uniqueId("page-content-container-")); 1750 } 1751 1752 selector = "[" + attrName + "='" + $parent.attr(attrName) + "']"; 1753 1754 selector = CP_Customizer.hooks.applyFilters('page_content_container_selector', selector); 1755 1756 return selector; 1757 }, 1758 1759 getRootNode: function () { 1760 if (!wp.customize('page_content')) { 1761 return this.jQuery("<div/>"); 1762 } 1763 1764 return this.find(this.getPageContainerSelector()); 1765 }, 1766 1767 find: function (query) { 1768 var $ = this.jQuery(); 1769 return $(query); 1770 }, 1771 1772 getSectionByDataId: function (id) { 1773 return this.find('[data-id="' + id + '"]'); 1774 }, 1775 1776 getNodeSection: function (node) { 1777 var $node = CP_Customizer.preview.jQuery(node); 1778 if ($node.is('[data-id]')) { 1779 return $node; 1780 } else { 1781 return $node.closest('[data-id]'); 1782 } 1783 }, 1784 1785 getNodeAbsSelector: function (node, relativeSelector) { 1786 var section = this.getNodeSection(node), 1787 sectionId = "[data-id='" + section.attr('data-id') + "']", 1788 absSelector = sectionId + ' ' + relativeSelector; 1789 1790 return absSelector.replace(/\s\s?/, ' ').trim(); 1791 }, 1792 1793 getNodeSectionId: function (node) { 1794 var section = this.getNodeSection(node); 1795 return section.attr('data-id'); 1796 }, 1797 1798 getNodeExportId: function (node) { 1799 var section = this.getNodeSection(node); 1800 return section.attr('data-export-id'); 1801 }, 1802 1803 getThemeMods: function ($container) { 1804 if (!$container || $container.is(this.getRootNode())) { 1805 $container = this.jQuery('body'); 1806 } 1807 1808 var themeModNodesSelector = root.CP_Customizer.hooks.applyFilters('theme_mod_nodes_selector', root.CP_Customizer.THEME_MOD_NODES); 1809 1810 if (root.CP_Customizer.options().mods) { 1811 for (var m in root.CP_Customizer.options().mods) { 1812 themeModNodesSelector += ',' + m; 1813 } 1814 } 1815 1816 $themeModNodes = $container.find(themeModNodesSelector); 1817 1818 if ($container.is(themeModNodesSelector)) { 1819 $themeModNodes.add($container); 1820 } 1821 1822 return $themeModNodes; 1823 }, 1824 1825 getContentNodes: function (filter) { 1826 //replaced children() with contents() to also get html comments for gutenberg blocks 1827 var nodes = this.getRootNode().contents().toArray(); 1828 nodes.html = function () { 1829 return this.map(function (node) { 1830 if (node.nodeType == Node.COMMENT_NODE) { 1831 return "<!--" + node.textContent + "-->"; 1832 } else { 1833 return node.outerHTML; 1834 } 1835 }).join(''); 1836 }; 1837 1838 return nodes; 1839 }, 1840 1841 getContent: function ($node) { 1842 1843 $node = $node || this.getContentNodes(); 1844 var nodesHML = $node.html().//remove all gutenberg block comments they will be added back by decorate 1845 replace(/<!-- \/?wp:extendstudio\/materialis -->/gi, ''). 1846 replace(/[\w-]+="gutenberg-section-\d+"/gi, ''). 1847 replace(/[\w-]+="Gutenberg"/gi, ''); 1848 1849 var $currentNodes = $('<div/>').append(nodesHML); 1850 1851 $currentNodes.find('.reiki-customizer-ordering-overlay').remove(); 1852 1853 // cleanup inline styling, leaving only background properties and typography 1854 $currentNodes[0].querySelectorAll('[style]').forEach(function (el) { 1855 var style = el.getAttribute('style'), 1856 whitelistedProps = root.CP_Customizer.options('cssAllowedProperties'), 1857 inlineCss = {}, 1858 styleProps = style.split(';'); 1859 1860 for (var i = 0; i < styleProps.length; i++) { 1861 var propParts = styleProps[i].split(':'), 1862 prop = (propParts.shift() || "").trim(), 1863 value = (propParts || []).join(':').trim(); 1864 1865 if (prop && value) { 1866 inlineCss[prop] = value; 1867 } 1868 1869 } 1870 1871 var inlineCssText = ""; 1872 1873 for (var prop in inlineCss) { 1874 inlineCssText += prop + ': ' + inlineCss[prop] + '; '; 1875 } 1876 1877 if (inlineCssText.trim()) { 1878 el.setAttribute('style', inlineCssText.trim()); 1879 } else { 1880 el.removeAttribute('style'); 1881 } 1882 1883 el.removeAttribute('data-mce-style'); 1884 1885 }); 1886 1887 1888 $currentNodes[0].querySelectorAll('[data-content-shortcode]').forEach(function (el) { 1889 el.innerHTML = '[' + CP_Customizer.utils.phpTrim(el.getAttribute('data-content-shortcode')) + ']'; 1890 }); 1891 1892 1893 $currentNodes[0].querySelectorAll('[data-attr-shortcode]').forEach(function (el) { 1894 var attr = el.getAttribute('data-attr-shortcode'); 1895 var parts = attr.split(','); 1896 1897 for (var i = 0; i < parts.length; i++) { 1898 var part = parts[i].trim(); 1899 part = part.split(':'); 1900 el.setAttribute(part[0].trim(), '[' + part[1].trim() + ']'); 1901 } 1902 }); 1903 1904 1905 this.cleanNode($currentNodes); 1906 1907 CP_Customizer.hooks.doAction('clean_nodes', $currentNodes); 1908 1909 $currentNodes[0].querySelectorAll('*').forEach(function (el) { 1910 var attributes = el.attributes; 1911 for (var i = 0; i < attributes.length; i++) { 1912 var attrName = attributes.item(i).name; 1913 if (attrName.match(/scrollreveal/)) { 1914 el.removeAttribute(attrName); 1915 } 1916 } 1917 }); 1918 1919 $currentNodes.find('*').not('[data-cpid]').remove(); 1920 1921 // $currentNodes.find('*').not('[data-cpid]').each(function () { 1922 // var $el = $(this); 1923 1924 // if ($el.attr('data-cp-remove-this')) { 1925 // $el.remove(); 1926 // } 1927 1928 // if (this.previousSibling && this.previousSibling.nodeType === 8) { 1929 // var commentText = this.previousSibling.textContent, 1930 // shortcode = "", 1931 // startComment = ""; 1932 1933 // this.previousSibling.parentNode.removeChild(this.previousSibling); 1934 // if (commentText.match(/cp-shortcode:(.*?):(.*)/)) { 1935 // shortcode = commentText.match(/cp-shortcode:(.*?):(.*)/).pop(); 1936 // startComment = commentText; 1937 // } 1938 1939 // var nextSibling = this.nextSibling; 1940 1941 // while (nextSibling) { 1942 // if (nextSibling.nodeType === 8) { 1943 // var commentText = nextSibling.textContent; 1944 1945 // if (commentText.trim() === startComment.trim()) { 1946 // nextSibling.parentNode.removeChild(nextSibling); 1947 // break; 1948 // } 1949 // } 1950 1951 // $(nextSibling).attr('data-cp-remove-this', '1'); 1952 // nextSibling = nextSibling.nextSibling; 1953 // } 1954 1955 // this.outerHTML = shortcode; 1956 // } else { 1957 // $el.remove(); 1958 // } 1959 // }); 1960 1961 $currentNodes.find('br').each(function () { 1962 if (!this.nextSibling) { 1963 $(this).remove(); 1964 } 1965 }); 1966 1967 CP_Customizer.hooks.applyFilters('get_content', $currentNodes); 1968 1969 //gutenberg 1970 this.decorateSectionsForGutenberg($currentNodes.find('[data-id][data-export-id]')); 1971 return $currentNodes.html().replace(/data-cpid="[^"]+"/gi, ''); ; 1972 }, 1973 1974 __cleanNode: function (el) { 1975 el.removeAttribute('data-content-editable'); 1976 el.removeAttribute('data-content-code-editable'); 1977 el.removeAttribute('data-container-editable'); 1978 el.removeAttribute('data-non-editable'); 1979 el.removeAttribute('contenteditable'); 1980 el.removeAttribute('spellcheck'); 1981 1982 el.classList.remove('ui-sortable'); 1983 el.classList.remove('ui-sortable-disabled'); 1984 el.classList.remove('ui-sortable-handle'); 1985 el.classList.remove('customize-unpreviewable'); 1986 1987 var elClass = el.getAttribute('class'); 1988 if (elClass) { 1989 // remove the tinymce (mce-*) classes; 1990 elClass = elClass.replace(/mce\-[a-z\-]+/ig, "").trim(); 1991 1992 // remove multiple spaces in class names 1993 elClass = elClass.replace(/\s\s+/g, ' '); 1994 1995 el.setAttribute('class', elClass); 1996 } 1997 1998 if (el.id && el.id.indexOf('mce_') === 0) { 1999 el.removeAttribute('id'); 2000 } 2001 2002 // preview styles 2003 el.removeAttribute('data-preview-empty'); 2004 2005 // clean node url 2006 2007 if (el.getAttribute('href')) { 2008 var href = CP_Customizer.preview.cleanURL(el.getAttribute('href')); 2009 el.setAttribute('href', href) 2010 } 2011 }, 2012 2013 2014 getNodeClasses: function (node) { 2015 var $clone = $(node).clone(); 2016 this.__cleanNode($clone[0]); 2017 return Array.from($clone[0].classList); 2018 }, 2019 2020 cleanNode: function ($node) { 2021 2022 $node[0].querySelectorAll('[data-content-editable], [data-content-code-editable], [data-container-editable], [data-non-editable]').forEach(function (el) { 2023 root.CP_Customizer.preview.__cleanNode(el); 2024 }); 2025 2026 $node[0].querySelectorAll('.ui-sortable,.ui-sortable-disabled,.ui-sortable-handle').forEach(function (el) { 2027 root.CP_Customizer.preview.__cleanNode(el); 2028 }); 2029 2030 root.CP_Customizer.preview.__cleanNode($node[0]); 2031 2032 return $node; 2033 }, 2034 2035 cleanURL: function (url) { 2036 2037 var startsWithDoubleSlash = (url.indexOf('//') === 0); 2038 var startsWithSlash = (url.indexOf('/') === 0); 2039 2040 var queryKeys = Object.getOwnPropertyNames(CP_Customizer.wpApi.previewer.query()); 2041 queryKeys = _.unique(queryKeys.concat([ 2042 'customize_theme', 2043 'customize_changeset_uuid', 2044 'customize_messenger_channel', 2045 'customize_autosaved' 2046 ])); 2047 2048 url = CP_Customizer.utils.removeUrlQueryStrings(url, queryKeys); 2049 2050 // clean url 2051 url = CP_Customizer.utils.phpTrim(url, '/').trim() || "#"; 2052 2053 // add // or / depending on how url received 2054 if (startsWithDoubleSlash) { 2055 url = '//' + url; 2056 } else { 2057 if (startsWithSlash) { 2058 url = '/' + url; 2059 } 2060 } 2061 2062 return url; 2063 }, 2064 2065 fixWronglyWrappedTextNodes: function ($node) { 2066 $($node).find('div').each(function () { 2067 var hasOnlyTextInside = Array.from(this).map(function (item) { 2068 return ([8, 3].indexOf(item.nodeType) !== -1) 2069 }).reduce(function (a, b) { 2070 return a && b 2071 }, true); 2072 2073 if (hasOnlyTextInside) { 2074 if (this.innerHTML.trim().length) { 2075 this.outerHTML = this.innerHTML + '<br/>'; 2076 } else { 2077 $(this).remove(); 2078 } 2079 } 2080 }); 2081 }, 2082 2083 markNode: function ($node, prefix) { 2084 2085 CP_Customizer.preview.pauseObserver(); 2086 prefix = prefix || 'new_cp_node_'; 2087 2088 $($node).find("*").addBack().each(function () { 2089 $(this).attr('data-cpid', _.uniqueId(prefix)); 2090 }); 2091 2092 CP_Customizer.preview.restartObserver(); 2093 }, 2094 2095 insertNode: function ($node, $parent, index) { 2096 2097 CP_Customizer.preview.silentCall(function () { 2098 index = (index !== undefined) ? index : $parent.children().length; 2099 jQuery($node).insertAt(index, $parent); 2100 2101 this.decorateElements($node); 2102 this.markNode($node); 2103 2104 root.CP_Customizer.updateState(); 2105 2106 $parent.removeAttr('data-preview-empty'); 2107 2108 CP_Customizer.hooks.doAction('after_node_insert', $node); 2109 }); 2110 }, 2111 2112 replaceNode: function ($node, $newNode) { 2113 2114 CP_Customizer.preview.silentCall(function () { 2115 jQuery($node).replaceWith($newNode); 2116 2117 this.decorateElements($newNode); 2118 this.markNode($newNode); 2119 2120 root.CP_Customizer.updateState(); 2121 2122 }); 2123 }, 2124 2125 hideNode: function ($node) { 2126 $node.attr('data-reiki-hidden', 'true'); 2127 2128 var $parent = $node.parent(); 2129 if ($parent.children(':visible').length === 0) { 2130 $parent.attr('data-preview-empty', 1); 2131 } else { 2132 $parent.removeAttr('data-preview-empty'); 2133 } 2134 }, 2135 2136 showNode: function ($node) { 2137 $node.removeAttr('data-reiki-hidden'); 2138 2139 var $parent = $node.parent(); 2140 if ($parent.children(':visible').length === 0) { 2141 $parent.attr('data-preview-empty', 1); 2142 } else { 2143 $parent.removeAttr('data-preview-empty'); 2144 } 2145 }, 2146 2147 isNodeVisible: function ($node) { 2148 return !($node.is('[data-reiki-hidden]')); 2149 }, 2150 2151 removeNode: function ($node, skipUpdate) { 2152 CP_Customizer.preview.pauseObserver(); 2153 var $parent = $node.parent(); 2154 $node.remove(); 2155 2156 if (!skipUpdate) { 2157 root.CP_Customizer.updateState(); 2158 } 2159 2160 if ($parent.children().length === 0) { 2161 $parent.attr('data-preview-empty', 1); 2162 } else { 2163 $parent.removeAttr('data-preview-empty'); 2164 } 2165 2166 _.delay(function () { 2167 root.CP_Customizer.overlays.hideMovableOverlays(); 2168 var addOverlay = root.CP_Customizer.overlays.addOverlay(); 2169 root.CP_Customizer.overlays.updateOverlay(addOverlay, addOverlay.data().node, false, true); 2170 }, 10); 2171 2172 CP_Customizer.preview.restartObserver(); 2173 }, 2174 2175 2176 insertContentSection: function (newRow, index) { 2177 index = _.isNumber(index) ? index : undefined; 2178 2179 if (_.isUndefined(index) && this.getRootNode().children('[data-id][data-label]').length) { 2180 index = this.getRootNode().children('[data-id][data-label]').last().index() + 1; 2181 } 2182 2183 this.insertNode(newRow, this.getRootNode(), index); 2184 //this.decorateSectionsForGutenberg(newRow); 2185 this.decorateElements(newRow); 2186 2187 2188 function colorize(row) { 2189 var hasColor = (tinycolor(row.css('background-color')).getAlpha() !== 0); 2190 2191 if (!hasColor && !row.is('[data-bg="transparent"]')) { 2192 var prevSection = row.prev('[data-id][data-label]'); 2193 2194 if (!prevSection.length) { 2195 row.css('background-color', '#ffffff'); 2196 return; 2197 } 2198 2199 var isPrevTransparent = (tinycolor(prevSection.css('background-color')).getAlpha() === 0); 2200 var isPrevWhite = (tinycolor(prevSection.css('background-color')).toHex().toUpperCase() === "FFFFFF" || tinycolor(prevSection.css('background-color')).toHex().toUpperCase() === "FFF"); 2201 2202 if (isPrevTransparent || isPrevWhite) { 2203 row.css('background-color', '#F5FAFD'); 2204 } else { 2205 row.css('background-color', '#ffffff'); 2206 } 2207 } 2208 } 2209 2210 colorize(newRow); 2211 2212 2213 CP_Customizer.renderNodeShortcodes(newRow); 2214 // CP_Customizer.hooks.doAction('after_node_insert', newRow); 2215 this.jQuery('html, body').animate({ 2216 'scrollTop': newRow.offset().top 2217 }); 2218 2219 var exports = CP_Customizer.getSectionExports(newRow.attr('data-export-id')); 2220 if (exports.afterInsert && _.isFunction(exports.afterInsert)) { 2221 CP_Customizer.one(CP_Customizer.events.STATE_UPDATED, function () { 2222 exports.afterInsert(newRow); 2223 }); 2224 } 2225 2226 CP_Customizer.updateState(); 2227 2228 }, 2229 2230 editContainerData: function () { 2231 var item = $(this), 2232 fields = [], 2233 elements = item.find('[data-content-code-editable],[data-theme-href],[data-theme],[data-theme-mdi]'); 2234 2235 2236 item.blur(); 2237 2238 if (CP_Customizer.hooks.applyFilters('custom_container_data_handle', false, item)) { 2239 CP_Customizer.hooks.doAction('custom_container_data_handle', item); 2240 CP_Customizer.preview.blur(); 2241 return; 2242 } 2243 2244 if (!elements.length) { 2245 elements = item.filter('.mdi'); 2246 } 2247 2248 CP_Customizer.overlays.updateOverlay(CP_Customizer.overlays.hoverOverlay(), item); 2249 2250 if (item.is('[data-content-code-editable]') || item.is('[data-bg="image"]')) { 2251 elements = elements.add(item); 2252 } 2253 2254 elements = elements.filter(function (index, elem) { 2255 var result = true; 2256 elem = $(elem); 2257 2258 for (var i = 0; i < CP_Customizer.__containerDataFilters.length; i++) { 2259 var filter = CP_Customizer.__containerDataFilters[i]; 2260 if (false === filter.call(elem, elem)) { 2261 result = false; 2262 break; 2263 } 2264 } 2265 return result; 2266 2267 }); 2268 2269 elements.each(function (index, elem) { 2270 var result = false, 2271 setter = false, 2272 $elem = $(this); 2273 2274 for (var selector in CP_Customizer.__containerDataHandlers) { 2275 if ($elem.is(selector)) { 2276 result = CP_Customizer.__containerDataHandlers[selector].getter.call($elem, $elem); 2277 setter = CP_Customizer.__containerDataHandlers[selector].setter; 2278 break; 2279 } 2280 } 2281 2282 result = root.CP_Customizer.hooks.applyFilters('container_data_element', result, $elem); 2283 if (result !== false) { 2284 if (!_.isArray(result)) { 2285 result = [result]; 2286 } 2287 2288 for (var i = 0; i < result.length; i++) { 2289 result[i].id = 'item_no_' + index + '_' + i; 2290 result[i].setter = setter; 2291 result[i].node = $elem; 2292 } 2293 2294 fields = fields.concat(result); 2295 } 2296 2297 }); 2298 2299 var content = ''; 2300 for (var i = 0; i < fields.length; i++) { 2301 var field = fields[i], 2302 type = field.type || 'text'; 2303 2304 var $fieldContent = $(CP_Customizer.jsTPL[type] ? CP_Customizer.jsTPL[type](field) : ''); 2305 2306 if (field.classes) { 2307 $fieldContent.addClass(field.classes); 2308 } 2309 2310 if (field.ready && _.isFunction(field.ready)) { 2311 field.ready($fieldContent); 2312 } 2313 2314 $fieldContent.addClass(type); 2315 2316 content += $('<div />').append($fieldContent).html(); 2317 } 2318 2319 var popupContainer = $('#cp-container-editor'); 2320 2321 2322 function setContent() { 2323 for (var i = 0; i < fields.length; i++) { 2324 var field = fields[i], 2325 value = {}, 2326 node = field.node 2327 if (field.getValue) { 2328 value = field.getValue($('[id="' + field.id + '"]')); 2329 } else { 2330 var _values = $('[id^="' + field.id + '"]').filter('input,textarea,select').map(function (index, elem) { 2331 return { 2332 key: $(this).attr('id').replace(field.id + "__", ''), 2333 value: $(this).is('[type=checkbox]') ? this.checked : $(this).val() 2334 }; 2335 }).toArray(); 2336 2337 _(_values).each(function (v) { 2338 value[v.key] = v.value; 2339 }); 2340 2341 if (_values.length === 1 && value.hasOwnProperty(field.id)) { 2342 value = value[field.id]; 2343 } 2344 } 2345 2346 if (field.setter) { 2347 field.setter.call(node, node, value, field.type, field); 2348 root.CP_Customizer.hooks.doAction('container_data_element_setter', node, value, field); 2349 } 2350 } 2351 2352 if (node.is('[data-theme]')) { 2353 CP_Customizer.preview.jQuery(node).data('was-changed', true); 2354 } 2355 2356 2357 if (node.closest('[data-theme]').length) { 2358 CP_Customizer.preview.jQuery(node.closest('[data-theme]')).data('was-changed', true); 2359 } 2360 2361 2362 CP_Customizer.closePopUps(); 2363 CP_Customizer.updateState(); 2364 } 2365 2366 2367 setContent = CP_Customizer.preview.addSilentExecution(setContent); 2368 2369 popupContainer.find('[id="cp-item-ok"]').off().click(setContent); 2370 2371 popupContainer.find('[id="cp-item-cancel"]').off().click(function () { 2372 CP_Customizer.closePopUps(); 2373 }); 2374 2375 popupContainer.find('#cp-items').html(content); 2376 2377 CP_Customizer.popUp(root.CP_Customizer.translateCompanionString('Manage Content'), "cp-container-editor", { 2378 class: "data-edit-popup" 2379 }); 2380 2381 CP_Customizer.preview.blur(true); 2382 2383 }, 2384 2385 __dataContainers: ['[data-container-editable]', '[data-type=group]'], 2386 2387 addDataContainerSelector: function (selector) { 2388 this.__dataContainers.push(selector); 2389 }, 2390 2391 registerContainerDataHandler: function (selector, handler) { 2392 CP_Customizer.preview.addDataContainerSelector(selector); 2393 var context = { 2394 selector: selector, 2395 handler: handler 2396 }; 2397 2398 CP_Customizer.hooks.addFilter('custom_container_data_handle', function (value, $item) { 2399 if ($item.is(this.selector)) { 2400 value = true; 2401 } 2402 return value; 2403 2404 }.bind(context)); 2405 2406 CP_Customizer.hooks.addAction('custom_container_data_handle', function ($item) { 2407 if ($item.is(this.selector)) { 2408 this.handler($item); 2409 } 2410 }.bind(context)); 2411 }, 2412 2413 2414 getContainersSelector: function (addSelectors) { 2415 var result = _.clone(this.__dataContainers); 2416 2417 if (_.isArray(addSelectors)) { 2418 result = result.concat(addSelectors); 2419 } else { 2420 if (_.isString(addSelectors)) { 2421 result.push(addSelectors); 2422 } 2423 } 2424 2425 return result.join(','); 2426 }, 2427 2428 2429 addContentBinds: function () { 2430 var $ = this.jQuery(), 2431 document = this.frame().document, 2432 window = this.frame(); 2433 2434 $(document).on('mouseover.hoveroverlay', this.getContainersSelector('[data-widgets-area],[data-bg="image"]'), _.debounce(function () { 2435 if (this.hasAttribute("data-non-editable")) return false; 2436 var node = $(this); 2437 var hoverOverlay = root.CP_Customizer.overlays.hoverOverlay(); 2438 2439 if (node.closest('[data-type=group]').length) { 2440 node = $(this).closest('[data-type=group]'); 2441 } 2442 2443 if (node.closest('[data-content-shortcode]').length) { 2444 node = node.closest('[data-content-shortcode]'); 2445 } 2446 2447 root.CP_Customizer.overlays.assignNode(hoverOverlay, node, true); 2448 hoverOverlay.show(); 2449 2450 var structureAllowsRemoving = (node.parents('[data-type=row]').length || node.parents('[data-type=column]').length)/* && node.siblings().length*/; 2451 var isFixed = (node.is('[data-fixed]') || node.parents('[data-fixed]').length); 2452 2453 isFixed = CP_Customizer.hooks.applyFilters('is_fixed_element', isFixed, node); 2454 2455 if (structureAllowsRemoving && !isFixed && node.is(root.CP_Customizer.CONTENT_ELEMENTS)) { 2456 hoverOverlay.find('.remove').show(); 2457 } else { 2458 hoverOverlay.find('.remove').hide(); 2459 } 2460 }, 1)); 2461 2462 2463 $(document).on('mouseover.hoveroverlay', '[data-content-editable], .page-content i.mdi, body [data-content-item-container="true"]', _.debounce(function () { 2464 if (this.hasAttribute("data-non-editable")) return false; 2465 var node = $(this); 2466 2467 if (node.parent().is('[data-content-item-container="true"]')) { 2468 return; 2469 } 2470 2471 var hoverOverlay = root.CP_Customizer.overlays.hoverOverlay(); 2472 2473 if (node.closest('[data-type=group]').length) { 2474 node = $(this).closest('[data-type=group]'); 2475 } 2476 2477 root.CP_Customizer.overlays.assignNode(hoverOverlay, node); 2478 hoverOverlay.show(); 2479 2480 if (CP_Customizer.isShortcodeContent(node)) { 2481 hoverOverlay.find('.remove').hide(); 2482 2483 if (!CP_Customizer.isOnCanvasMod(node)) { 2484 hoverOverlay.hide(); 2485 } 2486 } else { 2487 var inRow = node.parents('[data-type=row]').length || node.parents('[data-type=column]').length; 2488 if (inRow && !node.is('[data-fixed]') && !node.closest('[data-fixed]').length) { 2489 hoverOverlay.find('.remove').show(); 2490 } else { 2491 hoverOverlay.find('.remove').hide(); 2492 } 2493 } 2494 2495 2496 }, 1)); 2497 2498 $(document).on('mouseover.hoveroverlay', '.page-content [data-content-shortcode]', function () { 2499 2500 if (CP_Customizer.isShortcodeEditable($(this))) { 2501 var overlay = root.CP_Customizer.overlays.hoverOverlay(); 2502 root.CP_Customizer.overlays.assignNode(overlay, $(this)); 2503 overlay.show(); 2504 } 2505 }); 2506 2507 2508 $(document).on('mouseover', root.CP_Customizer.preview.getPageContainerSelector() + ' > div', function () { 2509 root.CP_Customizer.trigger('content.section.hovered', [$(this)]); 2510 }); 2511 2512 2513 $(document).on('mouseover', '[data-type="richtext"]', function () { 2514 var hoverOverlay = root.CP_Customizer.overlays.hoverOverlay(); 2515 root.CP_Customizer.overlays.assignNode(hoverOverlay, $(this), true); 2516 2517 }); 2518 2519 2520 $(document).on('mouseover.addoverlay', '.page-content [data-type="row"] > div, [data-theme] [data-type="row"] > div, .page-content [data-type="column"]', function () { 2521 2522 if ($(this).closest("[data-type=\"row\"]").is('[data-fixed]')) { 2523 return; 2524 } 2525 2526 if ($(this).find('[data-type=column]').length) { 2527 return; 2528 } 2529 2530 if ($(this).closest('[data-content-shortcode]').length) { 2531 return; 2532 } 2533 2534 var addOverlay = root.CP_Customizer.overlays.addOverlay(); 2535 root.CP_Customizer.overlays.assignNode(addOverlay, $(this)); 2536 addOverlay.show(); 2537 }); 2538 2539 2540 $(document).on('mouseover.rowitemoverlay', '.page-content [data-type="row"] > div, [data-theme] [data-type="row"] > div, .page-content [data-type="row"] > div, [data-theme] [data-type="row"] > div * ', function () { 2541 var node = $(this); 2542 2543 if (!node.parent().is('[data-type="row"]')) { 2544 var parents = node.parentsUntil('[data-type="row"]'); 2545 node = parents.last(); 2546 } 2547 2548 if (CP_Customizer.isShortcodeContent(node)) { 2549 return; 2550 } 2551 2552 2553 var itemOverlay = root.CP_Customizer.overlays.rowItemHoverOverlay(); 2554 root.CP_Customizer.overlays.assignNode(itemOverlay, node); 2555 itemOverlay.show(); 2556 } 2557 ); 2558 2559 $(window).on('scroll', root.CP_Customizer.overlays.updateAllOverlays); 2560 $(window).on('resize', _(root.CP_Customizer.overlays.updateAllOverlays).debounce(50)); 2561 2562 $(document).on('click', this.getContainersSelector(), root.CP_Customizer.preview.editContainerData); 2563 2564 $(document).on('click', 'body [data-content-editable]', function () { 2565 $(this).focus(); 2566 }); 2567 2568 $(document).on('click', 'img[data-content-editable], [data-bg="image"]', function () { 2569 2570 2571 var self = $(this), 2572 type = "image", 2573 data = {}; 2574 2575 if (self.is(CP_Customizer.preview.getContainersSelector())) { 2576 return; 2577 } 2578 2579 var section = CP_Customizer.preview.getNodeSection(self); 2580 var sectionExports = CP_Customizer.getSectionExports(section); 2581 2582 var flexible = _.isUndefined(sectionExports.maintainCropPropotion) ? true : sectionExports.maintainCropPropotion; 2583 2584 if (self.is('[data-size-flexible=false]')) { 2585 flexible = false; 2586 } 2587 2588 if (self.attr('data-size')) { 2589 var size = self.attr('data-size').split('x'); 2590 type = "cropable"; 2591 data = { 2592 width: size[0], 2593 height: size[1] ? size[1] : size[0], 2594 flexible: flexible 2595 }; 2596 } else { 2597 data = { 2598 width: self.width(), 2599 height: self.height(), 2600 flexible: true 2601 }; 2602 } 2603 2604 root.CP_Customizer.openMediaBrowser(type, setterCB, data); 2605 2606 function setterCB(src) { 2607 if (!src) { 2608 return; 2609 } 2610 if (self.is('img')) { 2611 self.attr('src', src[0].url); 2612 2613 // remove attributes added by other plugins like JetPack 2614 self.removeAttr('srcset'); 2615 self.removeAttr('src-orig'); 2616 self.removeAttr('width'); 2617 self.removeAttr('height'); 2618 2619 } else { 2620 self.css('background-image', 'url(' + src[0].url + ')'); 2621 } 2622 2623 root.CP_Customizer.markSave(); 2624 } 2625 }); 2626 2627 $(document).on('click', 'i.mdi', function () { 2628 if (CP_Customizer.hooks.applyFilters('can_edit_icon', true, $(this))) { 2629 CP_Customizer.preview.editContainerData.apply(this); 2630 } 2631 }); 2632 2633 var cachedValue = ""; 2634 $(document).on('mousedown', '.page-content [data-content-editable]', function (event) { 2635 cachedValue = $(this).text(); 2636 }); 2637 2638 2639 $(document).on('mouseup', '.page-content [data-content-editable]', function () { 2640 if ($(this).text() !== cachedValue) { 2641 root.CP_Customizer.markSave(); 2642 cachedValue = $(this).text(); 2643 } else { 2644 cachedValue = ""; 2645 } 2646 }); 2647 2648 //Check for IE ('Trident') 2649 var contentEditableInputEvent = /Trident/.test(navigator.userAgent) ? 'textinput' : 'input'; 2650 2651 2652 $(document).on(contentEditableInputEvent, 'body [data-content-editable]', function () { 2653 if ($(this).is('[data-theme]')) { 2654 $(this).data('was-changed', true); 2655 return; 2656 } 2657 2658 root.CP_Customizer.overlays.updateOverlay(root.CP_Customizer.overlays.hoverOverlay(), $(this), false, true); 2659 root.CP_Customizer.markSave(); 2660 }); 2661 2662 2663 $(document).on('blur', 'body [data-theme]', function () { 2664 if ($(this).data('was-changed')) { 2665 root.CP_Customizer.markSave(); 2666 } 2667 }); 2668 2669 var elementsSpecificSelector = CP_Customizer.TEXT_ELEMENTS.split(',').map(function (item) { 2670 var result = CP_Customizer.preview.getPageContainerSelector() + ' ' + item; 2671 2672 result += ", [data-theme] " + item; 2673 return result; 2674 }); 2675 2676 elementsSpecificSelector.push('[data-theme]'); 2677 2678 elementsSpecificSelector = elementsSpecificSelector.join(','); 2679 2680 var elementsOnFocusLeave = _.debounce(function () { 2681 var $this = $(this); 2682 root.CP_Customizer.preview.markNode($this); 2683 2684 if ($this.is(root.CP_Customizer.CONTENT_ELEMENTS) && $this.html().trim().length === 0) { 2685 $this.attr('data-preview-empty', 1); 2686 } 2687 }, 10); 2688 2689 $(document).on('blur focusout', elementsSpecificSelector, elementsOnFocusLeave); 2690 2691 $(document).on('focus', elementsSpecificSelector, function (event) { 2692 var $this = $(this); 2693 $this.removeAttr('data-preview-empty'); 2694 2695 if ($this.is('.mdi')) { 2696 event.preventDefault(); 2697 event.stopPropagation(); 2698 return false; 2699 } 2700 }); 2701 2702 2703 $(document).on('keydown.cp', '[contenteditable=true]', function (event) { 2704 2705 var editedNode = this; 2706 2707 _.delay(function () { 2708 root.CP_Customizer.overlays.updateOverlay(root.CP_Customizer.overlays.hoverOverlay(), $(editedNode), false, true); 2709 $(editedNode).removeAttr('data-preview-empty'); 2710 }, 20); 2711 2712 }); 2713 2714 $(document).on('keypress.cp', '[contenteditable=true]', function (event) { 2715 2716 if (event.which !== 13) 2717 return true; 2718 2719 var document = CP_Customizer.preview.frame().document; 2720 2721 var docFragment = document.createDocumentFragment(); 2722 //add a new line 2723 var newEle = document.createTextNode('\n'); 2724 docFragment.appendChild(newEle); 2725 //add the br, or p, or something else 2726 newEle = document.createElement('br'); 2727 docFragment.appendChild(newEle); 2728 2729 var caretPosition = root.CP_Customizer.preview.getSelectionTextInfo(this); 2730 2731 //make the br replace selection 2732 var range = window.getSelection().getRangeAt(0); 2733 range.deleteContents(); 2734 range.insertNode(docFragment); 2735 //create a new range 2736 range = document.createRange(); 2737 range.setStartAfter(newEle); 2738 range.collapse(true); 2739 //make the cursor there 2740 var sel = window.getSelection(); 2741 sel.removeAllRanges(); 2742 sel.addRange(range); 2743 2744 event.preventDefault(); 2745 2746 $(this).trim(); 2747 2748 root.CP_Customizer.overlays.updateOverlay(root.CP_Customizer.overlays.hoverOverlay(), $(this), false, true); 2749 2750 return false; 2751 2752 }); 2753 2754 $(document).on('blur.cpmarksave', '[contenteditable=true]', _.debounce(function (event) { 2755 2756 if (!$(this).data('cpFocused')) { 2757 return; 2758 } 2759 2760 $(this).data('cpFocused', false); 2761 2762 root.CP_Customizer.preview.markNode($(this)); 2763 root.CP_Customizer.markSave(); 2764 }, 800)); 2765 2766 $(window).bind('keydown', function (event) { 2767 if (event.ctrlKey || event.metaKey) { 2768 var key = String.fromCharCode(event.which).toLowerCase(); 2769 if (key === "s") { 2770 event.preventDefault(); 2771 event.stopPropagation(); 2772 root.CP_Customizer.save(); 2773 } 2774 } 2775 }); 2776 2777 2778 }, 2779 // http://stackoverflow.com/questions/1125292/how-to-move-cursor-to-end-of-contenteditable-entity 2780 placeCursorAtEnd: function (contentEditableElement) { 2781 try { 2782 var range, selection, 2783 document = this.frame().document, 2784 window = this.frame(); 2785 if (document.createRange) //Firefox, Chrome, Opera, Safari, IE 9+ 2786 { 2787 range = document.createRange(); //Create a range (a range is a like the selection but invisible) 2788 range.selectNodeContents(contentEditableElement); //Select the entire contents of the element with the range 2789 range.collapse(false); //collapse the range to the end point. false means collapse to end rather than the start 2790 selection = window.getSelection(); //get the selection object (allows you to change selection) 2791 selection.removeAllRanges(); //remove any selections already made 2792 selection.addRange(range); //make the range you have just created the visible selection 2793 } else if (document.selection) //IE 8 and lower 2794 { 2795 range = document.body.createTextRange(); //Create a range (a range is a like the selection but invisible) 2796 range.moveToElementText(contentEditableElement); //Select the entire contents of the element with the range 2797 range.collapse(false); //collapse the range to the end point. false means collapse to end rather than the start 2798 range.select(); //Select the range (make it the visible selection 2799 } 2800 } catch (e) { 2801 2802 } 2803 }, 2804 2805 2806 decorateMods: function ($container) { 2807 2808 // decorate default mods 2809 CP_Customizer.preview.pauseObserver(); 2810 $container = $container ? this.jQuery($container) : this.find('body'); 2811 var defaultMods = root.CP_Customizer.preview.getThemeMods($container); 2812 var preview = this; 2813 defaultMods.each(function () { 2814 var $el = $(this); 2815 if ($el.is('[data-theme]')) { 2816 preview.markNode($el); 2817 $el.find('[data-type="row"] > div').each(preview.enableSortable); 2818 } 2819 }); 2820 2821 if (root.CP_Customizer.options().mods) { 2822 for (var selector in root.CP_Customizer.options().mods) { 2823 var $el = this.find(selector); 2824 var modData = root.CP_Customizer.options().mods[selector]; 2825 if (modData.type) { 2826 $el.attr(modData.type, modData.mod); 2827 2828 if (modData.type === "data-theme") { 2829 preview.markNode($el); 2830 $el.find('[data-type="row"] > div').each(this.enableSortable); 2831 } 2832 } 2833 2834 if (modData.atts) { 2835 for (var attr in modData.atts) { 2836 $el.attr('data-theme-' + attr, modData.atts[attr]); 2837 } 2838 } 2839 2840 } 2841 } 2842 2843 CP_Customizer.preview.restartObserver(); 2844 }, 2845 2846 //scan siblings and parent siblings until a comment node is found 2847 getGutenbergBlockCommentStart:function (node) 2848 { 2849 if (!node || (node && node.tagName == "body")) return false; 2850 if (node.nodeType == Node.COMMENT_NODE) return node; 2851 2852 var previousSibling = node.previousSibling; 2853 var maxDepth = 10; 2854 while (previousSibling && 2855 previousSibling.nodeType != Node.COMMENT_NODE && 2856 maxDepth-- > 0) 2857 { 2858 previousSibling = previousSibling.previousSibling; 2859 } 2860 2861 if (!previousSibling || previousSibling.nodeType != Node.COMMENT_NODE) 2862 previousSibling = this.getGutenbergBlockCommentStart(node.parentNode); 2863 2864 if (previousSibling.nodeType == Node.COMMENT_NODE) 2865 return previousSibling; 2866 2867 return false; 2868 }, 2869 2870 getGutenbergBlockCommentEnd:function (node) 2871 { 2872 if (!node || (node && node.tagName == "body")) return false; 2873 if (node.nodeType == Node.COMMENT_NODE) return node; 2874 2875 var nextSibling = node.nextSibling; 2876 var maxDepth = 10; 2877 while (nextSibling && 2878 nextSibling.nodeType != Node.COMMENT_NODE && 2879 maxDepth-- > 0) 2880 { 2881 nextSibling = nextSibling.nextSibling; 2882 } 2883 2884 if (!nextSibling || nextSibling.nodeType != Node.COMMENT_NODE) 2885 nextSibling = this.getGutenbergBlockCommentEnd(node.parentNode); 2886 2887 if (nextSibling.nodeType == Node.COMMENT_NODE) 2888 return nextSibling; 2889 2890 return false; 2891 }, 2892 2893 disableGutenbergBlocks: function (contentEditableElements) 2894 { 2895 var self = this; 2896 console.log(self); 2897 var dataIdCounter = 1; 2898 contentEditableElements.each(function (i, node) { 2899 2900 //add data-non-editable also for node children for gutenberg figure > img case 2901 function setNonEditableNodes(node, parent) 2902 { 2903 function setNode(node, parent) 2904 { 2905 $(node).removeAttr("data-content-editable data-container-editable data-content-code-editable contenteditable srcset sizes data-category data-label data-export-id"); 2906 if (parent === true) 2907 { 2908 $(node).attr("data-non-editable", true); 2909 } 2910 } 2911 2912 2913 setNode(node, parent); 2914 for (var i = 0; i < node.childNodes.length; i++) { 2915 var child = node.childNodes[i]; 2916 setNonEditableNodes(child); 2917 //delete srcset andsizes attributes so that Gutenberg does not say invalid content 2918 setNode(node); 2919 } 2920 } 2921 2922 2923 2924 //check previous sibling nodes until reaching comment node to skip eventual text nodes 2925 function nextNonTextNode(node) 2926 { 2927 var nextSibling = node; 2928 var maxDepth = 10; 2929 while (nextSibling && 2930 (nextSibling.nodeType == Node.COMMENT_NODE || 2931 nextSibling.nodeType == Node.TEXT_NODE) && 2932 maxDepth-- > 0) 2933 { 2934 nextSibling = nextSibling.nextSibling; 2935 } 2936 2937 return nextSibling; 2938 } 2939 2940 var commentNode = self.getGutenbergBlockCommentStart(node); 2941 var sectionNode; 2942 2943 if ((commentNode && commentNode.nodeType == Node.COMMENT_NODE) && //check if section has wp:comment 2944 commentNode.textContent.indexOf("wp:") != -1 && //check if gutenberg block 2945 commentNode.textContent.indexOf("wp:extendstudio/materialis") == -1 && //check if not materialis block 2946 commentNode.textContent.indexOf("wp:extendstudio/mesmerize") == -1) //check if not mesmerize block 2947 { 2948 //set gutenberg block as non editable 2949 sectionNode = nextNonTextNode(commentNode); 2950 setNonEditableNodes(sectionNode, true); 2951 } 2952 }); 2953 }, 2954 2955 decorateElements: function ($container) { 2956 2957 2958 CP_Customizer.preview.pauseObserver(); 2959 2960 var $ = root.CP_Customizer.preview.jQuery(), 2961 self = this; 2962 2963 var elementsContainers = root.CP_Customizer.hooks.applyFilters('decorable_elements_containers', [root.CP_Customizer.preview.getPageContainerSelector(), '[data-dynamic-mod-container]']); 2964 $container = $container ? $($container) : root.CP_Customizer.preview.find(elementsContainers.join(',')); 2965 2966 2967 $(function () { 2968 var $toDecorate = $(""); 2969 $toDecorate = $toDecorate.add($container); 2970 // $toDecorate = $toDecorate.add($('[data-theme]')); 2971 CP_Customizer.overlays.addFixedOverlays($toDecorate); 2972 }); 2973 2974 2975 $container.find('a').unbind('click').click(function (event) { 2976 event.preventDefault(); 2977 event.stopImmediatePropagation(); 2978 event.stopPropagation(); 2979 2980 if ($(this).is('[data-container-editable]') || $(this).is('[data-type=group]')) { 2981 self.editContainerData.apply(this); 2982 } 2983 2984 return false; 2985 }); 2986 var elements = $container.find(root.CP_Customizer.CONTENT_ELEMENTS).filter(function () { 2987 return root.CP_Customizer.preview.data().maintainable; 2988 }); 2989 2990 if ($container.is(root.CP_Customizer.CONTENT_ELEMENTS)) { 2991 if (elements.length) { 2992 elements.add($container); 2993 } else { 2994 elements = $container; 2995 } 2996 } 2997 2998 2999 elements = elements.filter(function (item) { 3000 if ($(this).closest('[data-content-shortcode]').length) { 3001 return false; 3002 } 3003 return true; 3004 }); 3005 elements = elements.add(root.CP_Customizer.preview.getThemeMods($container).filter(root.CP_Customizer.CONTENT_ELEMENTS)); 3006 elements.filter('a').each(function () { 3007 var $el = $(this); 3008 3009 if ($el.closest(root.CP_Customizer.preview.getPageContainerSelector()).length) { 3010 $el.attr('data-container-editable', true); 3011 } 3012 3013 if ($el.is('[data-theme]')) { 3014 $el.attr('data-container-editable', true); 3015 } 3016 3017 }); 3018 elements.filter('ul').attr('data-container-editable', true); 3019 elements = elements.filter(function (item) { 3020 if (this.tagName === "SPAN" && $(this).parents(CP_Customizer.TEXT_ELEMENTS).length) { 3021 return false; 3022 } 3023 3024 if ($(this).parents(root.CP_Customizer.preview.getContainersSelector()).length) { 3025 $(this).attr('data-content-code-editable', true); 3026 return false; 3027 } 3028 3029 if ($(this).is(root.CP_Customizer.preview.getContainersSelector())) { 3030 $(this).attr('data-content-code-editable', true); 3031 return false; 3032 } 3033 3034 return true; 3035 }); 3036 3037 elements.not('i.mdi,a').attr('data-content-editable', true); 3038 elements.not('i.mdi,hr,a').attr('contenteditable', true); 3039 3040 elements.filter('i.mdi').each(function () { 3041 if ($(this).parent().is(root.CP_Customizer.CONTENT_ELEMENTS)) { 3042 return; 3043 } 3044 3045 $(this).attr('data-content-editable', true); 3046 $(this).attr('contenteditable', true); 3047 }); 3048 3049 var contentEditableElements = $container.find('[contenteditable="true"]'); 3050 3051 if ($container.is('[contentededitable=true]')) { 3052 contentEditableElements.add($container); 3053 } 3054 3055 contentEditableElements = contentEditableElements.add(root.CP_Customizer.preview.getThemeMods($container).filter('[contenteditable="true"]')); 3056 3057 3058 var handlePasteEvent = function (e) { 3059 var $ = CP_Customizer.preview.jQuery(); 3060 3061 var text = ''; 3062 var that = $(this); 3063 var document = CP_Customizer.preview.frame().document; 3064 3065 e.preventDefault(); 3066 e.stopPropagation(); 3067 3068 if (e.clipboardData) { 3069 text = e.clipboardData.getData('text/plain'); 3070 } else if (window.clipboardData) { 3071 text = window.clipboardData.getData('Text'); 3072 } else if (e.originalEvent.clipboardData) { 3073 text = $('<div></div>').text(e.originalEvent.clipboardData.getData('text')); 3074 } 3075 3076 var textContainer = $('<div/>').append(text); 3077 3078 CP_Customizer.preview.fixWronglyWrappedTextNodes(textContainer); 3079 3080 text = textContainer[0].innerHTML.replace(/\r\n/g, '<br/>').replace(/\r/g, '<br/>').replace(/\n/g, '<br/>'); 3081 3082 if (document.queryCommandSupported('insertText')) { 3083 document.execCommand('insertHTML', false, text); 3084 return false; 3085 } 3086 else { // IE > 7 3087 that.find('*').each(function () { 3088 $(this).addClass('within'); 3089 }); 3090 3091 setTimeout(function () { 3092 // nochmal alle durchlaufen 3093 that.find('*').each(function () { 3094 // wenn das element keine klasse 'within' hat, dann unwrap 3095 // http://api.jquery.com/unwrap/ 3096 $(this).not('.within').contents().unwrap(); 3097 }); 3098 root.CP_Customizer.preview.markNode(that); 3099 }, 1); 3100 } 3101 root.CP_Customizer.markSave(); 3102 }; 3103 3104 contentEditableElements.filter('*').each(function () { 3105 if (!CP_Customizer.IS_PRO) { 3106 this.addEventListener('paste', handlePasteEvent); 3107 } 3108 }); 3109 3110 $container.find('[data-type="row"] > div, [data-type=column]').each(this.enableSortable); 3111 3112 if ($container.is('[data-type="row"] > div, [data-type=column]')) { 3113 this.enableSortable.call($container); 3114 } 3115 3116 if ($container.closest('.ui-sortable').length) { 3117 try { 3118 $container.closest('.ui-sortable').sortable('refresh'); 3119 $container.closest('.ui-sortable').sortable('disable'); 3120 } catch (e) { 3121 3122 } 3123 } 3124 3125 this.disableGutenbergBlocks($container.find('[contenteditable="true"], [data-content-code-editable="true"], [class^=wp-]')); 3126 root.CP_Customizer.trigger(root.CP_Customizer.events.ELEMENT_DECORATED, [$container]); 3127 CP_Customizer.preview.restartObserver(); 3128 }, 3129 3130 decorateSectionsForGutenberg: function(sections){ 3131 var sections = sections ? sections : CP_Customizer.preview.getSections(); 3132 3133 //adds gutenberg block html comment 3134 sections.each(function (i, node) { 3135 //skip decorate if node already has comment 3136 if (node.previousSibling && 3137 node.previousSibling.nodeType == Node.COMMENT_NODE && 3138 node.previousSibling.textContent.indexOf(" wp:extendstudio/materialis") != -1) 3139 return; 3140 3141 var commentOpen = document.createComment(" wp:extendstudio/materialis "); 3142 var commentClose = document.createComment(" /wp:extendstudio/materialis "); 3143 node.before(commentOpen); 3144 node.after(commentClose); 3145 }); 3146 }, 3147 3148 enableSortable: function () { 3149 var $ = CP_Customizer.preview.jQuery(); 3150 var $this = $(this); 3151 3152 if ($this.find('[data-type=column]').length) { 3153 return; 3154 } 3155 3156 if ($this.parent().is('[data-content-shortcode]')) { 3157 return; 3158 } 3159 3160 3161 if ($this.children().length === 0) { 3162 if ($this.is(root.CP_Customizer.CONTENT_ELEMENTS) && $this.html().trim().length === 0) { 3163 $this.attr('data-preview-empty', 1); 3164 } 3165 } 3166 3167 $this.sortable({ 3168 axis: "y", 3169 start: function (event, ui) { 3170 ui.helper.css({ 3171 'display': 'block', 3172 }); 3173 }, 3174 stop: function (evt, ui) { 3175 $this.sortable('disable'); 3176 $('.node-hover-overlay[is-dragging=true]').removeAttr('is-dragging'); 3177 $(ui.item).data('reikidragging', false); 3178 ui.item.removeAttr("style");//button drag left:0px fix 3179 3180 function refreshOverlay() { 3181 root.CP_Customizer.overlays.assignNode(root.CP_Customizer.overlays.hoverOverlay(), $(ui.item)); 3182 root.CP_Customizer.overlays.updateOverlay(root.CP_Customizer.overlays.hoverOverlay(), $(ui.item)); 3183 } 3184 3185 ui.item.css('display', ''); 3186 ui.item.css('transition', ''); 3187 setTimeout(refreshOverlay, 10); 3188 $('[contenteditable]').attr('contenteditable', true); 3189 root.CP_Customizer.isSorting = false; 3190 root.CP_Customizer.updateState(); 3191 }, 3192 deactivate: function (evt, ui) { 3193 $('.node-hover-overlay[is-dragging=true]').removeAttr('is-dragging'); 3194 }, 3195 cursorAt: { 3196 left: 0, 3197 top: 0 3198 } 3199 3200 }); 3201 $this.sortable('disable'); 3202 }, 3203 3204 showTextElementCUI: function (node) { 3205 CP_Customizer.preview.pauseObserver(); 3206 3207 $(node).off('paste.cp_customizer').on('paste.cp_customizer', function (event) { 3208 var clipboardData = null; 3209 var mimeType = ""; 3210 var window = CP_Customizer.preview.frame(); 3211 var document = window.document; 3212 3213 3214 event.preventDefault(); 3215 // event.stopPropagation(); 3216 // event.stopImmediatePropagation(); 3217 3218 if (event.clipboardData) { 3219 clipboardData = event.clipboardData; 3220 mimeType = 'text/plain'; 3221 } else if (window.clipboardData) { 3222 clipboardData = window.clipboardData; 3223 mimeType = 'Text'; 3224 } else if (event.originalEvent.clipboardData) { 3225 clipboardData = event.originalEvent.clipboardData; 3226 mimeType = 'text'; 3227 } 3228 3229 var text = clipboardData.getData(mimeType); 3230 text = CP_Customizer.utils.wpautop(text.replace(/\n\s*\n/g, '\n')); 3231 var textContainer = $('<div/>').append(text); 3232 3233 CP_Customizer.preview.fixWronglyWrappedTextNodes(textContainer); 3234 3235 text = textContainer[0].innerHTML; 3236 3237 if (document.queryCommandSupported('insertText')) { 3238 document.execCommand('insertHTML', false, text); 3239 return false; 3240 } 3241 else { // IE > 7 3242 that.find('*').each(function () { 3243 $(this).addClass('within'); 3244 }); 3245 3246 setTimeout(function () { 3247 // nochmal alle durchlaufen 3248 that.find('*').each(function () { 3249 // wenn das element keine klasse 'within' hat, dann unwrap 3250 // http://api.jquery.com/unwrap/ 3251 $(this).not('.within').contents().unwrap(); 3252 }); 3253 }, 1); 3254 } 3255 3256 }); 3257 3258 node = $(node)[0]; 3259 3260 var cui = this.getTextElementCUI(); 3261 3262 if (!cui) { 3263 CP_Customizer.logError('TinyMCE Editor not found'); 3264 return; 3265 } 3266 3267 cui.hidden = false; 3268 cui.target = node; 3269 cui.bodyElement = node; 3270 cui.show(); 3271 cui.fire('focusin'); 3272 cui.undoManager.clear(); 3273 cui.theme.panel.getEl().classList.add('cp-tinymce-inline'); 3274 cui.theme.panel.getEl().style.display = "block"; 3275 3276 3277 var docWidth = Math.min(CP_Customizer.preview.frame().innerWidth, CP_Customizer.preview.jQuery('html').width()), 3278 cuiRect = cui.theme.panel.getEl().getBoundingClientRect(), 3279 nodeWidth = CP_Customizer.preview.jQuery(node).width(), 3280 nodeOffsetLeft = CP_Customizer.preview.jQuery(node).offset().left; 3281 3282 3283 var newLeft = (nodeOffsetLeft - (cuiRect.width - nodeWidth) * 0.5); 3284 3285 if (newLeft < 0) { 3286 newLeft = nodeOffsetLeft; 3287 } 3288 3289 if (newLeft + cuiRect.width > docWidth) { 3290 newLeft = nodeOffsetLeft + nodeWidth - cuiRect.width; 3291 3292 } 3293 cui.theme.panel.getEl().style.left = newLeft + 'px'; 3294 3295 }, 3296 3297 hideTextElementCUI: function () { 3298 var cui = this.getTextElementCUI(); 3299 3300 if (!cui) { 3301 CP_Customizer.logError('TinyMCE Editor not found'); 3302 return; 3303 } 3304 3305 3306 if (cui.theme && cui.theme.panel) { 3307 cui.theme.panel.getEl().style.display = "none"; 3308 } 3309 3310 if (cui.getBody()) { 3311 cui.fire('focusout'); 3312 // cui.hide(); 3313 } 3314 }, 3315 3316 getFonts: function () { 3317 3318 var defaultFonts = { 3319 "Arial": "arial,helvetica,sans-serif", 3320 "Arial Black": "arial black,sans-serif", 3321 "Andale Mono": "andale mono,monospace", 3322 // "Book Antiqua": "book antiqua,palatino,serif", 3323 // "Comic Sans MS": "comic sans ms,sans-serif", 3324 // "Courier New": "courier new,courier,monospace", 3325 // "Georgia": "georgia,palatino,serif", 3326 // "Helvetica": "helvetica,arial,sans-serif", 3327 // "Impact": "impact,sans-serif", 3328 // "Symbol": "symbol", 3329 "Tahoma": "tahoma,arial,helvetica,sans-serif", 3330 "Terminal": "terminal,monaco,monospace", 3331 "Times New Roman": "times new roman,times,serif", 3332 // "Trebuchet MS": "trebuchet ms,geneva,sans-serif", 3333 "Verdana": "verdana,geneva,sans-serif" 3334 // "Webdings": "webdings", 3335 // "Wingdings": "wingdings,zapf dingbats" 3336 }; 3337 3338 var googleFonts = {}; 3339 3340 if (root.CP_Customizer.pluginOptions.data.fonts) { 3341 for (var font in root.CP_Customizer.pluginOptions.data.fonts) { 3342 googleFonts[font] = font + ",arial,helvetica,sans-serif"; 3343 } 3344 } 3345 3346 googleFonts = root.CP_Customizer.hooks.applyFilters('tinymce_google_fonts', googleFonts); 3347 3348 var fonts = _.extend(googleFonts, defaultFonts); 3349 3350 fonts.toTinyMCEFormat = function () { 3351 var result = []; 3352 for (var font in this) { 3353 if (_.isString(this[font])) { 3354 result.push(font + "=" + this[font]); 3355 } 3356 } 3357 3358 return result.join(';'); 3359 }; 3360 3361 return fonts; 3362 }, 3363 3364 getNodeFont: function (node) { 3365 var $node = this.jQuery(node) 3366 var font = $node.css('font-family'); 3367 var fontArray = font.replace(/[\'\"]/g, '').replace(/\s/g, '').toLowerCase().split(','); 3368 var fonts = this.getFonts(); 3369 3370 if (_.isObject(fonts)) { 3371 for (var name in fonts) { 3372 if (_.isString(fonts[name])) { 3373 var _fontArray = fonts[name].replace(/[\'\"]/g, '').replace(/\s/g, '').toLowerCase().split(','); 3374 if (_.difference(_fontArray, fontArray).length === 0) { 3375 return name; 3376 } 3377 } 3378 } 3379 } 3380 3381 return font; 3382 }, 3383 3384 getFontWeights: function (font) { 3385 var fonts = CP_Customizer.utils.getValue('web_fonts'); 3386 3387 if (fonts) { 3388 for (var i = 0; i < fonts.length; i++) { 3389 var _font = fonts[i]; 3390 if (_font.family.toLowerCase() === font.toLowerCase()) { 3391 var weights = []; 3392 for (var w = 0; w < _font.weights.length; w++) { 3393 var weight = _font.weights[w]; 3394 if (weight === 'normal' || weight === 'regular') { 3395 weight = '400'; 3396 } else { 3397 try { 3398 weight = parseInt(weight).toString(); 3399 } catch (e) { 3400 3401 } 3402 } 3403 3404 if (weights.indexOf(weight) === -1) { 3405 weights.push(weight); 3406 } 3407 } 3408 return weights; 3409 } 3410 } 3411 } 3412 3413 return ['100', '200', '300', '400', '500', '600', '700', '800', '900']; 3414 }, 3415 3416 getTextElementCUI: function () { 3417 var editorID = 'cp-tinymce-cui-editor'; 3418 var editor = root.CP_Customizer.preview.frame().tinymce ? root.CP_Customizer.preview.frame().tinymce.get(editorID) : 'cp-editor-not-found'; 3419 3420 if (editor === 'cp-editor-not-found') { 3421 return undefined; 3422 } 3423 3424 var self = this; 3425 if (!editor) { 3426 this.jQuery('body').after('<div id="' + editorID + '"></div>'); 3427 var options = { 3428 "selector": "#" + editorID, 3429 inline: true, 3430 style_formats_merge: true, 3431 extended_valid_elements: 'span', 3432 "formats": { 3433 alignment: {selector: 'p,h1,h2,h3,h4,h5,h6', styles: {textAlign: '%value'}}, 3434 fontweight: {inline: 'span', styles: {fontWeight: '%value'}}, 3435 fontsize: {inline: 'span', styles: {fontSize: '%value'}}, 3436 fontcolor: {inline: 'span', styles: {color: '%value'}}, 3437 italic: {inline: 'span', styles: {fontStyle: 'italic'}}, 3438 3439 }, 3440 "menubar": false, 3441 "theme": "modern", 3442 "skin": "lightgray", 3443 "toolbar": 'fontselect addwebfont font-weight font-size-popup | italic underline strikethrough superscript subscript alignment font-color-popup | removeformat', 3444 "font_formats": this.getFonts().toTinyMCEFormat(), 3445 "paste_as_text": true, 3446 "forced_root_block": false, 3447 setup: function (ed) { 3448 var bm; 3449 3450 ed.addButton('font-weight', { 3451 type: 'listbox', 3452 text: root.CP_Customizer.translateCompanionString('Font Weight'), 3453 icon: false, 3454 onselect: function (e) { 3455 ed.formatter.apply('fontweight', {value: this.value()}); 3456 }, 3457 values: [ 3458 {text: 'Thin (100)', value: '100'}, 3459 {text: 'Extra light (200)', value: '200'}, 3460 {text: 'Light (300)', value: '300'}, 3461 {text: 'Normal (400)', value: '400'}, 3462 {text: 'Medium (500)', value: '500'}, 3463 {text: 'Semi Bold (600)', value: '600'}, 3464 {text: 'Bold (700)', value: '700'}, 3465 {text: 'Extra Bold (800)', value: '800'}, 3466 {text: 'Black (900)', value: '900'} 3467 ], 3468 onPostRender: function () { 3469 3470 // add font control separator// 3471 var fontControl = ed.theme.panel.controlIdLookup['mceu_0']; 3472 fontControl.on('showMenu', function (e) { 3473 var items = this.menu.items(); 3474 for (var i in items) { 3475 var item = items[i]; 3476 3477 if (!_.isFunction(item.text)) { 3478 continue; 3479 } 3480 3481 if (item.text().raw.toLowerCase() == 'arial') { 3482 item.$el.addClass('first-system-font'); 3483 } 3484 } 3485 }); 3486 3487 var btn = this; 3488 ed.on('NodeChange', _.debounce(function (e) { 3489 var weight = jQuery(e.element || ed.selection.getNode()).css('font-weight'); 3490 if (weight === "bold") weight = "700"; 3491 if (weight === "normal") weight = "400"; 3492 btn.value(weight); 3493 }, 10)); 3494 3495 btn.on('show', function (e) { 3496 ed.theme.panel.getEl().style.display = "block"; 3497 e.control.$el.css({top: this.$el.offset().top + 34, left: this.$el.offset().left}) 3498 }); 3499 3500 btn.on('showMenu', function () { 3501 var font = CP_Customizer.preview.getNodeFont(ed.selection.getNode()); 3502 var weights = CP_Customizer.preview.getFontWeights(font); 3503 for (var i in btn.menu.items()) { 3504 var item = btn.menu.items()[i]; 3505 3506 if (!_.isFunction(item.value)) { 3507 continue; 3508 } 3509 3510 if (weights.indexOf(item.value()) === -1) { 3511 item.$el.hide(); 3512 } else { 3513 item.$el.show(); 3514 } 3515 } 3516 }); 3517 } 3518 }); 3519 3520 3521 ed.addButton('alignment', { 3522 type: 'listbox', 3523 text: root.CP_Customizer.translateCompanionString(''), 3524 icon: true, 3525 onselect: function (e) { 3526 ed.formatter.apply('alignment', {value: this.value()}); 3527 }, 3528 values: [ 3529 { 3530 icon: 'alignleft', 3531 text: root.CP_Customizer.translateCompanionString(''), 3532 value: 'left' 3533 }, 3534 { 3535 icon: 'aligncenter', 3536 text: root.CP_Customizer.translateCompanionString(''), 3537 value: 'center' 3538 }, 3539 { 3540 icon: 'alignright', 3541 text: root.CP_Customizer.translateCompanionString(''), 3542 value: 'right' 3543 }, 3544 { 3545 icon: 'alignjustify', 3546 text: root.CP_Customizer.translateCompanionString(''), 3547 value: 'justify' 3548 } 3549 ], 3550 onPostRender: function () { 3551 var btn = this; 3552 ed.on('NodeChange', function (e) { 3553 var textAlign = jQuery(ed.selection.getNode()).css('text-align'); 3554 btn.value(textAlign); 3555 btn.icon('align' + textAlign); 3556 3557 //Disable text alignment for header elements 3558 if (jQuery(e.element).parents('.header-wrapper').length) 3559 { 3560 btn.$el.hide(); 3561 } else 3562 { 3563 btn.$el.show(); 3564 } 3565 }); 3566 3567 btn.on('show', function (e) { 3568 ed.theme.panel.getEl().style.display = "block"; 3569 e.control.$el.css({top: this.$el.offset().top + 34, left: this.$el.offset().left}) 3570 e.control.$el.eq(0).css('min-width', '10px'); 3571 }); 3572 } 3573 }); 3574 3575 ed.addButton('addwebfont', { 3576 type: 'button', 3577 icon: 'insert', 3578 tooltip: root.CP_Customizer.translateCompanionString("Add web font"), 3579 onPostRender: function () { 3580 this.on("click", function () { 3581 top.wp.customize.control('web_fonts').focus() 3582 }); 3583 } 3584 }); 3585 ed.addButton('font-color-popup', { 3586 type: "colorbutton", 3587 icon: false, 3588 3589 3590 onPostRender: function () { 3591 var btn = this; 3592 3593 self.jQuery(this.getEl()).spectrum({ 3594 showAlpha: true, 3595 3596 preferredFormat: "rgb", 3597 showInput: true, 3598 show: function () { 3599 //console.log(this); 3600 3601 var colorPalette = CP_Customizer.hooks.applyFilters('spectrum_color_palette', []); 3602 3603 3604 var color = jQuery(ed.selection.getNode()).css('color'); 3605 var spectrumEl = self.jQuery(btn.getEl()); 3606 3607 var container = spectrumEl.spectrum("container"); 3608 spectrumEl.spectrum("set", color); 3609 3610 spectrumEl.spectrum("option", "showPalette", colorPalette.length > 0); 3611 3612 if (colorPalette.length > 0) { 3613 3614 // group colors a 3 per row 3615 colorPalette = CP_Customizer.utils.arrayChunk(colorPalette, 3); 3616 3617 spectrumEl.spectrum("option", "palette", colorPalette); 3618 } 3619 3620 3621 var offTop = container.offset().top 3622 var scrollTop = self.frame().scrollY; 3623 3624 container.css({ 3625 top: self.jQuery(btn.getEl()).offset().top - scrollTop + 30, 3626 "left": "auto", 3627 "right": CP_Customizer.preview.frame().innerWidth - jQuery(btn.getEl()).offset().left - 40 3628 }); 3629 3630 self.jQuery(self.jQuery('body')[0].ownerDocument).scroll(function () { 3631 var offTop = container.offset().top 3632 var scrollTop = self.jQuery('body').scrollTop(); 3633 3634 container.offset({ 3635 top: self.jQuery(btn.getEl()).offset().top - scrollTop + 30 3636 }); 3637 }); 3638 3639 }, 3640 change: function (color) { 3641 var col = color.toRgbString(); 3642 btn.value(col); 3643 3644 ed.selection.moveToBookmark(bm); 3645 ed.formatter.apply('fontcolor', {value: col}); 3646 } 3647 }); 3648 3649 btn.on("click", function () { 3650 bm = ed.selection.getBookmark(); 3651 }); 3652 3653 ed.on('NodeChange', function (e) { 3654 var color = jQuery(ed.selection.getNode()).css('color'); 3655 btn.color(color); 3656 self.jQuery(btn.getEl()).spectrum("set", color); 3657 }); 3658 3659 function onEditorBlur(e) { 3660 self.jQuery(btn.getEl()).spectrum('hide'); 3661 CP_Customizer.preview.restartObserver(); 3662 } 3663 3664 ed.on('blur', onEditorBlur); 3665 3666 3667 } 3668 }); 3669 ed.on('focus', function (e) { 3670 // _.delay(function () { 3671 // var editorEL = e.target.theme.panel.getEl(), 3672 // node = e.target.bodyElement, 3673 // margin = ($(node).width() - $(editorEL).width()) / 2; 3674 // 3675 // $(editorEL).css({ 3676 // 'margin-left': margin 3677 // }); 3678 // }, 0); 3679 }); 3680 3681 updateOnEditorBlur = _.debounce(function (e) { 3682 _.delay(function () { 3683 var $node = $(e.target.bodyElement); 3684 CP_Customizer.preview.markNode($node); 3685 3686 if ($node.is('[data-theme]')) { 3687 CP_Customizer.preview.jQuery($node).data('was-changed', true); 3688 } 3689 CP_Customizer.updateState(); 3690 }, 0); 3691 }, 100); 3692 3693 ed.on('blur', updateOnEditorBlur); 3694 3695 } 3696 }; 3697 root.CP_Customizer.preview.frame().tinymce.init(options); 3698 editor = root.CP_Customizer.preview.frame().tinymce.get(editorID); 3699 3700 } 3701 3702 return editor; 3703 }, 3704 3705 blur: function (overlayOnly) { 3706 var hoverOverlay = CP_Customizer.overlays.hoverOverlay(); 3707 var hoveredNode = CP_Customizer.preview.jQuery(hoverOverlay.data().node); 3708 3709 // hoverOverlay.deactivateHeatZone(); 3710 3711 var fakeNode = CP_Customizer.preview.jQuery("<p contenteditable='true' style='display: none;' />"); 3712 3713 CP_Customizer.overlays.assignNode(hoverOverlay, fakeNode); 3714 3715 if (overlayOnly) { 3716 return; 3717 } 3718 3719 if (CP_Customizer.preview.getTextElementCUI()) { 3720 CP_Customizer.preview.getTextElementCUI().fire('blur'); 3721 } 3722 3723 3724 } 3725 }, 3726 3727 overlays: { 3728 3729 3730 addFixedOverlays: function ($startNode) { 3731 var $ = root.CP_Customizer.preview.jQuery(); 3732 3733 if ($startNode.length > 1) { 3734 3735 var self = this; 3736 $startNode.each(function () { 3737 self.addFixedOverlays($(this)); 3738 }); 3739 return; 3740 3741 } 3742 $startNode = $startNode || $('body'); 3743 3744 if ($startNode.closest('[data-type="row"]').length || $startNode.closest('[data-type="column"]').length) { 3745 return; 3746 } 3747 3748 root.CP_Customizer.trigger(root.CP_Customizer.events.ADD_FIXED_OVERLAYS, [$startNode]); 3749 3750 }, 3751 3752 3753 __fixedOverlayOptions: {}, 3754 registerFixedOverlayOptions: function (name, options) { 3755 3756 if (_.isObject(name)) { 3757 _.each(name, function (options, key) { 3758 CP_Customizer.overlays.registerFixedOverlayOptions(key, options); 3759 }); 3760 } else { 3761 3762 if (!this.__fixedOverlayOptions.hasOwnProperty(name)) { 3763 this.__fixedOverlayOptions[name] = options; 3764 } else { 3765 // console.error("Overlay options name '" + name + "' already exists"); 3766 } 3767 } 3768 3769 }, 3770 3771 getOverlayOptionButton: getButtonElement, 3772 3773 addOptionsToFixedOverlay: 3774 function ($container, type, node, callback) { 3775 var typeOptions = this.__fixedOverlayOptions[type], 3776 $toAppend; 3777 3778 typeOptions = CP_Customizer.hooks.applyFilters('section_fixed_overlay_options', _.clone(typeOptions), type); 3779 3780 if (!typeOptions) { 3781 console.error('Undefined typeoptions', type, node); 3782 return; 3783 } 3784 3785 var jQuery = CP_Customizer.preview.jQuery(); 3786 var _node = (typeOptions.nodeOverrider || _.identity)(node); 3787 for (var key in typeOptions) { 3788 var filteredOptions = CP_Customizer.hooks.applyFilters('section_fixed_overlay', typeOptions[key], key); 3789 if (typeOptions.hasOwnProperty(key)) { 3790 switch (key) { 3791 case 'title': 3792 $toAppend = getTitleElement(filteredOptions, _node, type); 3793 if ($toAppend) { 3794 $container.append($toAppend); 3795 } 3796 break; 3797 case 'items': 3798 $toAppend = getItemsElements(filteredOptions, _node, type); 3799 $container.append($toAppend); 3800 break; 3801 case 'node_binds': 3802 var nodeBinds = filteredOptions; 3803 jQuery.each(nodeBinds, function (bind, callbacks) { 3804 if (bind === "hover") { 3805 _node.hover( 3806 function (event) { 3807 callbacks[0].bind(this)(event, jQuery(this).data().overlay); 3808 }, 3809 function (event) { 3810 var isNodeRelated = jQuery(this).data().overlay.find("*").addBack().is(event.relatedTarget); 3811 if (isNodeRelated) { 3812 event.preventDefault(); 3813 event.stopPropagation(); 3814 return false; 3815 } 3816 3817 callbacks[1].bind(this)(event, jQuery(this).data().overlay); 3818 } 3819 ); 3820 } else { 3821 _node.bind(bind, callbacks); 3822 } 3823 }); 3824 break; 3825 case 'toolbar_binds': 3826 var toolbarBinds = typeOptions[key]; 3827 var overlay = jQuery(node).data().overlay; 3828 jQuery.each(toolbarBinds, function (bind, callbacks) { 3829 if (bind === "hover") { 3830 overlay.find('.overlay-toolbar').hover( 3831 function (event) { 3832 callbacks[0].bind(node)(event, overlay); 3833 }, 3834 function (event) { 3835 callbacks[1].bind(node)(event, overlay); 3836 } 3837 ); 3838 } else { 3839 overlay.bind(bind, callbacks); 3840 } 3841 }); 3842 break; 3843 } 3844 } 3845 } 3846 3847 if (callback) { 3848 callback(typeOptions); 3849 } 3850 } 3851 3852 , 3853 3854 updateOverlay: function (overlay, node, cover, positionOnly) { 3855 var $ = root.CP_Customizer.preview.jQuery(); 3856 node = $(node); 3857 updateControls = !positionOnly; 3858 3859 if (!node || !node.length) { 3860 return; 3861 } 3862 3863 3864 if (updateControls) { 3865 overlay.find('.pen-overlay').css({ 3866 width: node.outerWidth(), 3867 height: node.outerHeight(), 3868 'pointer-events': 'all', 3869 'display': 'block' 3870 }); 3871 3872 overlay.find('.add-element-bubble.visible').removeClass('visible'); 3873 overlay.find('.add-element-bubble .expanded').removeClass('expanded'); 3874 3875 if (node.outerHeight() < 30) { 3876 overlay.find('.pen-overlay').addClass('small'); 3877 } else { 3878 overlay.find('.pen-overlay').removeClass('small'); 3879 } 3880 3881 3882 if (node.parent().is('.ui-sortable') && node.siblings(root.CP_Customizer.CONTENT_ELEMENTS).length && node.closest(".page-content,[data-theme]").length) { 3883 overlay.find('.move').show(); 3884 } else { 3885 overlay.find('.move').hide(); 3886 } 3887 3888 3889 if (!node.is(':visible')) { 3890 overlay.hide(); 3891 } else { 3892 overlay.show(); 3893 } 3894 3895 overlay.find('.add').show(); 3896 if (node.closest('[data-add-content]').length) { 3897 value = node.closest('[data-add-content]').attr('data-add-content'); 3898 3899 if (value === "false") { 3900 overlay.find('.add').hide(); 3901 } 3902 } 3903 3904 3905 if (node.closest('[data-type="row"]').length && node.closest('[data-type="row"]').is('[data-custom-items]')) { 3906 overlay.find('.top-container').hide(); 3907 overlay.find('[h-align-center]').hide(); 3908 } else { 3909 overlay.find('.top-container').show(); 3910 overlay.find('[h-align-center]').show(); 3911 } 3912 3913 3914 if (overlay.is('.add-content-overlay')) { 3915 if (node.is('[data-type="column"]') && node.closest('[data-type=row]').length === 0) { 3916 overlay.find('.remove').hide(); 3917 } else { 3918 if (node.closest('[data-type=row]').children().length > 1) { 3919 overlay.find('.remove').show(); 3920 } else { 3921 overlay.find('.remove').hide(); 3922 } 3923 } 3924 } 3925 3926 if (overlay.is('.node-hover-overlay')) { 3927 if (node.siblings().length === 0) { 3928 overlay.find('.remove').hide(); 3929 } else { 3930 if (node.is(root.CP_Customizer.CONTENT_ELEMENTS)) { 3931 overlay.find('.remove').show(); 3932 } else { 3933 overlay.find('.remove').hide(); 3934 } 3935 } 3936 } 3937 3938 if (overlay.is('.item-hover-overlay')) { 3939 if (node.closest('[data-type=row]').children().length > 1) { 3940 overlay.find('.remove').show(); 3941 } else { 3942 overlay.find('.remove').hide(); 3943 } 3944 } 3945 3946 } 3947 3948 var bounds = node[0].getBoundingClientRect(); 3949 var scrollTop = root.CP_Customizer.preview.frame().pageYOffset; 3950 var scrollLeft = root.CP_Customizer.preview.frame().pageXOffset; 3951 overlay.css({ 3952 left: (parseInt(bounds.left) + scrollLeft) + "px", 3953 top: (parseInt(bounds.top) + scrollTop) + "px" 3954 }); 3955 3956 overlay.css({ 3957 width: node.outerWidth(), 3958 'position': 'absolute' 3959 }); 3960 3961 if (!cover) { 3962 overlay.css({ 3963 height: 'auto', 3964 'background-color': '' 3965 }); 3966 } 3967 3968 overlay.children('.overlay-left, .overlay-right').css({ 3969 height: node.outerHeight(), 3970 width: '0px' 3971 }); 3972 overlay.children('.overlay-right').css({ 3973 left: node.outerWidth() - 1, 3974 width: '0px' 3975 }); 3976 overlay.children('.overlay-top, .overlay-bottom').css({ 3977 height: '0px', 3978 width: node.outerWidth() 3979 }); 3980 overlay.children('.overlay-bottom').css({ 3981 top: node.outerHeight() 3982 }); 3983 3984 overlay.children('[align-bottom]').each(function () { 3985 $(this).css({ 3986 top: node.outerHeight() - 5 3987 }); 3988 }); 3989 3990 overlay.children('[align-top]').css({ 3991 top: 0 3992 }); 3993 3994 overlay.children('[h-align-center]').each(function () { 3995 $(this).css({ 3996 left: (node.outerWidth() - $(this).outerWidth()) / 2 3997 }); 3998 }); 3999 4000 }, 4001 4002 4003 updateAllOverlays: function (event) { 4004 var updateOnlySections = Array.from(arguments).length === 0; 4005 var update = function () { 4006 var $ = CP_Customizer.preview.jQuery(); 4007 this.overlaysContainer.children().each(function () { 4008 var isSection = $(this).is('.section-overlay'); 4009 4010 if (updateOnlySections && !isSection) { 4011 return; 4012 } 4013 4014 var node = $(this).data('node'); 4015 if (node) { 4016 4017 4018 root.CP_Customizer.overlays.updateOverlay($(this), $(node), false, true); 4019 4020 var isScrollEvent = event && event.type == 'scroll'; 4021 4022 if ($(this).is('.heatzone') && !isScrollEvent) { 4023 $(this).removeClass('heatzone'); 4024 } 4025 if (event === true) { 4026 $(this).hide(); 4027 } 4028 } 4029 }); 4030 }.bind({ 4031 overlaysContainer: root.CP_Customizer.overlays.overlaysContainer() 4032 }); 4033 4034 update(); 4035 return true; 4036 }, 4037 4038 overlaysContainer: function () { 4039 var overlaysContainer = CP_Customizer.preview.find('#cp-overlays'); 4040 4041 if (!overlaysContainer.length) { 4042 overlaysContainer = CP_Customizer.preview.jQuery()('<div id="cp-overlays"></div>'); 4043 CP_Customizer.preview.find('body').append(overlaysContainer); 4044 } 4045 4046 return overlaysContainer; 4047 }, 4048 4049 hoverOverlay: function () { 4050 var $ = root.CP_Customizer.preview.jQuery(); 4051 var hoverOverlay = $('[data-overlay="cp-hoveroverlay"]'); 4052 4053 if (hoverOverlay.length) { 4054 return hoverOverlay; 4055 } 4056 4057 hoverOverlay = $('<div data-overlay="cp-hoveroverlay" class="node-hover-overlay"><div class="pen-overlay"><svg xmlns="http://www.w3.org/2000/svg" height="20px" viewBox="0 0 20 20"><path d="M13.89 3.39l2.71 2.72c.46.46.42 1.24.03 1.64l-8.01 8.02-5.56 1.16 1.16-5.58s7.6-7.63 7.99-8.03c.39-.39 1.22-.39 1.68.07zm-2.73 2.79l-5.59 5.61 1.11 1.11 5.54-5.65zm-2.97 8.23l5.58-5.6-1.07-1.08-5.59 5.6z"></path></svg></div><span title="' + root.CP_Customizer.translateCompanionString("Move element") + '" class="move"></span><span title="' + root.CP_Customizer.translateCompanionString("Delete element") + '" class=" remove"></span><div class="overlay-top overlay-border"></div><div class="overlay-left overlay-border"></div><div class="overlay-right overlay-border"></div><div class="overlay-bottom overlay-border"></div></div>'); 4058 4059 root.CP_Customizer.overlays.overlaysContainer().append(hoverOverlay); 4060 hoverOverlay.hide(); 4061 4062 hoverOverlay.find('.remove').click(function () { 4063 root.CP_Customizer.preview.removeNode($(hoverOverlay.data('node'))); 4064 hoverOverlay.hide(); 4065 }); 4066 4067 hoverOverlay.find('.pen-overlay').unbind('click').click(function (event) { 4068 var $node = $(hoverOverlay.data('node')); 4069 4070 if ($node.is('[data-focus-control]')) { 4071 var setting = wp.customize($node.attr('data-focus-control')); 4072 var control = setting ? setting.findControls()[0] : null; 4073 4074 if (control) { 4075 control.focus(); 4076 if (control.container.closest('.customizer-right-section').length) { 4077 var sidebarID = control.container.closest('.customizer-right-section').attr('id').replace('-popup', ''); 4078 jQuery('[data-sidebar-container="' + sidebarID + '"]').click(); 4079 // control.container.closest('.customizer-right-section').addClass('active'); 4080 } 4081 } 4082 4083 return; 4084 } 4085 4086 if ($node.is('[data-widgets-area]')) { 4087 root.wp.customize.section('sidebar-widgets-' + $node.attr('data-widgets-area')).focus(); 4088 return; 4089 } 4090 4091 if ($node.is('hr')) { 4092 return; 4093 } 4094 4095 if ($node.is('[data-content-shortcode]')) { 4096 var shortcodeData = CP_Customizer.parseShortcode($node.attr('data-content-shortcode')); 4097 CP_Customizer.hooks.doAction('shortcode_edit', $node, shortcodeData); 4098 CP_Customizer.hooks.doAction('shortcode_edit_' + shortcodeData.tag, $node, shortcodeData); 4099 return; 4100 } 4101 4102 if (!$node.data('container-editable')) { 4103 $node.off(); 4104 $(this).hide(); 4105 } 4106 4107 if ($node.is('[data-content-item-container="true"]')) { 4108 $node = $node.children().eq(0); 4109 } 4110 4111 $node.click(); 4112 $node.data('cpFocused', true); 4113 4114 if ($node.is(root.CP_Customizer.TEXT_ELEMENTS)) { 4115 $node.focus(); 4116 4117 _.delay(function () { 4118 root.CP_Customizer.preview.placeCursorAtEnd($node[0]); 4119 }, 5); 4120 4121 CP_Customizer.hooks.doAction('text_element_clicked', $node); 4122 4123 hoverOverlay.activateHeatZone(); 4124 } else { 4125 CP_Customizer.hooks.doAction('element_clicked', $node); 4126 } 4127 4128 }); 4129 4130 function findCenter($, el) { 4131 el = $(el); 4132 var o = el.offset(); 4133 return { 4134 x: o.left + el.outerWidth() / 2, 4135 y: o.top + el.outerHeight() / 2 4136 }; 4137 } 4138 4139 function triggerDrag(el, ev) { 4140 var target = el, 4141 $ = root.CP_Customizer.preview.jQuery(), 4142 frame = root.CP_Customizer.preview.frame(); 4143 4144 var self = this, 4145 center = findCenter($, target), 4146 options = {}, 4147 x = Math.floor(center.x), 4148 y = Math.floor(center.y), 4149 dx = options.dx || 0, 4150 dy = options.dy || 0; 4151 var coord = { 4152 clientX: x, 4153 clientY: y 4154 }; 4155 4156 var type = "mousedown"; 4157 4158 var e = $.extend({ 4159 bubbles: true, 4160 cancelable: (type != "mousemove"), 4161 view: frame, 4162 detail: 0, 4163 screenX: 0, 4164 screenY: 0, 4165 clientX: 0, 4166 clientY: 0, 4167 ctrlKey: false, 4168 altKey: false, 4169 shiftKey: false, 4170 metaKey: false, 4171 button: 0, 4172 relatedTarget: el 4173 }, coord); 4174 4175 // var relatedTarget = $(el).parent().data('node'); 4176 4177 var evt = document.createEvent("MouseEvents"); 4178 evt.initMouseEvent(type, e.bubbles, e.cancelable, e.view, e.detail, 4179 e.screenX, e.screenY, ev.clientX, ev.clientY, 4180 e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, 4181 e.button, null); 4182 4183 el.dispatchEvent(evt); 4184 } 4185 4186 4187 var moveHandlerCallback = function ($handle, event) { 4188 4189 if (event.which !== 1) { 4190 return; 4191 } 4192 4193 var overlay = $handle.closest('.node-hover-overlay'); 4194 4195 var $node = $(hoverOverlay.data('node')); 4196 4197 if ($node.siblings().length === 0) { 4198 return; 4199 } 4200 4201 $node.blur(); 4202 4203 if ($node.data('reikidragging')) { 4204 overlay.attr('is-dragging', false); 4205 $node.data('reikidragging', false); 4206 return; 4207 } 4208 4209 var $first = $node.parents('.ui-sortable').first(); 4210 if ($first.data("ui-sortable")) { 4211 $first.sortable('enable'); 4212 } 4213 4214 $node.data('reikidragging', true); 4215 overlay.attr('is-dragging', true); 4216 4217 $('[contenteditable="true"]').attr('contenteditable', false); 4218 $('[contenteditable="true"]').blur(); 4219 triggerDrag($node[0], event); 4220 root.CP_Customizer.isSorting = true; 4221 4222 root.CP_Customizer.preview.hideTextElementCUI(); 4223 }; 4224 4225 4226 hoverOverlay.find('.move').off('mousedown.cp').on('mousedown.cp', function (event) { 4227 _(moveHandlerCallback).delay(50, $(this), event); 4228 }); 4229 4230 4231 hoverOverlay.find('.move').off('mouseup.cp').on('mouseup.cp', function (event) { 4232 var overlay = $(this).closest('.node-hover-overlay'); 4233 overlay.attr('is-dragging', false); 4234 }); 4235 4236 hoverOverlay.activateHeatZone = function () { 4237 var $this = $(this); 4238 $this.addClass('heatzone'); 4239 4240 var top = $this.find('.overlay-top'), 4241 left = $this.find('.overlay-left'), 4242 right = $this.find('.overlay-right'), 4243 bottom = $this.find('.overlay-bottom'); 4244 4245 if (top.find('.zone').length === 0) { 4246 top.append('<div class="zone" />'); 4247 } 4248 4249 if (left.find('.zone').length === 0) { 4250 left.append('<div class="zone" />'); 4251 } 4252 4253 if (right.find('.zone').length === 0) { 4254 right.append('<div class="zone" />'); 4255 } 4256 4257 if (bottom.find('.zone').length === 0) { 4258 bottom.append('<div class="zone" />'); 4259 } 4260 4261 var node = $this.data('node'); 4262 var $node = CP_Customizer.preview.jQuery(node); 4263 4264 var nodeRect = { 4265 top: $node.offset().top, 4266 bottom: $node.offset().top + node.offsetHeight, 4267 height: node.offsetHeight, 4268 left: node.getBoundingClientRect().left, 4269 right: node.getBoundingClientRect().left + node.offsetWidth, 4270 width: node.offsetWidth 4271 }; 4272 4273 var docHeight = $(node).closest('body').height(); 4274 var docWidth = Math.min(CP_Customizer.preview.frame().innerWidth, CP_Customizer.preview.jQuery('html').width()); 4275 4276 4277 top.find('.zone').css({ 4278 height: nodeRect.top, 4279 width: docWidth, 4280 left: -1 * nodeRect.left 4281 } 4282 ); 4283 4284 bottom.find('.zone').css({ 4285 height: docHeight - nodeRect.bottom, 4286 width: docWidth, 4287 left: -1 * nodeRect.left, 4288 top: '-1px' 4289 } 4290 ); 4291 4292 left.find('.zone').css({ 4293 height: nodeRect.height, 4294 width: nodeRect.left 4295 //top: -1 * nodeRect.top - nodeRect.height / 2 4296 } 4297 ); 4298 4299 right.find('.zone').css({ 4300 height: nodeRect.height, 4301 width: docWidth - nodeRect.right 4302 // top: -1 * nodeRect.top - nodeRect.height / 2 4303 } 4304 ); 4305 4306 hoverOverlay.off('click.zone').on('click.zone', '.zone', function (event) { 4307 hoverOverlay.removeClass('heatzone'); 4308 4309 event.preventDefault(); 4310 event.stopPropagation(); 4311 4312 var x = event.clientX, 4313 y = event.clientY, 4314 elementMouseIsOver = CP_Customizer.preview.frame().document.elementFromPoint(x, y); 4315 4316 // 4317 hoverOverlay.addClass('heatzone'); 4318 CP_Customizer.preview.blur(); 4319 _.delay(function () { 4320 hoverOverlay.removeClass('heatzone'); 4321 CP_Customizer.preview.jQuery(elementMouseIsOver).trigger('mouseover'); 4322 }, 10); 4323 return false; 4324 }); 4325 }; 4326 4327 // hoverOverlay.deactivateHeatZone = function () { 4328 // hoverOverlay.removeClass('heatzone'); 4329 // }; 4330 4331 return hoverOverlay; 4332 4333 }, 4334 4335 rowItemHoverOverlay: function () { 4336 var $ = root.CP_Customizer.preview.jQuery(); 4337 var itemHoverOverlay = $('[data-overlay="cp-item-hover-overlay"]'); 4338 4339 if (itemHoverOverlay.length) { 4340 return itemHoverOverlay; 4341 } 4342 4343 itemHoverOverlay = $('<div data-overlay="cp-item-hover-overlay" class="item-hover-overlay"> <div h-align-right title="' + root.CP_Customizer.translateCompanionString("Delete item") + '" class="remove"></div> </div>'); 4344 4345 root.CP_Customizer.overlays.overlaysContainer().append(itemHoverOverlay); 4346 4347 itemHoverOverlay.hide(); 4348 4349 itemHoverOverlay.find('.remove').click(function () { 4350 var node = $(itemHoverOverlay.data('node')); 4351 root.CP_Customizer.preview.removeNode(node); 4352 root.CP_Customizer.hooks.doAction('section_list_item_refresh'); 4353 itemHoverOverlay.hide(); 4354 }); 4355 4356 return itemHoverOverlay; 4357 }, 4358 4359 4360 addOverlay: function () { 4361 4362 var $ = root.CP_Customizer.preview.jQuery(); 4363 var addOverlay = $('[data-overlay="cp-addoverlay"]'); 4364 4365 if (addOverlay.length) { 4366 return addOverlay; 4367 } 4368 4369 addOverlay = $('<div data-overlay="cp-addoverlay" class="add-content-overlay"><div class="buttons" align-bottom h-align-center><div class="add" title="' + root.CP_Customizer.translateCompanionString("Add element") + '">' + root.CP_Customizer.translateCompanionString("Add element") + '</div></div></div>'); 4370 root.CP_Customizer.overlays.overlaysContainer().append(addOverlay); 4371 addOverlay.hide(); 4372 4373 //addOverlay.find('.add').prepend('<div class="add-element-bubble"><div class="elements-container"></div><i class="element-bubble-close"></i></div>'); 4374 // let's add the close button in a future update 4375 addOverlay.find('.add').prepend('<div class="add-element-bubble"><div class="elements-container"></div></div>'); 4376 4377 4378 addOverlay.find('.add').click(function (event) { 4379 addOverlay.find('.add').find('.add-element-bubble').toggleClass('visible'); 4380 }); 4381 4382 root.CP_Customizer.content.addContentItemsTo(addOverlay.find('.elements-container')); 4383 4384 addOverlay.find('.elements-container').on('cp-insert-content-item', function (event, type, insertHandler) { 4385 event.preventDefault(); 4386 var $node = $(addOverlay.data('node')); 4387 var index = $node.children().length; 4388 4389 insertHandler(type, $node, index, after); 4390 4391 function after($node) { 4392 root.CP_Customizer.preview.decorateElements($node); 4393 root.CP_Customizer.overlays.updateOverlay(addOverlay, $(addOverlay.data('node'))); 4394 CP_Customizer.renderNodeShortcodes($node); 4395 // CP_Customizer.hooks.doAction('after_node_insert', $node); 4396 } 4397 }); 4398 4399 return addOverlay; 4400 }, 4401 4402 assignNode: function (overlay, node, cover) { 4403 var $ = root.CP_Customizer.preview.jQuery(); 4404 if (overlay.attr('is-dragging') && overlay.attr('is-dragging') === "true") { 4405 return; 4406 } 4407 if ($(overlay.data('node')).is(node)) { 4408 return; 4409 } else { 4410 /*if (overlay.data('node') && overlay.data('node').ownerDocument.activeElement == overlay.data('node')) { 4411 debugger; 4412 $(overlay.data('node')).blur(); 4413 }*/ 4414 } 4415 4416 overlay.data('node', $(node)[0]); 4417 4418 function updateOverlay() { 4419 root.CP_Customizer.overlays.updateOverlay(overlay, $(node), cover); 4420 } 4421 4422 overlay.on('reiki.update_overlays', '*', function (event) { 4423 setTimeout(updateOverlay, 0); 4424 }); 4425 4426 root.CP_Customizer.preview.hideTextElementCUI(); 4427 updateOverlay(); 4428 }, 4429 4430 hideMovableOverlays: function () { 4431 CP_Customizer.overlays.addOverlay().hide(); 4432 CP_Customizer.overlays.hoverOverlay().hide(); 4433 CP_Customizer.overlays.rowItemHoverOverlay().hide() 4434 } 4435 4436 } 4437 , 4438 4439 content: { 4440 __registeredItems: { 4441 'link': 4442 { 4443 icon: 'mdi-link-variant', 4444 tooltip: translateCompanionString('link'), 4445 data: 4446 '<a class="link" data-cpid="new" data-container-editable="true" data-content-code-editable href="#">' + translateCompanionString('new link') + '</a>', 4447 'after': function ($item) { 4448 $item.unbind('click').click(function (event) { 4449 event.preventDefault(); 4450 event.stopImmediatePropagation(); 4451 event.stopPropagation(); 4452 4453 if ($(this).is('[data-container-editable]') || $(this).is('[data-type=group]')) { 4454 CP_Customizer.preview.editContainerData.apply(this); 4455 } 4456 4457 return false; 4458 }); 4459 } 4460 } 4461 , 4462 'button': 4463 { 4464 icon: 'mdi-open-in-new', 4465 tooltip: translateCompanionString('button'), 4466 data: 4467 '<a data-cpid="new" data-container-editable="true" data-content-code-editable class="button blue" href="#">' + translateCompanionString('new button') + '</a>', 4468 'after': function ($item) { 4469 $item.unbind('click').click(function (event) { 4470 event.preventDefault(); 4471 event.stopImmediatePropagation(); 4472 event.stopPropagation(); 4473 4474 if ($(this).is('[data-container-editable]') || $(this).is('[data-type=group]')) { 4475 CP_Customizer.preview.editContainerData.apply(this); 4476 } 4477 4478 return false; 4479 }); 4480 } 4481 } 4482 , 4483 'heading': 4484 { 4485 icon: 'mdi-format-header-pound larger', 4486 tooltip: translateCompanionString('heading'), 4487 items: 4488 function () { 4489 var result = {}; 4490 for (var i = 1; i <= 6; i++) { 4491 result['h' + i] = { 4492 label: "H" + i, 4493 data: '<h' + i + '>' + translateCompanionString("Heading") + ' ' + i + '</h' + i + '>', 4494 tooltip: translateCompanionString('Heading') + ' ' + i 4495 }; 4496 } 4497 4498 return result; 4499 } 4500 } 4501 , 4502 4503 'lead': 4504 { 4505 icon: 'mdi-format-align-left', 4506 tooltip: translateCompanionString('lead'), 4507 data: 4508 '<p data-cpid="new" class="lead" data-content-editable="true" contenteditable="true">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>' 4509 } 4510 , 4511 4512 'paragraph': 4513 { 4514 icon: 'mdi-format-paragraph larger', 4515 tooltip: translateCompanionString('paragraph'), 4516 data: 4517 '<p data-cpid="new" data-content-editable="true" contenteditable="true">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>' 4518 } 4519 , 4520 4521 'image': 4522 { 4523 icon: 'mdi-image-area big', 4524 tooltip: translateCompanionString('image'), 4525 data: 4526 '<img data-cpid="new" class="custom-image" data-content-code-editable="true" data-content-editable="true" contenteditable="true" src="#"/>' 4527 } 4528 // , 4529 4530 // 'icon': 4531 // { 4532 // icon: 'mdi-adjust', 4533 // items: 4534 // function () { 4535 // var result = {}; 4536 // for (var i = 1; i <= 6; i++) { 4537 // result['mdi' + i] = { 4538 // icon: 'mdi-flag mdi' + i, 4539 // data: '<i class="mdi cp-icon mdi' + i + ' mdi-adjust"></i>', 4540 // tooltip: "Font Icon " + i 4541 // }; 4542 // } 4543 // 4544 // return result; 4545 // } 4546 // } 4547 // , 4548 // 'separator': 4549 // { 4550 // 'icon': 4551 // "mdi-adjust", 4552 // data: 4553 // '<div class="spacer" data-type="group"><span class="mdi before"></span><i data-content-code-editable="true" class="mdi mdi-adjust"></i><span class="mdi after"></span></div>' 4554 // } 4555 }, 4556 4557 registerItem: function (data) { 4558 4559 if (data) { 4560 for (var key in data) { 4561 if (data[key].contentElementSelector) { 4562 CP_Customizer.addContentElementsSelectors(data[key].contentElementSelector); 4563 } 4564 } 4565 } 4566 4567 _.extend(this.__registeredItems, data); 4568 }, 4569 4570 getItemData: function (type) { 4571 types = type.split('.'); 4572 var start = this.__registeredItems; 4573 4574 for (var i = 0; i < types.length; i++) { 4575 var _type = types[i]; 4576 4577 if (i + 1 < types.length) { 4578 var _items = start[_type].items; 4579 if (_(_items).isFunction()) { 4580 _items = _items.call(); 4581 4582 } 4583 start = _items; 4584 } else { 4585 return start[_type].data; 4586 } 4587 } 4588 }, 4589 4590 getItemAfter: function (type) { 4591 types = type.split('.'); 4592 var start = this.__registeredItems; 4593 4594 for (var i = 0; i < types.length; i++) { 4595 var _type = types[i]; 4596 4597 if (i + 1 < types.length) { 4598 var _items = start[_type].items; 4599 if (_(_items).isFunction()) { 4600 _items = _items.call(); 4601 4602 } 4603 start = _items; 4604 } else { 4605 return start[_type].after; 4606 } 4607 } 4608 }, 4609 4610 getContentItems: function (data, subitems, parentId) { 4611 data = data || this.__registeredItems; 4612 subitems = subitems || false; 4613 var self = this; 4614 var $result = $("<div />"); 4615 $.each(data, function (id, option) { 4616 var title = option.toolip || option.tooltip || id; // || for old typo :D 4617 var idAttr = parentId ? parentId + "." + id : id; 4618 var _item = $('<i class="mdi ' + (option.icon || "") + '" title="' + title + '" data-' + (option.items ? "parent" : "content") + '-id="' + idAttr + '"></i>'); 4619 4620 if (option.label) { 4621 _item.append('<span class="item-label">' + option.label + '</span>'); 4622 } 4623 4624 if (option.items) { 4625 4626 var _items = option.items; 4627 4628 if (_(_items).isFunction()) { 4629 _items = option.items.call(); 4630 } 4631 4632 var subitemsContainer = $('<div class="subitems-container" />'); 4633 subitemsContainer.append(self.getContentItems(_items, true, idAttr)); 4634 _item.append(subitemsContainer); 4635 } 4636 4637 $result.append(_item); 4638 }); 4639 4640 return $result.html(); 4641 4642 }, 4643 4644 4645 addContentItemsTo: function ($container) { 4646 $container.append(CP_Customizer.content.getContentItems()); 4647 var self = this; 4648 $container.off('click.cp-new-content').on('click.cp-new-content', 'i.mdi[data-content-id]', function (event) { 4649 event.preventDefault(); 4650 event.stopPropagation(); 4651 4652 var node_type = $(this).data('content-id'); 4653 $container.trigger('cp-insert-content-item', [node_type, self.insertNewContent]); 4654 }); 4655 4656 $container.off('click.cp-new-parent').on('click.cp-new-parent', 'i.mdi[data-parent-id]', function (event) { 4657 event.preventDefault(); 4658 event.stopPropagation(); 4659 $(this).toggleClass('expanded'); 4660 $(this).siblings().removeClass('expanded'); 4661 }); 4662 }, 4663 4664 insertNewContent: function (type, $container, index, after) { 4665 var $ = CP_Customizer.preview.jQuery(); 4666 var $new = $(CP_Customizer.content.getItemData(type)); 4667 var itemAfter = CP_Customizer.content.getItemAfter(type); 4668 CP_Customizer.preview.insertNode($new, $container, index); 4669 setTimeout(function () { 4670 $new.trigger('click'); 4671 if (_(after).isFunction()) { 4672 after($new); 4673 4674 4675 } 4676 if (_.isFunction(itemAfter)) { 4677 itemAfter($new); 4678 } 4679 }, 100); 4680 } 4681 } 4682 4683 } 4684 ; 4685 4686 CP_Customizer = _.extend(CP_Customizer, { 4687 closePopUps: root.Materialis.closePopUps, 4688 popUp: root.Materialis.popUp, 4689 openRightSidebar: root.Materialis.openRightSidebar, 4690 hideRightSidebar: root.Materialis.hideRightSidebar, 4691 4692 }); 4693 top.CP_Customizer = root.CP_Customizer = CP_Customizer; 4694 4695 4696 var previewLoadedMessageCallback = function (event) { 4697 if (event.data === 'cloudpress_update_customizer') { 4698 4699 if (root.__isCPChangesetPreview) { 4700 CP_Customizer.preview.jQuery('html').addClass('cp__changeset__preview'); 4701 return; 4702 } 4703 4704 setTimeout(function () { 4705 CP_Customizer.hideLoader(); 4706 CP_Customizer.preview.frame().wp.customize.preview.bind('loading-initiated', function () { 4707 CP_Customizer.showLoader(); 4708 CP_Customizer.trigger('PREVIEW_LOADING_START'); 4709 }); 4710 4711 }, 300); 4712 4713 _(CP_Customizer).extend(window.cpCustomizerGlobal); 4714 CP_Customizer.trigger('PREVIEW_LOADED'); 4715 4716 CP_Customizer.preview.addContentBinds(); 4717 4718 CP_Customizer.preview.jQuery('a').on('click', function (event) { 4719 event.preventDefault(); 4720 event.stopPropagation(); 4721 }); 4722 4723 CP_Customizer.preview.decorateMods(); 4724 CP_Customizer.preview.decorateElements(); 4725 4726 4727 // make the save button use CP_Customizer save wrapper 4728 $(root.document).find('input#save').unbind('click').bind('click', function (event) { 4729 4730 event.preventDefault(); 4731 event.stopPropagation(); 4732 root.CP_Customizer.save(); 4733 }); 4734 4735 } 4736 }; 4737 4738 root.addEventListener('message', previewLoadedMessageCallback); 4739 4740 4741 $(root).bind('keydown', function (event) { 4742 if (event.ctrlKey || event.metaKey) { 4743 var key = String.fromCharCode(event.which).toLowerCase(); 4744 if (key === "s") { 4745 event.preventDefault(); 4746 event.stopPropagation(); 4747 root.CP_Customizer.save(); 4748 } 4749 } 4750 }); 4751 4752 $(root.document).find('input#save').unbind('click').bind('click', function (event) { 4753 event.preventDefault(); 4754 event.stopPropagation(); 4755 root.CP_Customizer.save(); 4756 }); 4757 4758 4759 $(root.document).ready(function () { 4760 4761 for (var i = 0; i < CP_Customizer.__modules.length; i++) { 4762 var callback = CP_Customizer.__modules[i]; 4763 callback(CP_Customizer); 4764 } 4765 4766 CP_Customizer.__modulesLoaded = true; 4767 CP_Customizer.trigger('DOCUMENT_READY'); 4768 }); 4769 4770 // UTILS 4771 4772 function getTitleElement(name, node, category) { 4773 var label = ""; 4774 if (typeof name === "function") { 4775 label = name(node); 4776 } else { 4777 if (!_.isUndefined(name)) { 4778 label = name; 4779 } else { 4780 return ""; 4781 } 4782 } 4783 4784 return "<span data-category=\"" + category + "\" class=\"cog-item title\">" + label + "</span>"; 4785 } 4786 4787 function getButtonElement(itemData, node, category) { 4788 var template = '<span data-category="' + category + '" class="cog-item ' + (itemData.classes || "") + '"></span>'; 4789 4790 var $button = $(template).attr({ 4791 'data-name': (itemData.name || 'button') 4792 }); 4793 $button.text(itemData.title || 'Button'); 4794 4795 4796 // key is event handler 4797 $.each(itemData, function (key, data) { 4798 if (key === 'on_hover') { 4799 var callbackIn = function () { 4800 data[0].call($button, node); 4801 }; 4802 var callbackOut = function () { 4803 4804 data[1].call($button, node); 4805 }; 4806 $button.hover(callbackIn, callbackOut); 4807 4808 } else if (key.indexOf('on_') === 0) { 4809 var ev = key.replace('on_', ''); 4810 var callback = function (event) { 4811 event.preventDefault(); 4812 event.stopPropagation(); 4813 data.call($button, node); 4814 }; 4815 $button.bind(ev, callback); 4816 } 4817 }); 4818 4819 return $button; 4820 } 4821 4822 function getItemsElements(itemsArray, node, category) { 4823 result = []; 4824 for (var i = 0; i < itemsArray.length; i++) { 4825 var itemData = itemsArray[i]; 4826 var $item = getButtonElement(itemData, node, category); 4827 result.push($item); 4828 } 4829 return result; 4830 } 4831 4832 })(jQuery, window);