~canonical-sysadmins/wordpress/4.7.2

« back to all changes in this revision

Viewing changes to wp-includes/js/tinymce/plugins/wordpress/plugin.js

  • Committer: Jacek Nykis
  • Date: 2015-01-05 16:17:05 UTC
  • Revision ID: jacek.nykis@canonical.com-20150105161705-w544l1h5mcg7u4w9
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* global tinymce, getUserSetting, setUserSetting */
 
2
 
 
3
// Set the minimum value for the modals z-index higher than #wpadminbar (100000)
 
4
tinymce.ui.FloatPanel.zIndex = 100100;
 
5
 
 
6
tinymce.PluginManager.add( 'wordpress', function( editor ) {
 
7
        var DOM = tinymce.DOM, wpAdvButton, modKey, style,
 
8
                last = 0;
 
9
 
 
10
        function toggleToolbars( state ) {
 
11
                var iframe, initial, toolbars,
 
12
                        pixels = 0;
 
13
 
 
14
                initial = ( state === 'hide' );
 
15
 
 
16
                if ( editor.theme.panel ) {
 
17
                        toolbars = editor.theme.panel.find('.toolbar:not(.menubar)');
 
18
                }
 
19
 
 
20
                if ( ! toolbars || toolbars.length < 2 || ( state === 'hide' && ! toolbars[1].visible() ) ) {
 
21
                        return;
 
22
                }
 
23
 
 
24
                if ( ! state && toolbars[1].visible() ) {
 
25
                        state = 'hide';
 
26
                }
 
27
 
 
28
                tinymce.each( toolbars, function( toolbar, i ) {
 
29
                        if ( i > 0 ) {
 
30
                                if ( state === 'hide' ) {
 
31
                                        toolbar.hide();
 
32
                                        pixels += 30;
 
33
                                } else {
 
34
                                        toolbar.show();
 
35
                                        pixels -= 30;
 
36
                                }
 
37
                        }
 
38
                });
 
39
 
 
40
                if ( pixels && ! initial ) {
 
41
                        // Resize iframe, not needed in iOS
 
42
                        if ( ! tinymce.Env.iOS ) {
 
43
                                iframe = editor.getContentAreaContainer().firstChild;
 
44
                                DOM.setStyle( iframe, 'height', iframe.clientHeight + pixels );
 
45
                        }
 
46
 
 
47
                        if ( state === 'hide' ) {
 
48
                                setUserSetting('hidetb', '0');
 
49
                                wpAdvButton && wpAdvButton.active( false );
 
50
                        } else {
 
51
                                setUserSetting('hidetb', '1');
 
52
                                wpAdvButton && wpAdvButton.active( true );
 
53
                        }
 
54
                }
 
55
 
 
56
                editor.fire( 'wp-toolbar-toggle' );
 
57
        }
 
58
 
 
59
        // Add the kitchen sink button :)
 
60
        editor.addButton( 'wp_adv', {
 
61
                tooltip: 'Toolbar Toggle',
 
62
                cmd: 'WP_Adv',
 
63
                onPostRender: function() {
 
64
                        wpAdvButton = this;
 
65
                        wpAdvButton.active( getUserSetting( 'hidetb' ) === '1' ? true : false );
 
66
                }
 
67
        });
 
68
 
 
69
        // Hide the toolbars after loading
 
70
        editor.on( 'PostRender', function() {
 
71
                if ( editor.getParam( 'wordpress_adv_hidden', true ) && getUserSetting( 'hidetb', '0' ) === '0' ) {
 
72
                        toggleToolbars( 'hide' );
 
73
                }
 
74
        });
 
75
 
 
76
        editor.addCommand( 'WP_Adv', function() {
 
77
                toggleToolbars();
 
78
        });
 
79
 
 
80
        editor.on( 'focus', function() {
 
81
        window.wpActiveEditor = editor.id;
 
82
    });
 
83
 
 
84
        // Replace Read More/Next Page tags with images
 
85
        editor.on( 'BeforeSetContent', function( e ) {
 
86
                var title;
 
87
 
 
88
                if ( e.content ) {
 
89
                        if ( e.content.indexOf( '<!--more' ) !== -1 ) {
 
90
                                title = editor.editorManager.i18n.translate( 'Read more...' );
 
91
 
 
92
                                e.content = e.content.replace( /<!--more(.*?)-->/g, function( match, moretext ) {
 
93
                                        return '<img src="' + tinymce.Env.transparentSrc + '" data-wp-more="more" data-wp-more-text="' + moretext + '" ' +
 
94
                                                'class="wp-more-tag mce-wp-more" title="' + title + '" data-mce-resize="false" data-mce-placeholder="1" />';
 
95
                                });
 
96
                        }
 
97
 
 
98
                        if ( e.content.indexOf( '<!--nextpage-->' ) !== -1 ) {
 
99
                                title = editor.editorManager.i18n.translate( 'Page break' );
 
100
 
 
101
                                e.content = e.content.replace( /<!--nextpage-->/g,
 
102
                                        '<img src="' + tinymce.Env.transparentSrc + '" data-wp-more="nextpage" class="wp-more-tag mce-wp-nextpage" ' +
 
103
                                                'title="' + title + '" data-mce-resize="false" data-mce-placeholder="1" />' );
 
104
                        }
 
105
                }
 
106
        });
 
107
 
 
108
        // Replace images with tags
 
109
        editor.on( 'PostProcess', function( e ) {
 
110
                if ( e.get ) {
 
111
                        e.content = e.content.replace(/<img[^>]+>/g, function( image ) {
 
112
                                var match, moretext = '';
 
113
 
 
114
                                if ( image.indexOf( 'data-wp-more="more"' ) !== -1 ) {
 
115
                                        if ( match = image.match( /data-wp-more-text="([^"]+)"/ ) ) {
 
116
                                                moretext = match[1];
 
117
                                        }
 
118
 
 
119
                                        image = '<!--more' + moretext + '-->';
 
120
                                } else if ( image.indexOf( 'data-wp-more="nextpage"' ) !== -1 ) {
 
121
                                        image = '<!--nextpage-->';
 
122
                                }
 
123
 
 
124
                                return image;
 
125
                        });
 
126
                }
 
127
        });
 
128
 
 
129
        // Display the tag name instead of img in element path
 
130
        editor.on( 'ResolveName', function( event ) {
 
131
                var attr;
 
132
 
 
133
                if ( event.target.nodeName === 'IMG' && ( attr = editor.dom.getAttrib( event.target, 'data-wp-more' ) ) ) {
 
134
                        event.name = attr;
 
135
                }
 
136
        });
 
137
 
 
138
        // Register commands
 
139
        editor.addCommand( 'WP_More', function( tag ) {
 
140
                var parent, html, title,
 
141
                        classname = 'wp-more-tag',
 
142
                        dom = editor.dom,
 
143
                        node = editor.selection.getNode();
 
144
 
 
145
                tag = tag || 'more';
 
146
                classname += ' mce-wp-' + tag;
 
147
                title = tag === 'more' ? 'Read more...' : 'Next page';
 
148
                title = editor.editorManager.i18n.translate( title );
 
149
                html = '<img src="' + tinymce.Env.transparentSrc + '" title="' + title + '" class="' + classname + '" ' +
 
150
                        'data-wp-more="' + tag + '" data-mce-resize="false" data-mce-placeholder="1" />';
 
151
 
 
152
                // Most common case
 
153
                if ( node.nodeName === 'BODY' || ( node.nodeName === 'P' && node.parentNode.nodeName === 'BODY' ) ) {
 
154
                        editor.insertContent( html );
 
155
                        return;
 
156
                }
 
157
 
 
158
                // Get the top level parent node
 
159
                parent = dom.getParent( node, function( found ) {
 
160
                        if ( found.parentNode && found.parentNode.nodeName === 'BODY' ) {
 
161
                                return true;
 
162
                        }
 
163
 
 
164
                        return false;
 
165
                }, editor.getBody() );
 
166
 
 
167
                if ( parent ) {
 
168
                        if ( parent.nodeName === 'P' ) {
 
169
                                parent.appendChild( dom.create( 'p', null, html ).firstChild );
 
170
                        } else {
 
171
                                dom.insertAfter( dom.create( 'p', null, html ), parent );
 
172
                        }
 
173
 
 
174
                        editor.nodeChanged();
 
175
                }
 
176
        });
 
177
 
 
178
        editor.addCommand( 'WP_Code', function() {
 
179
                editor.formatter.toggle('code');
 
180
        });
 
181
 
 
182
        editor.addCommand( 'WP_Page', function() {
 
183
                editor.execCommand( 'WP_More', 'nextpage' );
 
184
        });
 
185
 
 
186
        editor.addCommand( 'WP_Help', function() {
 
187
                editor.windowManager.open({
 
188
                        url: tinymce.baseURL + '/wp-mce-help.php',
 
189
                        title: 'Keyboard Shortcuts',
 
190
                        width: 450,
 
191
                        height: 420,
 
192
                        inline: 1,
 
193
                        classes: 'wp-help'
 
194
                });
 
195
        });
 
196
 
 
197
        editor.addCommand( 'WP_Medialib', function() {
 
198
                if ( typeof wp !== 'undefined' && wp.media && wp.media.editor ) {
 
199
                        wp.media.editor.open( editor.id );
 
200
                }
 
201
        });
 
202
 
 
203
        // Register buttons
 
204
        editor.addButton( 'wp_more', {
 
205
                tooltip: 'Insert Read More tag',
 
206
                onclick: function() {
 
207
                        editor.execCommand( 'WP_More', 'more' );
 
208
                }
 
209
        });
 
210
 
 
211
        editor.addButton( 'wp_page', {
 
212
                tooltip: 'Page break',
 
213
                onclick: function() {
 
214
                        editor.execCommand( 'WP_More', 'nextpage' );
 
215
                }
 
216
        });
 
217
 
 
218
        editor.addButton( 'wp_help', {
 
219
                tooltip: 'Keyboard Shortcuts',
 
220
                cmd: 'WP_Help'
 
221
        });
 
222
 
 
223
        editor.addButton( 'wp_code', {
 
224
                tooltip: 'Code',
 
225
                cmd: 'WP_Code',
 
226
                stateSelector: 'code'
 
227
        });
 
228
 
 
229
        // Menubar
 
230
        // Insert->Add Media
 
231
        if ( typeof wp !== 'undefined' && wp.media && wp.media.editor ) {
 
232
                editor.addMenuItem( 'add_media', {
 
233
                        text: 'Add Media',
 
234
                        icon: 'wp-media-library',
 
235
                        context: 'insert',
 
236
                        cmd: 'WP_Medialib'
 
237
                });
 
238
        }
 
239
 
 
240
        // Insert "Read More..."
 
241
        editor.addMenuItem( 'wp_more', {
 
242
                text: 'Insert Read More tag',
 
243
                icon: 'wp_more',
 
244
                context: 'insert',
 
245
                onclick: function() {
 
246
                        editor.execCommand( 'WP_More', 'more' );
 
247
                }
 
248
        });
 
249
 
 
250
        // Insert "Next Page"
 
251
        editor.addMenuItem( 'wp_page', {
 
252
                text: 'Page break',
 
253
                icon: 'wp_page',
 
254
                context: 'insert',
 
255
                onclick: function() {
 
256
                        editor.execCommand( 'WP_More', 'nextpage' );
 
257
                }
 
258
        });
 
259
 
 
260
        editor.on( 'BeforeExecCommand', function(e) {
 
261
                if ( tinymce.Env.webkit && ( e.command === 'InsertUnorderedList' || e.command === 'InsertOrderedList' ) ) {
 
262
                        if ( ! style ) {
 
263
                                style = editor.dom.create( 'style', {'type': 'text/css'},
 
264
                                        '#tinymce,#tinymce span,#tinymce li,#tinymce li>span,#tinymce p,#tinymce p>span{font:medium sans-serif;color:#000;line-height:normal;}');
 
265
                        }
 
266
 
 
267
                        editor.getDoc().head.appendChild( style );
 
268
                }
 
269
        });
 
270
 
 
271
        editor.on( 'ExecCommand', function( e ) {
 
272
                if ( tinymce.Env.webkit && style &&
 
273
                        ( 'InsertUnorderedList' === e.command || 'InsertOrderedList' === e.command ) ) {
 
274
 
 
275
                        editor.dom.remove( style );
 
276
                }
 
277
        });
 
278
 
 
279
        editor.on( 'init', function() {
 
280
                var env = tinymce.Env,
 
281
                        bodyClass = ['mceContentBody'], // back-compat for themes that use this in editor-style.css...
 
282
                        doc = editor.getDoc(),
 
283
                        dom = editor.dom;
 
284
 
 
285
                if ( tinymce.Env.iOS ) {
 
286
                        dom.addClass( doc.documentElement, 'ios' );
 
287
                }
 
288
 
 
289
                if ( editor.getParam( 'directionality' ) === 'rtl' ) {
 
290
                        bodyClass.push('rtl');
 
291
                        dom.setAttrib( doc.documentElement, 'dir', 'rtl' );
 
292
                }
 
293
 
 
294
                if ( env.ie ) {
 
295
                        if ( parseInt( env.ie, 10 ) === 9 ) {
 
296
                                bodyClass.push('ie9');
 
297
                        } else if ( parseInt( env.ie, 10 ) === 8 ) {
 
298
                                bodyClass.push('ie8');
 
299
                        } else if ( env.ie < 8 ) {
 
300
                                bodyClass.push('ie7');
 
301
                        }
 
302
                } else if ( env.webkit ) {
 
303
                        bodyClass.push('webkit');
 
304
                }
 
305
 
 
306
                bodyClass.push('wp-editor');
 
307
 
 
308
                tinymce.each( bodyClass, function( cls ) {
 
309
                        if ( cls ) {
 
310
                                dom.addClass( doc.body, cls );
 
311
                        }
 
312
                });
 
313
 
 
314
                // Remove invalid parent paragraphs when inserting HTML
 
315
                // TODO: still needed?
 
316
                editor.on( 'BeforeSetContent', function( e ) {
 
317
                        if ( e.content ) {
 
318
                                e.content = e.content.replace(/<p>\s*<(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre|address)( [^>]*)?>/gi, '<$1$2>');
 
319
                                e.content = e.content.replace(/<\/(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre|address)>\s*<\/p>/gi, '</$1>');
 
320
                        }
 
321
                });
 
322
 
 
323
                if ( typeof window.jQuery !== 'undefined' ) {
 
324
                        window.jQuery( document ).triggerHandler( 'tinymce-editor-init', [editor] );
 
325
                }
 
326
 
 
327
                if ( window.tinyMCEPreInit && window.tinyMCEPreInit.dragDropUpload ) {
 
328
                        dom.bind( doc, 'dragstart dragend dragover drop', function( event ) {
 
329
                                if ( typeof window.jQuery !== 'undefined' ) {
 
330
                                        // Trigger the jQuery handlers.
 
331
                                        window.jQuery( document ).trigger( new window.jQuery.Event( event ) );
 
332
                                }
 
333
                        });
 
334
                }
 
335
 
 
336
                if ( editor.getParam( 'wp_paste_filters', true ) ) {
 
337
                        if ( ! tinymce.Env.webkit ) {
 
338
                                // In WebKit handled by removeWebKitStyles()
 
339
                                editor.on( 'PastePreProcess', function( event ) {
 
340
                                        // Remove all inline styles
 
341
                                        event.content = event.content.replace( /(<[^>]+) style="[^"]*"([^>]*>)/gi, '$1$2' );
 
342
 
 
343
                                        // Put back the internal styles
 
344
                                        event.content = event.content.replace(/(<[^>]+) data-mce-style=([^>]+>)/gi, '$1 style=$2' );
 
345
                                });
 
346
                        }
 
347
 
 
348
                        editor.on( 'PastePostProcess', function( event ) {
 
349
                                // Remove empty paragraphs
 
350
                                tinymce.each( dom.select( 'p', event.node ), function( node ) {
 
351
                                        if ( dom.isEmpty( node ) ) {
 
352
                                                dom.remove( node );
 
353
                                        }
 
354
                                });
 
355
                        });
 
356
                }
 
357
        });
 
358
 
 
359
        // Word count
 
360
        if ( typeof window.jQuery !== 'undefined' ) {
 
361
                editor.on( 'keyup', function( e ) {
 
362
                        var key = e.keyCode || e.charCode;
 
363
 
 
364
                        if ( key === last ) {
 
365
                                return;
 
366
                        }
 
367
 
 
368
                        if ( 13 === key || 8 === last || 46 === last ) {
 
369
                                window.jQuery( document ).triggerHandler( 'wpcountwords', [ editor.getContent({ format : 'raw' }) ] );
 
370
                        }
 
371
 
 
372
                        last = key;
 
373
                });
 
374
        }
 
375
 
 
376
        editor.on( 'SaveContent', function( e ) {
 
377
                // If editor is hidden, we just want the textarea's value to be saved
 
378
                if ( ! editor.inline && editor.isHidden() ) {
 
379
                        e.content = e.element.value;
 
380
                        return;
 
381
                }
 
382
 
 
383
                // Keep empty paragraphs :(
 
384
                e.content = e.content.replace( /<p>(?:<br ?\/?>|\u00a0|\uFEFF| )*<\/p>/g, '<p>&nbsp;</p>' );
 
385
 
 
386
                if ( editor.getParam( 'wpautop', true ) && typeof window.switchEditors !== 'undefined' ) {
 
387
                        e.content = window.switchEditors.pre_wpautop( e.content );
 
388
                }
 
389
        });
 
390
 
 
391
        // Remove spaces from empty paragraphs.
 
392
        editor.on( 'BeforeSetContent', function( event ) {
 
393
                if ( event.content ) {
 
394
                        event.content = event.content.replace( /<p>(?:&nbsp;|\u00a0|\uFEFF| )+<\/p>/gi, '<p></p>' );
 
395
                }
 
396
        });
 
397
 
 
398
        editor.on( 'preInit', function() {
 
399
                // Don't replace <i> with <em> and <b> with <strong> and don't remove them when empty
 
400
                editor.schema.addValidElements( '@[id|accesskey|class|dir|lang|style|tabindex|title|contenteditable|draggable|dropzone|hidden|spellcheck|translate],i,b' );
 
401
 
 
402
                if ( tinymce.Env.iOS ) {
 
403
                        editor.settings.height = 300;
 
404
                }
 
405
        });
 
406
 
 
407
        // Add custom shortcuts
 
408
        modKey = 'alt+shift';
 
409
 
 
410
        editor.addShortcut( modKey + '+c', '', 'JustifyCenter' );
 
411
        editor.addShortcut( modKey + '+r', '', 'JustifyRight' );
 
412
        editor.addShortcut( modKey + '+l', '', 'JustifyLeft' );
 
413
        editor.addShortcut( modKey + '+j', '', 'JustifyFull' );
 
414
        editor.addShortcut( modKey + '+q', '', 'mceBlockQuote' );
 
415
        editor.addShortcut( modKey + '+u', '', 'InsertUnorderedList' );
 
416
        editor.addShortcut( modKey + '+o', '', 'InsertOrderedList' );
 
417
        editor.addShortcut( modKey + '+n', '', 'mceSpellCheck' );
 
418
        editor.addShortcut( modKey + '+s', '', 'unlink' );
 
419
        editor.addShortcut( modKey + '+m', '', 'WP_Medialib' );
 
420
        editor.addShortcut( modKey + '+z', '', 'WP_Adv' );
 
421
        editor.addShortcut( modKey + '+t', '', 'WP_More' );
 
422
        editor.addShortcut( modKey + '+d', '', 'Strikethrough' );
 
423
        editor.addShortcut( modKey + '+h', '', 'WP_Help' );
 
424
        editor.addShortcut( modKey + '+p', '', 'WP_Page' );
 
425
        editor.addShortcut( modKey + '+x', '', 'WP_Code' );
 
426
        editor.addShortcut( 'ctrl+s', '', function() {
 
427
                if ( typeof wp !== 'undefined' && wp.autosave ) {
 
428
                        wp.autosave.server.triggerSave();
 
429
                }
 
430
        });
 
431
 
 
432
        // popup buttons for the gallery, etc.
 
433
        editor.on( 'init', function() {
 
434
                editor.dom.bind( editor.getWin(), 'scroll', function() {
 
435
                        _hideButtons();
 
436
                });
 
437
 
 
438
                editor.dom.bind( editor.getBody(), 'dragstart', function() {
 
439
                        _hideButtons();
 
440
                });
 
441
        });
 
442
 
 
443
        editor.on( 'BeforeExecCommand', function() {
 
444
                _hideButtons();
 
445
        });
 
446
 
 
447
        editor.on( 'SaveContent', function() {
 
448
                _hideButtons();
 
449
        });
 
450
 
 
451
        editor.on( 'MouseDown', function( e ) {
 
452
                if ( e.target.nodeName !== 'IMG' ) {
 
453
                        _hideButtons();
 
454
                }
 
455
        });
 
456
 
 
457
        editor.on( 'keydown', function( e ) {
 
458
                if ( e.which === tinymce.util.VK.DELETE || e.which === tinymce.util.VK.BACKSPACE ) {
 
459
                        _hideButtons();
 
460
                }
 
461
        });
 
462
 
 
463
        // Internal functions
 
464
        function _setEmbed( c ) {
 
465
                return c.replace( /\[embed\]([\s\S]+?)\[\/embed\][\s\u00a0]*/g, function( a, b ) {
 
466
                        return '<img width="300" height="200" src="' + tinymce.Env.transparentSrc + '" class="wp-oembed" ' +
 
467
                                'alt="'+ b +'" title="'+ b +'" data-mce-resize="false" data-mce-placeholder="1" />';
 
468
                });
 
469
        }
 
470
 
 
471
        function _getEmbed( c ) {
 
472
                return c.replace( /<img[^>]+>/g, function( a ) {
 
473
                        if ( a.indexOf('class="wp-oembed') !== -1 ) {
 
474
                                var u = a.match( /alt="([^\"]+)"/ );
 
475
 
 
476
                                if ( u[1] ) {
 
477
                                        a = '[embed]' + u[1] + '[/embed]';
 
478
                                }
 
479
                        }
 
480
 
 
481
                        return a;
 
482
                });
 
483
        }
 
484
 
 
485
        function _showButtons( n, id ) {
 
486
                var p1, p2, vp, X, Y;
 
487
 
 
488
                vp = editor.dom.getViewPort( editor.getWin() );
 
489
                p1 = DOM.getPos( editor.getContentAreaContainer() );
 
490
                p2 = editor.dom.getPos( n );
 
491
 
 
492
                X = Math.max( p2.x - vp.x, 0 ) + p1.x;
 
493
                Y = Math.max( p2.y - vp.y, 0 ) + p1.y;
 
494
 
 
495
                DOM.setStyles( id, {
 
496
                        'top' : Y + 5 + 'px',
 
497
                        'left' : X + 5 + 'px',
 
498
                        'display': 'block'
 
499
                });
 
500
        }
 
501
 
 
502
        function _hideButtons() {
 
503
                DOM.hide( DOM.select( '#wp_editbtns, #wp_gallerybtns' ) );
 
504
        }
 
505
 
 
506
        // Expose some functions (back-compat)
 
507
        return {
 
508
                _showButtons: _showButtons,
 
509
                _hideButtons: _hideButtons,
 
510
                _setEmbed: _setEmbed,
 
511
                _getEmbed: _getEmbed
 
512
        };
 
513
});