| @@ -2,130 +2,183 @@ | ||
| 2 | 2 | * Handles the Insert and Cancel events on TinyMCE and QuickTag Modals |
| 3 | 3 | * |
| 4 | 4 | * @since 1.9.6 |
| 5 | 5 | * |
| 6 | - * @package ConvertKit | |
| 7 | 6 | * @author ConvertKit |
| 8 | 7 | */ |
| 9 | 8 | |
| 10 | -jQuery( document ).ready( | |
| 11 | - function( $ ) { | |
| 9 | +document.addEventListener('DOMContentLoaded', function () { | |
| 10 | + // Cancel. | |
| 11 | + document.body.addEventListener('click', function (e) { | |
| 12 | + // Check if a cancel button was clicked. | |
| 13 | + if ( | |
| 14 | + e.target.matches( | |
| 15 | + '#convertkit-modal-body div.mce-cancel button, #convertkit-modal-body div.mce-cancel button *, #convertkit-quicktags-modal .media-toolbar .media-toolbar-secondary button.cancel' | |
| 16 | + ) | |
| 17 | + ) { | |
| 18 | + // TinyMCE. | |
| 19 | + if ( | |
| 20 | + typeof tinyMCE !== 'undefined' && | |
| 21 | + tinyMCE.activeEditor && | |
| 22 | + !tinyMCE.activeEditor.isHidden() | |
| 23 | + ) { | |
| 24 | + tinymce.activeEditor.windowManager.close(); | |
| 25 | + return; | |
| 26 | + } | |
| 12 | 27 | |
| 13 | - // Cancel. | |
| 14 | - $( 'body' ).on( | |
| 15 | - 'click', | |
| 16 | - 'form.convertkit-tinymce-popup button.close', | |
| 17 | - function( e ) { | |
| 28 | + // Text Editor. | |
| 29 | + // Close the QuickTags modal. | |
| 30 | + convertKitQuickTagsModal.close(); | |
| 31 | + } | |
| 32 | + }); | |
| 18 | 33 | |
| 19 | - // TinyMCE. | |
| 20 | - if ( typeof tinyMCE !== 'undefined' && tinyMCE.activeEditor && ! tinyMCE.activeEditor.isHidden() ) { | |
| 21 | - tinymce.activeEditor.windowManager.close(); | |
| 22 | - return; | |
| 23 | - } | |
| 34 | + // Insert. | |
| 35 | + document.body.addEventListener('click', function (e) { | |
| 36 | + // Check if an insert button was clicked. | |
| 37 | + if ( | |
| 38 | + e.target.matches( | |
| 39 | + '#convertkit-modal-body div.mce-insert button, #convertkit-modal-body div.mce-insert button *, #convertkit-quicktags-modal .media-toolbar .media-toolbar-primary button.button-primary' | |
| 40 | + ) || | |
| 41 | + e.target.matches( | |
| 42 | + 'button.wp-convertkit-refresh-resources, span.dashicons-update' | |
| 43 | + ) | |
| 44 | + ) { | |
| 45 | + // Prevent default action. | |
| 46 | + e.preventDefault(); | |
| 24 | 47 | |
| 25 | - // Text Editor. | |
| 26 | - convertKitQuickTagsModal.close(); | |
| 27 | - | |
| 48 | + // Don't close the modal if the refresh button was clicked. | |
| 49 | + if ( | |
| 50 | + e.target.matches( | |
| 51 | + 'button.wp-convertkit-refresh-resources, span.dashicons-update' | |
| 52 | + ) | |
| 53 | + ) { | |
| 54 | + return; | |
| 28 | 55 | } |
| 29 | - ); | |
| 30 | 56 | |
| 31 | - // Insert. | |
| 32 | - $( 'body' ).on( | |
| 33 | - 'click', | |
| 34 | - 'form.convertkit-tinymce-popup div.buttons input[type=button]', | |
| 35 | - function( e ) { | |
| 57 | + // Get containing form. | |
| 58 | + const form = document.querySelector( | |
| 59 | + 'form.convertkit-tinymce-popup' | |
| 60 | + ); | |
| 36 | 61 | |
| 37 | - // Prevent default action. | |
| 38 | - e.preventDefault(); | |
| 62 | + // Build Shortcode. | |
| 63 | + let shortcode = | |
| 64 | + '[' + form.querySelector('input[name="shortcode"]').value; | |
| 65 | + const shortcodeClose = | |
| 66 | + form.querySelector('input[name="close_shortcode"]').value === | |
| 67 | + '1'; | |
| 39 | 68 | |
| 40 | - // Get containing form. | |
| 41 | - var form = $( this ).closest( 'form.convertkit-tinymce-popup' ); | |
| 69 | + // Iterate through form fields. | |
| 70 | + form.querySelectorAll('input, select').forEach(function (element) { | |
| 71 | + // Skip if no data-shortcode attribute. | |
| 72 | + if (!element.dataset.shortcode) { | |
| 73 | + return; | |
| 74 | + } | |
| 42 | 75 | |
| 43 | - // Build Shortcode. | |
| 44 | - var shortcode = '[' + $( 'input[name="shortcode"]', $( form ) ).val(), | |
| 45 | - shortcodeClose = ( $( 'input[name="close_shortcode"]', $( form ) ).val() == '1' ? true : false ); | |
| 76 | + let val = ''; | |
| 46 | 77 | |
| 47 | - $( 'input, select', $( form ) ).each( | |
| 48 | - function( i ) { | |
| 49 | - // Skip if no data-shortcode attribute. | |
| 50 | - if ( typeof $( this ).data( 'shortcode' ) === 'undefined' ) { | |
| 51 | - return true; | |
| 52 | - } | |
| 78 | + // If this is a color picker, #000000 will be submitted by the browser as the value | |
| 79 | + // even if no value / color was selected. | |
| 80 | + // Check the data-value attribute instead. | |
| 81 | + switch (element.type) { | |
| 82 | + case 'color': | |
| 83 | + val = element.dataset.value; | |
| 84 | + break; | |
| 85 | + default: | |
| 86 | + val = element.value; | |
| 87 | + break; | |
| 88 | + } | |
| 53 | 89 | |
| 54 | - // Skip if the value is empty. | |
| 55 | - if ( ! $( this ).val() ) { | |
| 56 | - return true; | |
| 57 | - } | |
| 58 | - if ( $( this ).val().length == 0 ) { | |
| 59 | - return true; | |
| 60 | - } | |
| 90 | + // Skip if the value is empty. | |
| 91 | + if (!val) { | |
| 92 | + return; | |
| 93 | + } | |
| 94 | + if (val.length === 0) { | |
| 95 | + return; | |
| 96 | + } | |
| 61 | 97 | |
| 62 | - // Get shortcode attribute. | |
| 63 | - var key = $( this ).data( 'shortcode' ), | |
| 64 | - trim = ( $( this ).data( 'trim' ) == '0' ? false : true ), | |
| 65 | - val = $( this ).val(); | |
| 98 | + // Get shortcode attribute. | |
| 99 | + const key = element.dataset.shortcode; | |
| 100 | + const trim = element.dataset.trim !== '0'; | |
| 66 | 101 | |
| 67 | - // Skip if the shortcode is empty. | |
| 68 | - if ( ! key.length ) { | |
| 69 | - return true; | |
| 70 | - } | |
| 102 | + // Skip if the shortcode is empty. | |
| 103 | + if (!key.length) { | |
| 104 | + return; | |
| 105 | + } | |
| 71 | 106 | |
| 72 | - // Trim the value, unless the shortcode attribute disables string trimming. | |
| 73 | - if ( trim ) { | |
| 74 | - val = val.trim(); | |
| 75 | - } | |
| 107 | + // Trim the value, unless the shortcode attribute disables string trimming. | |
| 108 | + if (trim) { | |
| 109 | + val = val.trim(); | |
| 110 | + } | |
| 76 | 111 | |
| 77 | - // Append attribute and value to shortcode string. | |
| 78 | - shortcode += ' ' + key.trim() + '="' + val + '"'; | |
| 79 | - } | |
| 80 | - ); | |
| 112 | + // Append attribute and value to shortcode string. | |
| 113 | + shortcode += ' ' + key.trim() + '="' + val + '"'; | |
| 114 | + }); | |
| 81 | 115 | |
| 82 | - // Close Shortcode. | |
| 83 | - shortcode += ']'; | |
| 116 | + // Close Shortcode. | |
| 117 | + shortcode += ']'; | |
| 84 | 118 | |
| 85 | - // If the shortcode includes a closing element, append it now. | |
| 86 | - if ( shortcodeClose ) { | |
| 87 | - shortcode += '[/' + $( 'input[name="shortcode"]', $( form ) ).val() + ']'; | |
| 88 | - } | |
| 119 | + // If the shortcode includes a closing element, append it now. | |
| 120 | + if (shortcodeClose) { | |
| 121 | + shortcode += | |
| 122 | + '[/' + | |
| 123 | + form.querySelector('input[name="shortcode"]').value + | |
| 124 | + ']'; | |
| 125 | + } | |
| 89 | 126 | |
| 90 | - // Depending on the editor type, insert the shortcode. | |
| 91 | - switch ( $( 'input[name="editor_type"]', $( form ) ).val() ) { | |
| 92 | - case 'tinymce': | |
| 93 | - // Sanity check that a Visual editor exists and is active. | |
| 94 | - if ( typeof tinyMCE !== 'undefined' && tinyMCE.activeEditor && ! tinyMCE.activeEditor.isHidden() ) { | |
| 95 | - // Insert into editor. | |
| 96 | - tinyMCE.activeEditor.execCommand( 'mceReplaceContent', false, shortcode ); | |
| 127 | + // Depending on the editor type, insert the shortcode. | |
| 128 | + switch (form.querySelector('input[name="editor_type"]').value) { | |
| 129 | + case 'tinymce': | |
| 130 | + // Sanity check that a Visual editor exists and is active. | |
| 131 | + if ( | |
| 132 | + typeof tinyMCE !== 'undefined' && | |
| 133 | + tinyMCE.activeEditor && | |
| 134 | + !tinyMCE.activeEditor.isHidden() | |
| 135 | + ) { | |
| 136 | + // Insert into editor. | |
| 137 | + tinyMCE.activeEditor.execCommand( | |
| 138 | + 'mceReplaceContent', | |
| 139 | + false, | |
| 140 | + shortcode | |
| 141 | + ); | |
| 97 | 142 | |
| 98 | - // Close modal. | |
| 99 | - tinyMCE.activeEditor.windowManager.close(); | |
| 100 | - } | |
| 101 | - break; | |
| 143 | + // Close modal. | |
| 144 | + tinyMCE.activeEditor.windowManager.close(); | |
| 145 | + } | |
| 146 | + break; | |
| 102 | 147 | |
| 103 | - case 'quicktags': | |
| 104 | - // Insert into editor. | |
| 105 | - QTags.insertContent( shortcode ); | |
| 148 | + case 'quicktags': | |
| 149 | + // Insert into editor. | |
| 150 | + QTags.insertContent(shortcode); | |
| 106 | 151 | |
| 107 | - // Close modal. | |
| 108 | - convertKitQuickTagsModal.close(); | |
| 109 | - break; | |
| 110 | - } | |
| 152 | + // Close modal. | |
| 153 | + convertKitQuickTagsModal.close(); | |
| 154 | + break; | |
| 111 | 155 | } |
| 112 | - ); | |
| 156 | + } | |
| 157 | + }); | |
| 158 | +}); | |
| 113 | 159 | |
| 114 | - } | |
| 115 | -); | |
| 160 | +// QuickTags: Setup Backbone Modal and Template. | |
| 161 | +if (typeof wp !== 'undefined' && typeof wp.media !== 'undefined') { | |
| 162 | + // Declared globally, as used in this file and quicktags.js. | |
| 163 | + // Setting this as const or let causes a JS error stating that `convertKitQuickTagsModal` is not defined globally. | |
| 164 | + // eslint-disable-next-line no-var | |
| 165 | + var convertKitQuickTagsModal = new wp.media.view.Modal({ | |
| 166 | + controller: { trigger() {} }, | |
| 167 | + className: 'convertkit-quicktags-modal', | |
| 168 | + }); | |
| 169 | + const convertKitQuickTagsModalContent = wp.Backbone.View.extend({ | |
| 170 | + template: wp.template('convertkit-quicktags-modal'), | |
| 171 | + }); | |
| 172 | + convertKitQuickTagsModal.content(new convertKitQuickTagsModalContent()); | |
| 116 | 173 | |
| 117 | -// QuickTags: Setup Backbone Modal and Template. | |
| 118 | -if ( typeof wp !== 'undefined' && typeof wp.media !== 'undefined' ) { | |
| 119 | - var convertKitQuickTagsModal = new wp.media.view.Modal( | |
| 120 | - { | |
| 121 | - controller: { trigger: function() {} }, | |
| 122 | - className: 'convertkit-quicktags-modal' | |
| 123 | - } | |
| 124 | - ); | |
| 125 | - var convertKitQuickTagsModalContent = wp.Backbone.View.extend( | |
| 126 | - { | |
| 127 | - template: wp.template( 'convertkit-quicktags-modal' ) | |
| 128 | - } | |
| 129 | - ); | |
| 130 | - convertKitQuickTagsModal.content( new convertKitQuickTagsModalContent() ); | |
| 174 | + /** | |
| 175 | + * Resets the content of the convertKitQuickTagsModal when closing. | |
| 176 | + * | |
| 177 | + * If this isn't performed, switching from Text to Visual Editor for the same shortcode results | |
| 178 | + * code picking up data from the QuickTags modal, not the TinyMCE one, due to this 'stale' | |
| 179 | + * modal remaining in the DOM, resulting in e.g. the tabbed UI not loading correctly. | |
| 180 | + */ | |
| 181 | + convertKitQuickTagsModal.on('close', function () { | |
| 182 | + this.content(new convertKitQuickTagsModalContent()); | |
| 183 | + }); | |
| 131 | 184 | } |