PluginProbe
Virtue/Ascend/Pinnacle Toolkit / 4.9.12.2
Virtue/Ascend/Pinnacle Toolkit v4.9.12.2
4.9.12.2 trunk 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3.0 3.1 3.2 3.3 3.4 3.7 All 48 releases
virtue-toolkit / cmb / js / cmb2-wysiwyg.js

cmb2-wysiwyg.js in Virtue/Ascend/Pinnacle Toolkit 4.9.12.2, at cmb/js/cmb2-wysiwyg.js

346 lines 9.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Used for WYSIWYG logic
3 */
4 window.CMB2 = window.CMB2 || {};
5 window.CMB2.wysiwyg = window.CMB2.wysiwyg || {};
6
7 ( function(window, document, $, cmb, wysiwyg, undefined ) {
8 'use strict';
9
10 // Private variables
11 var toBeDestroyed = [];
12 var toBeInitialized = [];
13 var all = wysiwyg.all = {};
14
15 // Private functions
16
17 /**
18 * Initializes any editors that weren't initialized because they didn't exist yet.
19 *
20 * @since 2.2.3
21 *
22 * @return {void}
23 */
24 function delayedInit() {
25
26 // Don't initialize until they've all been destroyed.
27 if ( 0 === toBeDestroyed.length ) {
28 toBeInitialized.forEach( function ( toInit ) {
29 toBeInitialized.splice( toBeInitialized.indexOf( toInit ), 1 );
30 wysiwyg.init.apply( wysiwyg, toInit );
31 } );
32 } else {
33 window.setTimeout( delayedInit, 100 );
34 }
35 }
36
37 /**
38 * Destroys any editors that weren't destroyed because they didn't exist yet.
39 *
40 * @since 2.2.3
41 *
42 * @return {void}
43 */
44 function delayedDestroy() {
45 toBeDestroyed.forEach( function( id ) {
46 toBeDestroyed.splice( toBeDestroyed.indexOf( id ), 1 );
47 wysiwyg.destroy( id );
48 } );
49 }
50
51 /**
52 * Gets the option data for a group (and initializes that data if it doesn't exist).
53 *
54 * @since 2.2.3
55 *
56 * @param {object} data The group/field data.
57 *
58 * @return {object} Options data object for a group.
59 */
60 function getGroupData( data ) {
61 var groupid = data.groupid;
62 var fieldid = data.fieldid;
63
64 if ( ! all[ groupid ] || ! all[ groupid ][ fieldid ] ) {
65 all[ groupid ] = all[ groupid ] || {};
66 all[ groupid ][ fieldid ] = {
67 template : wp.template( 'cmb2-wysiwyg-' + groupid + '-' + fieldid ),
68 defaults : {
69
70 // Get the data from the template-wysiwyg initiation.
71 mce : $.extend( {}, tinyMCEPreInit.mceInit[ 'cmb2_i_' + groupid + fieldid ] ),
72 qt : $.extend( {}, tinyMCEPreInit.qtInit[ 'cmb2_i_' + groupid + fieldid ] )
73 }
74 };
75 // This is the template-wysiwyg data, and we do not want that to be initiated.
76 delete tinyMCEPreInit.mceInit[ 'cmb2_i_' + groupid + fieldid ];
77 delete tinyMCEPreInit.qtInit[ 'cmb2_i_' + groupid + fieldid ];
78 }
79
80 return all[ groupid ][ fieldid ];
81 }
82
83 /**
84 * Initiates the tinyMCEPreInit options for a wysiwyg editor instance.
85 *
86 * @since 2.2.3
87 *
88 * @param {object} options Options data object for the wysiwyg editor instance.
89 *
90 * @return {void}
91 */
92 function initOptions( options ) {
93 var nameRegex = new RegExp( 'cmb2_n_' + options.groupid + options.fieldid, 'g' );
94 var idRegex = new RegExp( 'cmb2_i_' + options.groupid + options.fieldid, 'g' );
95 var prop, newSettings, newQTS;
96
97 // If no settings for this field. Clone from placeholder.
98 if ( 'undefined' === typeof( tinyMCEPreInit.mceInit[ options.id ] ) ) {
99 newSettings = $.extend( {}, options.defaults.mce );
100 for ( prop in newSettings ) {
101 if ( 'string' === typeof( newSettings[ prop ] ) ) {
102 newSettings[ prop ] = newSettings[ prop ]
103 .replace( idRegex, options.id )
104 .replace( nameRegex, options.name );
105 }
106 }
107 tinyMCEPreInit.mceInit[ options.id ] = newSettings;
108 }
109
110 // If no Quicktag settings for this field. Clone from placeholder.
111 if ( 'undefined' === typeof( tinyMCEPreInit.qtInit[ options.id ] ) ) {
112 newQTS = $.extend( {}, options.defaults.qt );
113 for ( prop in newQTS ) {
114 if ( 'string' === typeof( newQTS[ prop ] ) ) {
115 newQTS[ prop ] = newQTS[ prop ]
116 .replace( idRegex, options.id )
117 .replace( nameRegex, options.name );
118 }
119 }
120 tinyMCEPreInit.qtInit[ options.id ] = newQTS;
121 }
122 }
123
124 /**
125 * Initializes all group wysiwyg editors. Hooked to cmb_init.
126 *
127 * @since 2.2.3
128 *
129 * @return {void}
130 */
131 wysiwyg.initAll = function() {
132 var $this,data,initiated;
133
134 $( '.cmb2-wysiwyg-placeholder' ).each( function() {
135 $this = $( this );
136 data = $this.data();
137
138 if ( data.groupid ) {
139
140 data.id = $this.attr( 'id' );
141 data.name = $this.attr( 'name' );
142 data.value = $this.val();
143
144 wysiwyg.init( $this, data, false );
145 initiated = true;
146 }
147 } );
148
149 if ( true === initiated ) {
150 if ( 'undefined' !== typeof window.QTags ) {
151 window.QTags._buttonsInit();
152 }
153
154 // Hook in our event callbacks.
155 $( document )
156 .on( 'cmb2_add_row', wysiwyg.addRow )
157 .on( 'cmb2_remove_group_row_start', wysiwyg.destroyRowEditors )
158 .on( 'cmb2_shift_rows_start', wysiwyg.shiftStart )
159 .on( 'cmb2_shift_rows_complete', wysiwyg.shiftComplete );
160 }
161 };
162
163 /**
164 * Initiates wysiwyg editors in a new group row. Hooked to cmb2_add_row.
165 *
166 * @since 2.2.3
167 *
168 * @param {object} evt A jQuery-normalized event object.
169 * @param {object} $row A jQuery dom element object for the group row.
170 *
171 * @return {void}
172 */
173 wysiwyg.addRow = function( evt, $row ) {
174 wysiwyg.initRow( $row, evt );
175 };
176
177 /**
178 * Destroys wysiwyg editors in a group row when that row is removed. Hooked to cmb2_remove_group_row_start.
179 *
180 * @since 2.2.3
181 *
182 * @param {object} evt A jQuery-normalized event object.
183 * @param {object} $btn A jQuery dom element object for the remove-row button.
184 *
185 * @return {void}
186 */
187 wysiwyg.destroyRowEditors = function( evt, $btn ) {
188 wysiwyg.destroy( $btn.parents( '.cmb-repeatable-grouping' ).find( '.wp-editor-area' ).attr( 'id' ) );
189 };
190
191 /**
192 * When a row-shift starts, we need to destroy the wysiwyg editors for the group-rows being shuffled.
193 *
194 * @since 2.2.3
195 *
196 * @param {object} evt A jQuery-normalized event object.
197 * @param {object} $btn A jQuery dom element object for the remove-row button.
198 * @param {object} $from A jQuery dom element object for the row being shifted from.
199 * @param {object} $to A jQuery dom element object for the row being shifted to.
200 *
201 * @return {void}
202 */
203 wysiwyg.shiftStart = function( evt, $btn, $from, $to ) {
204 $from.add( $to ).find( '.wp-editor-wrap textarea' ).each( function() {
205 wysiwyg.destroy( $( this ).attr( 'id' ) );
206 } );
207 };
208
209 /**
210 * When a row-shift completes, we need to re-init the wysiwyg editors for the group-rows being shuffled.
211 *
212 * @since 2.2.3
213 *
214 * @param {object} evt A jQuery-normalized event object.
215 * @param {object} $btn A jQuery dom element object for the remove-row button.
216 * @param {object} $from A jQuery dom element object for the row being shifted from.
217 * @param {object} $to A jQuery dom element object for the row being shifted to.
218 *
219 * @return {void}
220 */
221 wysiwyg.shiftComplete = function( evt, $btn, $from, $to ) {
222 $from.add( $to ).each( function() {
223 wysiwyg.initRow( $( this ), evt );
224 } );
225 };
226
227 /**
228 * Initializes editors for a new CMB row.
229 *
230 * @since 2.2.3
231 *
232 * @param {object} $row A jQuery dom element object for the group row.
233 * @param {object} evt A jQuery-normalized event object.
234 *
235 * @return {void}
236 */
237 wysiwyg.initRow = function( $row, evt ) {
238 var $toReplace, data, defVal;
239
240 $row.find( '.cmb2-wysiwyg-inner-wrap' ).each( function() {
241 $toReplace = $( this );
242 data = $toReplace.data();
243 defVal = cmb.getFieldArg( data.hash, 'default', '' );
244 defVal = 'undefined' !== typeof defVal && false !== defVal ? defVal : '';
245
246 data.iterator = $row.data( 'iterator' );
247 data.fieldid = data.id;
248 data.id = data.groupid + '_' + data.iterator + '_' + data.fieldid;
249 data.name = data.groupid + '[' + data.iterator + '][' + data.fieldid + ']';
250 data.value = 'cmb2_add_row' !== evt.type && $toReplace.find( '.wp-editor-area' ).length ? $toReplace.find( '.wp-editor-area' ).val() : defVal;
251
252 // The destroys might not have happened yet. Don't init until they have.
253 if ( 0 === toBeDestroyed.length ) {
254
255 wysiwyg.init( $toReplace, data );
256
257 } else {
258 toBeInitialized.push( [$toReplace, data] );
259 window.setTimeout( delayedInit, 100 );
260 }
261 } );
262
263 };
264
265 /**
266 * Initiates a wysiwyg editor instance and replaces the passed dom element w/ the editor html.
267 *
268 * @since 2.2.3
269 *
270 * @param {object} $toReplace A jQuery dom element which will be replaced with the wysiwyg editor.
271 * @param {object} data Data used to initate the editor.
272 * @param {bool} buttonsInit Whether to run QTags._buttonsInit()
273 *
274 * @return {void}
275 */
276 wysiwyg.init = function( $toReplace, data, buttonsInit ) {
277 if ( ! data.groupid ) {
278 return false;
279 }
280
281 var mceActive = cmb.canTinyMCE();
282 var qtActive = 'function' === typeof window.quicktags;
283 $.extend( data, getGroupData( data ) );
284
285 initOptions( data );
286
287 $toReplace.replaceWith( data.template( data ) );
288
289 if ( mceActive ) {
290 window.tinyMCE.init( tinyMCEPreInit.mceInit[ data.id ] );
291 }
292
293 if ( qtActive ) {
294 window.quicktags( tinyMCEPreInit.qtInit[ data.id ] );
295 }
296
297 if ( mceActive ) {
298 $( document.getElementById( data.id ) ).parents( '.wp-editor-wrap' ).removeClass( 'html-active' ).addClass( 'tmce-active' );
299 }
300
301 if ( false !== buttonsInit && 'undefined' !== typeof window.QTags ) {
302 window.QTags._buttonsInit();
303 }
304
305 };
306
307 /**
308 * Destroys a wysiwyg editor instance.
309 *
310 * @since 2.2.3
311 *
312 * @param {string} id Editor id.
313 *
314 * @return {void}
315 */
316 wysiwyg.destroy = function( id ) {
317 if ( ! cmb.canTinyMCE() ) {
318 // Nothing to see here.
319 return;
320 }
321
322 // The editor might not be initialized yet. But we need to destroy it once it is.
323 var editor = tinyMCE.get( id );
324
325 if ( editor !== null && typeof( editor ) !== 'undefined' ) {
326 editor.destroy();
327
328 if ( 'undefined' === typeof( tinyMCEPreInit.mceInit[ id ] ) ) {
329 delete tinyMCEPreInit.mceInit[ id ];
330 }
331
332 if ( 'undefined' === typeof( tinyMCEPreInit.qtInit[ id ] ) ) {
333 delete tinyMCEPreInit.qtInit[ id ];
334 }
335
336 } else if ( -1 === toBeDestroyed.indexOf( id ) ) {
337 toBeDestroyed.push( id );
338 window.setTimeout( delayedDestroy, 100 );
339 }
340 };
341
342 // Hook in our event callbacks.
343 $( document ).on( 'cmb_init', wysiwyg.initAll );
344
345 } )( window, document, jQuery, window.CMB2, window.CMB2.wysiwyg );
346