~canonical-sysadmins/wordpress/4.9.7

« back to all changes in this revision

Viewing changes to wp-admin/js/editor-expand.js

  • Committer: Barry Price
  • Date: 2017-11-17 04:49:02 UTC
  • mfrom: (1.1.30 upstream)
  • Revision ID: barry.price@canonical.com-20171117044902-5frux4ycbq6g9fyf
Merge WP4.9 from upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
                $adminBar = $( '#wpadminbar' ),
7
7
                $footer = $( '#wpfooter' );
8
8
 
9
 
        /* Autoresize editor. */
 
9
        /**
 
10
         * @summary Handles the resizing of the editor.
 
11
         *
 
12
         * @since 4.0.0
 
13
         *
 
14
         * @returns {void}
 
15
         */
10
16
        $( function() {
11
17
                var $wrap = $( '#postdivrich' ),
12
18
                        $contentWrap = $( '#wp-content-wrap' ),
53
59
                                sideSortablesHeight: 0
54
60
                        };
55
61
 
 
62
                /**
 
63
                 * @summary Resizes textarea based on scroll height and width.
 
64
                 *
 
65
                 * Resizes textarea based on scroll height and width. Doesn't shrink the
 
66
                 * editor size below the 300px auto resize minimum height.
 
67
                 *
 
68
                 * @since 4.6.1
 
69
                 *
 
70
                 * @returns {void}
 
71
                 */
56
72
                var shrinkTextarea = window._.throttle( function() {
57
73
                        var x = window.scrollX || document.documentElement.scrollLeft;
58
74
                        var y = window.scrollY || document.documentElement.scrollTop;
73
89
                        }
74
90
                }, 300 );
75
91
 
 
92
                /**
 
93
                 * @summary Resizes the text editor depending on the old text length.
 
94
                 *
 
95
                 * If there is an mceEditor and it is hidden, it resizes the editor depending
 
96
                 * on the old text length. If the current length of the text is smaller than
 
97
                 * the old text length, it shrinks the text area. Otherwise it resizes the editor to
 
98
                 * the scroll height.
 
99
                 *
 
100
                 * @since 4.6.1
 
101
                 *
 
102
                 * @returns {void}
 
103
                 */
76
104
                function textEditorResize() {
77
105
                        var length = textEditor.value.length;
78
106
 
94
122
                        oldTextLength = length;
95
123
                }
96
124
 
 
125
                /**
 
126
                 * @summary Gets the height and widths of elements.
 
127
                 *
 
128
                 * Gets the heights of the window, the adminbar, the tools, the menu,
 
129
                 * the visualTop, the textTop, the bottom, the statusbar and sideSortables
 
130
                 * and stores these in the heights object. Defaults to 0.
 
131
                 * Gets the width of the window and stores this in the heights object.
 
132
                 *
 
133
                 * @since 4.0.0
 
134
                 *
 
135
                 * @returns {void}
 
136
                 */
97
137
                function getHeights() {
98
138
                        var windowWidth = $window.width();
99
139
 
110
150
                                sideSortablesHeight: $sideSortables.height() || 0
111
151
                        };
112
152
 
113
 
                        // Adjust for hidden
 
153
                        // Adjust for hidden menubar.
114
154
                        if ( heights.menuBarHeight < 3 ) {
115
155
                                heights.menuBarHeight = 0;
116
156
                        }
117
157
                }
118
158
 
119
159
                // We need to wait for TinyMCE to initialize.
 
160
                /**
 
161
                 * @summary Binds all necessary functions for editor expand to the editor
 
162
                 * when the editor is initialized.
 
163
                 *
 
164
                 * @since 4.0.0
 
165
                 *
 
166
                 * @param {event} event The TinyMCE editor init event.
 
167
                 * @param {object} editor The editor to bind the vents on.
 
168
                 *
 
169
                 * @returns {void}
 
170
                 */
120
171
                $document.on( 'tinymce-editor-init.editor-expand', function( event, editor ) {
 
172
                        // VK contains the type of key pressed. VK = virtual keyboard.
121
173
                        var VK = window.tinymce.util.VK,
 
174
                                /**
 
175
                                 * @summary Hides any float panel with a hover state. Additionally hides tooltips.
 
176
                                 *
 
177
                                 * @returns {void}
 
178
                                 */
122
179
                                hideFloatPanels = _.debounce( function() {
123
180
                                        ! $( '.mce-floatpanel:hover' ).length && window.tinymce.ui.FloatPanel.hideAll();
124
181
                                        $( '.mce-tooltip' ).hide();
141
198
                        $statusBar = $contentWrap.find( '.mce-statusbar' );
142
199
                        $menuBar = $contentWrap.find( '.mce-menubar' );
143
200
 
 
201
                        /**
 
202
                         * @summary Gets the offset of the editor.
 
203
                         *
 
204
                         * @returns {Number|Boolean} Returns the offset of the editor
 
205
                         * or false if there is no offset height.
 
206
                         */
144
207
                        function mceGetCursorOffset() {
145
208
                                var node = editor.selection.getNode(),
146
209
                                        range, view, offset;
147
210
 
 
211
                                /*
 
212
                                 * If editor.wp.getView and the selection node from the editor selection
 
213
                                 * are defined, use this as a view for the offset.
 
214
                                 */
148
215
                                if ( editor.wp && editor.wp.getView && ( view = editor.wp.getView( node ) ) ) {
149
216
                                        offset = view.getBoundingClientRect();
150
217
                                } else {
151
218
                                        range = editor.selection.getRng();
152
219
 
 
220
                                        // Try to get the offset from a range.
153
221
                                        try {
154
222
                                                offset = range.getClientRects()[0];
155
223
                                        } catch( er ) {}
156
224
 
 
225
                                        // Get the offset from the bounding client rectangle of the node.
157
226
                                        if ( ! offset ) {
158
227
                                                offset = node.getBoundingClientRect();
159
228
                                        }
162
231
                                return offset.height ? offset : false;
163
232
                        }
164
233
 
165
 
                        // Make sure the cursor is always visible.
166
 
                        // This is not only necessary to keep the cursor between the toolbars,
167
 
                        // but also to scroll the window when the cursor moves out of the viewport to a wpview.
168
 
                        // Setting a buffer > 0 will prevent the browser default.
169
 
                        // Some browsers will scroll to the middle,
170
 
                        // others to the top/bottom of the *window* when moving the cursor out of the viewport.
 
234
                        /**
 
235
                         * @summary Filters the special keys that should not be used for scrolling.
 
236
                         *
 
237
                         * @since 4.0.0
 
238
                         *
 
239
                         * @param {event} event The event to get the key code from.
 
240
                         *
 
241
                         * @returns {void}
 
242
                         */
171
243
                        function mceKeyup( event ) {
172
244
                                var key = event.keyCode;
173
245
 
174
 
                                // Bail on special keys.
 
246
                                // Bail on special keys. Key code 47 is a /
175
247
                                if ( key <= 47 && ! ( key === VK.SPACEBAR || key === VK.ENTER || key === VK.DELETE || key === VK.BACKSPACE || key === VK.UP || key === VK.LEFT || key === VK.DOWN || key === VK.UP ) ) {
176
248
                                        return;
177
 
                                // OS keys, function keys, num lock, scroll lock
 
249
                                // OS keys, function keys, num lock, scroll lock. Key code 91-93 are OS keys. Key code 112-123 are F1 to F12. Key code 144 is num lock. Key code 145 is scroll lock.
178
250
                                } else if ( ( key >= 91 && key <= 93 ) || ( key >= 112 && key <= 123 ) || key === 144 || key === 145 ) {
179
251
                                        return;
180
252
                                }
182
254
                                mceScroll( key );
183
255
                        }
184
256
 
 
257
                        /**
 
258
                         * @summary Makes sure the cursor is always visible in the editor.
 
259
                         *
 
260
                         * Makes sure the cursor is kept between the toolbars of the editor and scrolls
 
261
                         * the window when the cursor moves out of the viewport to a wpview.
 
262
                         * Setting a buffer > 0 will prevent the browser default.
 
263
                         * Some browsers will scroll to the middle,
 
264
                         * others to the top/bottom of the *window* when moving the cursor out of the viewport.
 
265
                         *
 
266
                         * @since 4.1.0
 
267
                         *
 
268
                         * @param {string} key The key code of the pressed key.
 
269
                         *
 
270
                         * @returns {void}
 
271
                         */
185
272
                        function mceScroll( key ) {
186
273
                                var offset = mceGetCursorOffset(),
187
274
                                        buffer = 50,
188
275
                                        cursorTop, cursorBottom, editorTop, editorBottom;
189
276
 
 
277
                                // Don't scroll if there is no offset.
190
278
                                if ( ! offset ) {
191
279
                                        return;
192
280
                                }
193
281
 
 
282
                                // Determine the cursorTop based on the offset and the top of the editor iframe.
194
283
                                cursorTop = offset.top + editor.iframeElement.getBoundingClientRect().top;
 
284
 
 
285
                                // Determine the cursorBottom based on the cursorTop and offset height.
195
286
                                cursorBottom = cursorTop + offset.height;
 
287
 
 
288
                                // Subtract the buffer from the cursorTop.
196
289
                                cursorTop = cursorTop - buffer;
 
290
 
 
291
                                // Add the buffer to the cursorBottom.
197
292
                                cursorBottom = cursorBottom + buffer;
198
293
                                editorTop = heights.adminBarHeight + heights.toolsHeight + heights.menuBarHeight + heights.visualTopHeight;
 
294
 
 
295
                                /*
 
296
                                 * Set the editorBottom based on the window Height, and add the bottomHeight and statusBarHeight if the
 
297
                                 * advanced editor is enabled.
 
298
                                 */
199
299
                                editorBottom = heights.windowHeight - ( advanced ? heights.bottomHeight + heights.statusBarHeight : 0 );
200
300
 
201
 
                                // Don't scroll if the node is taller than the visible part of the editor
 
301
                                // Don't scroll if the node is taller than the visible part of the editor.
202
302
                                if ( editorBottom - editorTop < offset.height ) {
203
303
                                        return;
204
304
                                }
205
305
 
 
306
                                /*
 
307
                                 * If the cursorTop is smaller than the editorTop and the up, left
 
308
                                 * or backspace key is pressed, scroll the editor to the position defined
 
309
                                 * by the cursorTop, pageYOffset and editorTop.
 
310
                                 */
206
311
                                if ( cursorTop < editorTop && ( key === VK.UP || key === VK.LEFT || key === VK.BACKSPACE ) ) {
207
312
                                        window.scrollTo( window.pageXOffset, cursorTop + window.pageYOffset - editorTop );
 
313
 
 
314
                                /*
 
315
                                 * If any other key is pressed or the cursorTop is bigger than the editorTop,
 
316
                                 * scroll the editor to the position defined by the cursorBottom,
 
317
                                 * pageYOffset and editorBottom.
 
318
                                 */
208
319
                                } else if ( cursorBottom > editorBottom ) {
209
320
                                        window.scrollTo( window.pageXOffset, cursorBottom + window.pageYOffset - editorBottom );
210
321
                                }
211
322
                        }
212
323
 
 
324
                        /**
 
325
                         * @summary If the editor is fullscreen, calls adjust.
 
326
                         *
 
327
                         * @since 4.1.0
 
328
                         *
 
329
                         * @param {event} event The FullscreenStateChanged event.
 
330
                         *
 
331
                         * @returns {void}
 
332
                         */
213
333
                        function mceFullscreenToggled( event ) {
 
334
                                // event.state is true if the editor is fullscreen.
214
335
                                if ( ! event.state ) {
215
336
                                        adjust();
216
337
                                }
217
338
                        }
218
339
 
219
 
                        // Adjust when switching editor modes.
 
340
                        /**
 
341
                         * @summary Shows the editor when scrolled.
 
342
                         *
 
343
                         * Binds the hideFloatPanels function on the window scroll.mce-float-panels event.
 
344
                         * Executes the wpAutoResize on the active editor.
 
345
                         *
 
346
                         * @since 4.0.0
 
347
                         *
 
348
                         * @returns {void}
 
349
                         */
220
350
                        function mceShow() {
221
351
                                $window.on( 'scroll.mce-float-panels', hideFloatPanels );
222
352
 
226
356
                                }, 300 );
227
357
                        }
228
358
 
 
359
                        /**
 
360
                         * @summary Resizes the editor.
 
361
                         *
 
362
                         * Removes all functions from the window scroll.mce-float-panels event.
 
363
                         * Resizes the text editor and scrolls to a position based on the pageXOffset and adminBarHeight.
 
364
                         *
 
365
                         * @since 4.0.0
 
366
                         *
 
367
                         * @returns {void}
 
368
                         */
229
369
                        function mceHide() {
230
370
                                $window.off( 'scroll.mce-float-panels' );
231
371
 
243
383
                                adjust();
244
384
                        }
245
385
 
 
386
                        /**
 
387
                         * @summary Toggles advanced states.
 
388
                         *
 
389
                         * @since 4.1.0
 
390
                         *
 
391
                         * @returns {void}
 
392
                         */
246
393
                        function toggleAdvanced() {
247
394
                                advanced = ! advanced;
248
395
                        }
249
396
 
 
397
                        /**
 
398
                         * @summary Binds events of the editor and window.
 
399
                         *
 
400
                         * @since 4.0.0
 
401
                         *
 
402
                         * @returns {void}
 
403
                         */
250
404
                        mceBind = function() {
251
405
                                editor.on( 'keyup', mceKeyup );
252
406
                                editor.on( 'show', mceShow );
253
407
                                editor.on( 'hide', mceHide );
254
408
                                editor.on( 'wp-toolbar-toggle', toggleAdvanced );
 
409
 
255
410
                                // Adjust when the editor resizes.
256
411
                                editor.on( 'setcontent wp-autoresize wp-toolbar-toggle', adjust );
 
412
 
257
413
                                // Don't hide the caret after undo/redo.
258
414
                                editor.on( 'undo redo', mceScroll );
 
415
 
259
416
                                // Adjust when exiting TinyMCE's fullscreen mode.
260
417
                                editor.on( 'FullscreenStateChanged', mceFullscreenToggled );
261
418
 
262
419
                                $window.off( 'scroll.mce-float-panels' ).on( 'scroll.mce-float-panels', hideFloatPanels );
263
420
                        };
264
421
 
 
422
                        /**
 
423
                         * @summary Unbinds the events of the editor and window.
 
424
                         *
 
425
                         * @since 4.0.0
 
426
                         *
 
427
                         * @returns {void}
 
428
                         */
265
429
                        mceUnbind = function() {
266
430
                                editor.off( 'keyup', mceKeyup );
267
431
                                editor.off( 'show', mceShow );
275
439
                        };
276
440
 
277
441
                        if ( $wrap.hasClass( 'wp-editor-expand' ) ) {
278
 
                                // Adjust "immediately"
 
442
 
 
443
                                // Adjust "immediately".
279
444
                                mceBind();
280
445
                                initialResize( adjust );
281
446
                        }
282
447
                } );
283
448
 
284
 
                // Adjust the toolbars based on the active editor mode.
 
449
                /**
 
450
                 * @summary Adjusts the toolbars heights and positions.
 
451
                 *
 
452
                 * Adjusts the toolbar heights and positions based on the scroll position on the page,
 
453
                 * the active editor mode and the heights of the editor, admin bar and side bar.
 
454
                 *
 
455
                 * @since 4.0.0
 
456
                 *
 
457
                 * @param {event} event The event that calls this function.
 
458
                 *
 
459
                 * @returns {void}
 
460
                 */
285
461
                function adjust( event ) {
286
 
                        // Make sure we're not in fullscreen mode.
 
462
 
 
463
                        // Makes sure we're not in fullscreen mode.
287
464
                        if ( fullscreen && fullscreen.settings.visible ) {
288
465
                                return;
289
466
                        }
299
476
                                $top, $editor, sidebarTop, footerTop, canPin,
300
477
                                topPos, topHeight, editorPos, editorHeight;
301
478
 
302
 
                        // Refresh the heights
 
479
                        /*
 
480
                         * Refresh the heights if type isn't 'scroll'
 
481
                         * or heights.windowHeight isn't set.
 
482
                         */
303
483
                        if ( resize || ! heights.windowHeight ) {
304
484
                                getHeights();
305
485
                        }
306
486
 
 
487
                        // Resize on resize event when the editor is in text mode.
307
488
                        if ( ! visual && type === 'resize' ) {
308
489
                                textEditorResize();
309
490
                        }
318
499
                                topHeight = heights.textTopHeight;
319
500
                        }
320
501
 
321
 
                        // TinyMCE still initializing.
 
502
                        // Return if TinyMCE is still intializing.
322
503
                        if ( ! visual && ! $top.length ) {
323
504
                                return;
324
505
                        }
327
508
                        editorPos = $editor.offset().top;
328
509
                        editorHeight = $editor.outerHeight();
329
510
 
330
 
                        // Should we pin?
 
511
                        /*
 
512
                         * If in visual mode, checks if the editorHeight is greater than the autoresizeMinHeight + topHeight.
 
513
                         * If not in visual mode, checks if the editorHeight is greater than the autoresizeMinHeight + 20.
 
514
                         */
331
515
                        canPin = visual ? autoresizeMinHeight + topHeight : autoresizeMinHeight + 20; // 20px from textarea padding
332
516
                        canPin = editorHeight > ( canPin + 5 );
333
517
 
357
541
                                        $bottom.attr( 'style', '' );
358
542
                                }
359
543
                        } else {
360
 
                                // Maybe pin the top.
 
544
                                // Check if the top is not already in a fixed position.
361
545
                                if ( ( ! fixedTop || resize ) &&
362
 
                                        // Handle scrolling down.
363
546
                                        ( windowPos >= ( topPos - heights.toolsHeight - heights.adminBarHeight ) &&
364
 
                                        // Handle scrolling up.
365
547
                                        windowPos <= ( topPos - heights.toolsHeight - heights.adminBarHeight + editorHeight - buffer ) ) ) {
366
548
                                        fixedTop = true;
367
549
 
384
566
                                                top: heights.adminBarHeight + heights.toolsHeight + heights.menuBarHeight,
385
567
                                                width: contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top.outerWidth() - $top.width() ) )
386
568
                                        } );
387
 
                                // Maybe unpin the top.
 
569
                                        // Check if the top is already in a fixed position.
388
570
                                } else if ( fixedTop || resize ) {
389
 
                                        // Handle scrolling up.
390
571
                                        if ( windowPos <= ( topPos - heights.toolsHeight - heights.adminBarHeight ) ) {
391
572
                                                fixedTop = false;
392
573
 
409
590
                                                        top: heights.menuBarHeight,
410
591
                                                        width: contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top.outerWidth() - $top.width() ) )
411
592
                                                } );
412
 
                                        // Handle scrolling down.
413
593
                                        } else if ( windowPos >= ( topPos - heights.toolsHeight - heights.adminBarHeight + editorHeight - buffer ) ) {
414
594
                                                fixedTop = false;
415
595
 
435
615
                                        }
436
616
                                }
437
617
 
438
 
                                // Maybe adjust the bottom bar.
 
618
                                // Check if the bottom is not already in a fixed position.
439
619
                                if ( ( ! fixedBottom || ( resize && advanced ) ) &&
440
 
                                                // +[n] for the border around the .wp-editor-container.
 
620
                                                // Add borderWidth for the border around the .wp-editor-container.
441
621
                                                ( windowPos + heights.windowHeight ) <= ( editorPos + editorHeight + heights.bottomHeight + heights.statusBarHeight + borderWidth ) ) {
442
622
 
443
623
                                        if ( event && event.deltaHeight > 0 && event.deltaHeight < 100 ) {
468
648
                                }
469
649
                        }
470
650
 
471
 
                        // Sidebar pinning
472
 
                        if ( $postboxContainer.width() < 300 && heights.windowWidth > 600 && // sidebar position is changed with @media from CSS, make sure it is on the side
473
 
                                $document.height() > ( $sideSortables.height() + postBodyTop + 120 ) && // the sidebar is not the tallest element
474
 
                                heights.windowHeight < editorHeight ) { // the editor is taller than the viewport
 
651
                        // The postbox container is positioned with @media from CSS. Ensure it is pinned on the side.
 
652
                        if ( $postboxContainer.width() < 300 && heights.windowWidth > 600 &&
 
653
 
 
654
                                // Check if the sidebar is not taller than the document height.
 
655
                                $document.height() > ( $sideSortables.height() + postBodyTop + 120 ) &&
 
656
 
 
657
                                // Check if the editor is taller than the viewport.
 
658
                                heights.windowHeight < editorHeight ) {
475
659
 
476
660
                                if ( ( heights.sideSortablesHeight + pinnedToolsTop + sidebarBottom ) > heights.windowHeight || fixedSideTop || fixedSideBottom ) {
477
 
                                        // Reset when scrolling to the top
 
661
 
 
662
                                        // Reset the sideSortables style when scrolling to the top.
478
663
                                        if ( windowPos + pinnedToolsTop <= postBodyTop ) {
479
664
                                                $sideSortables.attr( 'style', '' );
480
665
                                                fixedSideTop = fixedSideBottom = false;
481
666
                                        } else {
 
667
 
 
668
                                                // When scrolling down.
482
669
                                                if ( windowPos > lastScrollPosition ) {
483
 
                                                        // Scrolling down
484
670
                                                        if ( fixedSideTop ) {
485
 
                                                                // let it scroll
 
671
 
 
672
                                                                // Let it scroll.
486
673
                                                                fixedSideTop = false;
487
674
                                                                sidebarTop = $sideSortables.offset().top - heights.adminBarHeight;
488
675
                                                                footerTop = $footer.offset().top;
489
676
 
490
 
                                                                // don't get over the footer
 
677
                                                                // Don't get over the footer.
491
678
                                                                if ( footerTop < sidebarTop + heights.sideSortablesHeight + sidebarBottom ) {
492
679
                                                                        sidebarTop = footerTop - heights.sideSortablesHeight - 12;
493
680
                                                                }
498
685
                                                                        bottom: ''
499
686
                                                                });
500
687
                                                        } else if ( ! fixedSideBottom && heights.sideSortablesHeight + $sideSortables.offset().top + sidebarBottom < windowPos + heights.windowHeight ) {
501
 
                                                                // pin the bottom
 
688
                                                                // Pin the bottom.
502
689
                                                                fixedSideBottom = true;
503
690
 
504
691
                                                                $sideSortables.css({
507
694
                                                                        bottom: sidebarBottom
508
695
                                                                });
509
696
                                                        }
 
697
 
 
698
                                                // When scrolling up.
510
699
                                                } else if ( windowPos < lastScrollPosition ) {
511
 
                                                        // Scrolling up
512
700
                                                        if ( fixedSideBottom ) {
513
 
                                                                // let it scroll
 
701
                                                                // Let it scroll.
514
702
                                                                fixedSideBottom = false;
515
703
                                                                sidebarTop = $sideSortables.offset().top - sidebarBottom;
516
704
                                                                footerTop = $footer.offset().top;
517
705
 
518
 
                                                                // don't get over the footer
 
706
                                                                // Don't get over the footer.
519
707
                                                                if ( footerTop < sidebarTop + heights.sideSortablesHeight + sidebarBottom ) {
520
708
                                                                        sidebarTop = footerTop - heights.sideSortablesHeight - 12;
521
709
                                                                }
526
714
                                                                        bottom: ''
527
715
                                                                });
528
716
                                                        } else if ( ! fixedSideTop && $sideSortables.offset().top >= windowPos + pinnedToolsTop ) {
529
 
                                                                // pin the top
 
717
                                                                // Pin the top.
530
718
                                                                fixedSideTop = true;
531
719
 
532
720
                                                                $sideSortables.css({
538
726
                                                }
539
727
                                        }
540
728
                                } else {
541
 
                                        // if the sidebar container is smaller than the viewport, then pin/unpin the top when scrolling
 
729
                                        // If the sidebar container is smaller than the viewport, then pin/unpin the top when scrolling.
542
730
                                        if ( windowPos >= ( postBodyTop - pinnedToolsTop ) ) {
543
731
 
544
732
                                                $sideSortables.css( {
575
763
                        }
576
764
                }
577
765
 
 
766
                /**
 
767
                 * @summary Resizes the editor and adjusts the toolbars.
 
768
                 *
 
769
                 * @since 4.0.0
 
770
                 *
 
771
                 * @returns {void}
 
772
                 */
578
773
                function fullscreenHide() {
579
774
                        textEditorResize();
580
775
                        adjust();
581
776
                }
582
777
 
 
778
                /**
 
779
                 * @summary Runs the passed function with 500ms intervals.
 
780
                 *
 
781
                 * @since 4.0.0
 
782
                 *
 
783
                 * @param {function} callback The function to run in the timeout.
 
784
                 *
 
785
                 * @returns {void}
 
786
                 */
583
787
                function initialResize( callback ) {
584
788
                        for ( var i = 1; i < 6; i++ ) {
585
789
                                setTimeout( callback, 500 * i );
586
790
                        }
587
791
                }
588
792
 
 
793
                /**
 
794
                 * @summary Runs adjust after 100ms.
 
795
                 *
 
796
                 * @since 4.0.0
 
797
                 *
 
798
                 * @returns {void}
 
799
                 */
589
800
                function afterScroll() {
590
801
                        clearTimeout( scrollTimer );
591
802
                        scrollTimer = setTimeout( adjust, 100 );
592
803
                }
593
804
 
 
805
                /**
 
806
                 * @summary Binds editor expand events on elements.
 
807
                 *
 
808
                 * @since 4.0.0
 
809
                 *
 
810
                 * @returns {void}
 
811
                 */
594
812
                function on() {
595
 
                        // Scroll to the top when triggering this from JS.
596
 
                        // Ensures toolbars are pinned properly.
 
813
                        /*
 
814
                         * Scroll to the top when triggering this from JS.
 
815
                         * Ensure the toolbars are pinned properly.
 
816
                         */
597
817
                        if ( window.pageYOffset && window.pageYOffset > pageYOffsetAtTop ) {
598
818
                                window.scrollTo( window.pageXOffset, 0 );
599
819
                        }
606
826
                                afterScroll();
607
827
                        } );
608
828
 
609
 
                        // Adjust when collapsing the menu, changing the columns, changing the body class.
 
829
                        /*
 
830
                         * Adjust when collapsing the menu, changing the columns
 
831
                         * or changing the body class.
 
832
                         */
610
833
                        $document.on( 'wp-collapse-menu.editor-expand postboxes-columnchange.editor-expand editor-classchange.editor-expand', adjust )
611
834
                                .on( 'postbox-toggled.editor-expand postbox-moved.editor-expand', function() {
612
835
                                        if ( ! fixedSideTop && ! fixedSideBottom && window.pageYOffset > pinnedToolsTop ) {
628
851
                        $textEditor.on( 'focus.editor-expand input.editor-expand propertychange.editor-expand', textEditorResize );
629
852
                        mceBind();
630
853
 
631
 
                        // Adjust when entering/exiting fullscreen mode.
 
854
                        // Adjust when entering or exiting fullscreen mode.
632
855
                        fullscreen && fullscreen.pubsub.subscribe( 'hidden', fullscreenHide );
633
856
 
634
857
                        if ( mceEditor ) {
649
872
                        $document.trigger( 'editor-expand-on' );
650
873
                }
651
874
 
 
875
                /**
 
876
                 * @summary Unbinds editor expand events.
 
877
                 *
 
878
                 * @since 4.0.0
 
879
                 *
 
880
                 * @returns {void}
 
881
                 */
652
882
                function off() {
653
883
                        var height = parseInt( window.getUserSetting( 'ed_size', 300 ), 10 );
654
884
 
658
888
                                height = 5000;
659
889
                        }
660
890
 
661
 
                        // Scroll to the top when triggering this from JS.
662
 
                        // Ensures toolbars are reset properly.
 
891
                        /*
 
892
                         * Scroll to the top when triggering this from JS.
 
893
                         * Ensure the toolbars are reset properly.
 
894
                         */
663
895
                        if ( window.pageYOffset && window.pageYOffset > pageYOffsetAtTop ) {
664
896
                                window.scrollTo( window.pageXOffset, 0 );
665
897
                        }
671
903
                        $textEditor.off( '.editor-expand' );
672
904
                        mceUnbind();
673
905
 
674
 
                        // Adjust when entering/exiting fullscreen mode.
 
906
                        // Adjust when entering or exiting fullscreen mode.
675
907
                        fullscreen && fullscreen.pubsub.unsubscribe( 'hidden', fullscreenHide );
676
908
 
677
909
                        // Reset all css
694
926
                                }
695
927
                        }
696
928
 
 
929
                        // If there is a height found in the user setting.
697
930
                        if ( height ) {
698
931
                                $textEditor.height( height );
699
932
                        }
701
934
                        $document.trigger( 'editor-expand-off' );
702
935
                }
703
936
 
704
 
                // Start on load
 
937
                // Start on load.
705
938
                if ( $wrap.hasClass( 'wp-editor-expand' ) ) {
706
939
                        on();
707
940
 
708
 
                        // Ideally we need to resize just after CSS has fully loaded and QuickTags is ready.
 
941
                        // Resize just after CSS has fully loaded and QuickTags is ready.
709
942
                        if ( $contentWrap.hasClass( 'html-active' ) ) {
710
943
                                initialResize( function() {
711
944
                                        adjust();
714
947
                        }
715
948
                }
716
949
 
717
 
                // Show the on/off checkbox
 
950
                // Show the on/off checkbox.
718
951
                $( '#adv-settings .editor-expand' ).show();
719
952
                $( '#editor-expand-toggle' ).on( 'change.editor-expand', function() {
720
953
                        if ( $(this).prop( 'checked' ) ) {
726
959
                        }
727
960
                });
728
961
 
729
 
                // Expose on() and off()
 
962
                // Expose on() and off().
730
963
                window.editorExpand = {
731
964
                        on: on,
732
965
                        off: off
733
966
                };
734
967
        } );
735
968
 
736
 
        /* DFW. */
 
969
        /**
 
970
         * @summary Handles the distraction free writing of TinyMCE.
 
971
         *
 
972
         * @since 4.1.0
 
973
         *
 
974
         * @returns {void}
 
975
         */
737
976
        $( function() {
738
977
                var $body = $( document.body ),
739
978
                        $wrap = $( '#wpcontent' ),
777
1016
                        mouseY = event.pageY;
778
1017
                } );
779
1018
 
 
1019
                /**
 
1020
                 * @summary Recalculates the bottom and right position of the editor in the DOM.
 
1021
                 *
 
1022
                 * @since 4.1.0
 
1023
                 *
 
1024
                 * @returns {void}
 
1025
                 */
780
1026
                function recalcEditorRect() {
781
1027
                        editorRect = $editor.offset();
782
1028
                        editorRect.right = editorRect.left + $editor.outerWidth();
783
1029
                        editorRect.bottom = editorRect.top + $editor.outerHeight();
784
1030
                }
785
1031
 
 
1032
                /**
 
1033
                 * @summary Activates the distraction free writing mode.
 
1034
                 *
 
1035
                 * @since 4.1.0
 
1036
                 *
 
1037
                 * @returns {void}
 
1038
                 */
786
1039
                function activate() {
787
1040
                        if ( ! _isActive ) {
788
1041
                                _isActive = true;
792
1045
                        }
793
1046
                }
794
1047
 
 
1048
                /**
 
1049
                 * @summary Deactivates the distraction free writing mode.
 
1050
                 *
 
1051
                 * @since 4.1.0
 
1052
                 *
 
1053
                 * @returns {void}
 
1054
                 */
795
1055
                function deactivate() {
796
1056
                        if ( _isActive ) {
797
1057
                                off();
803
1063
                        }
804
1064
                }
805
1065
 
 
1066
                /**
 
1067
                 * @summary Returns _isActive.
 
1068
                 *
 
1069
                 * @since 4.1.0
 
1070
                 *
 
1071
                 * @returns {boolean} Returns true is _isActive is true.
 
1072
                 */
806
1073
                function isActive() {
807
1074
                        return _isActive;
808
1075
                }
809
1076
 
 
1077
                /**
 
1078
                 * @summary Binds events on the editor for distraction free writing.
 
1079
                 *
 
1080
                 * @since 4.1.0
 
1081
                 *
 
1082
                 * @returns {void}
 
1083
                 */
810
1084
                function on() {
811
1085
                        if ( ! _isOn && _isActive ) {
812
1086
                                _isOn = true;
823
1097
                        }
824
1098
                }
825
1099
 
 
1100
                /**
 
1101
                 * @summary Unbinds events on the editor for distraction free writing.
 
1102
                 *
 
1103
                 * @since 4.1.0
 
1104
                 *
 
1105
                 * @returns {void}
 
1106
                 */
826
1107
                function off() {
827
1108
                        if ( _isOn ) {
828
1109
                                _isOn = false;
839
1120
                        }
840
1121
                }
841
1122
 
 
1123
                /**
 
1124
                 * @summary Binds or unbinds the editor expand events.
 
1125
                 *
 
1126
                 * @since 4.1.0
 
1127
                 *
 
1128
                 * @returns {void}
 
1129
                 */
842
1130
                function toggle() {
843
1131
                        if ( _isOn ) {
844
1132
                                off();
847
1135
                        }
848
1136
                }
849
1137
 
 
1138
                /**
 
1139
                 * @summary Returns the value of _isOn.
 
1140
                 *
 
1141
                 * @since 4.1.0
 
1142
                 *
 
1143
                 * @returns {boolean} Returns true if _isOn is true.
 
1144
                 */
850
1145
                function isOn() {
851
1146
                        return _isOn;
852
1147
                }
853
1148
 
 
1149
                /**
 
1150
                 * @summary Fades out all elements except for the editor.
 
1151
                 *
 
1152
                 * The fading is done based on key presses and mouse movements.
 
1153
                 * Also calls the fadeIn on certain key presses
 
1154
                 * or if the mouse leaves the editor.
 
1155
                 *
 
1156
                 * @since 4.1.0
 
1157
                 *
 
1158
                 * @param event The event that triggers this function.
 
1159
                 *
 
1160
                 * @returns {void}
 
1161
                 */
854
1162
                function fadeOut( event ) {
855
1163
                        var isMac,
856
1164
                                key = event && event.keyCode;
859
1167
                                isMac = ( window.navigator.platform.indexOf( 'Mac' ) > -1 );
860
1168
                        }
861
1169
 
862
 
                        // fadeIn and return on Escape and keyboard shortcut Alt+Shift+W and Ctrl+Opt+W.
 
1170
                        // Fade in and returns on Escape and keyboard shortcut Alt+Shift+W and Ctrl+Opt+W.
863
1171
                        if ( key === 27 || ( key === 87 && event.altKey && ( ( ! isMac && event.shiftKey ) || ( isMac && event.ctrlKey ) ) ) ) {
864
1172
                                fadeIn( event );
865
1173
                                return;
866
1174
                        }
867
1175
 
 
1176
                        // Return if any of the following keys or combinations of keys is pressed.
868
1177
                        if ( event && ( event.metaKey || ( event.ctrlKey && ! event.altKey ) || ( event.altKey && event.shiftKey ) || ( key && (
869
1178
                                // Special keys ( tab, ctrl, alt, esc, arrow keys... )
870
1179
                                ( key <= 47 && key !== 8 && key !== 13 && key !== 32 && key !== 46 ) ||
892
1201
                                $editor.css( 'z-index', 9998 );
893
1202
 
894
1203
                                $overlay
895
 
                                        // Always recalculate the editor area entering the overlay with the mouse.
 
1204
                                        // Always recalculate the editor area when entering the overlay with the mouse.
896
1205
                                        .on( 'mouseenter.focus', function() {
897
1206
                                                recalcEditorRect();
898
1207
 
959
1268
                                                x = nx;
960
1269
                                                y = ny;
961
1270
                                        } )
962
 
                                        // When the overlay is touched, always fade in and cancel the event.
 
1271
 
 
1272
                                        // When the overlay is touched, fade in and cancel the event.
963
1273
                                        .on( 'touchstart.focus', function( event ) {
964
1274
                                                event.preventDefault();
965
1275
                                                fadeIn();
979
1289
                        fadeOutSlug();
980
1290
                }
981
1291
 
 
1292
                /**
 
1293
                 * @summary Fades all elements back in.
 
1294
                 *
 
1295
                 * @since 4.1.0
 
1296
                 *
 
1297
                 * @param event The event that triggers this function.
 
1298
                 *
 
1299
                 * @returns {void}
 
1300
                 */
982
1301
                function fadeIn( event ) {
983
1302
                        if ( faded ) {
984
1303
                                faded = false;
1018
1337
                        fadeInSlug();
1019
1338
                }
1020
1339
 
 
1340
                /**
 
1341
                 * @summary Fades in if the focused element based on it position.
 
1342
                 *
 
1343
                 * @since 4.1.0
 
1344
                 *
 
1345
                 * @returns {void}
 
1346
                 */
1021
1347
                function maybeFadeIn() {
1022
1348
                        setTimeout( function() {
1023
1349
                                var position = document.activeElement.compareDocumentPosition( $editor.get( 0 ) );
1033
1359
                        }, 0 );
1034
1360
                }
1035
1361
 
 
1362
                /**
 
1363
                 * @summary Fades out the admin bar based on focus on the admin bar.
 
1364
                 *
 
1365
                 * @since 4.1.0
 
1366
                 *
 
1367
                 * @returns {void}
 
1368
                 */
1036
1369
                function fadeOutAdminBar() {
1037
1370
                        if ( ! fadedAdminBar && faded ) {
1038
1371
                                fadedAdminBar = true;
1047
1380
                        }
1048
1381
                }
1049
1382
 
 
1383
                /**
 
1384
                 * @summary Fades in the admin bar.
 
1385
                 *
 
1386
                 * @since 4.1.0
 
1387
                 *
 
1388
                 * @returns {void}
 
1389
                 */
1050
1390
                function fadeInAdminBar() {
1051
1391
                        if ( fadedAdminBar ) {
1052
1392
                                fadedAdminBar = false;
1055
1395
                        }
1056
1396
                }
1057
1397
 
 
1398
                /**
 
1399
                 * @summary Fades out the edit slug box.
 
1400
                 *
 
1401
                 * @since 4.1.0
 
1402
                 *
 
1403
                 * @returns {void}
 
1404
                 */
1058
1405
                function fadeOutSlug() {
1059
1406
                        if ( ! fadedSlug && faded && ! $slug.find( ':focus').length ) {
1060
1407
                                fadedSlug = true;
1065
1412
                        }
1066
1413
                }
1067
1414
 
 
1415
                /**
 
1416
                 * @summary Fades in the edit slug box.
 
1417
                 *
 
1418
                 * @since 4.1.0
 
1419
                 *
 
1420
                 * @returns {void}
 
1421
                 */
1068
1422
                function fadeInSlug() {
1069
1423
                        if ( fadedSlug ) {
1070
1424
                                fadedSlug = false;
1075
1429
                        }
1076
1430
                }
1077
1431
 
 
1432
                /**
 
1433
                 * @summary Triggers the toggle on Alt + Shift + W.
 
1434
                 *
 
1435
                 * Keycode 87 = w.
 
1436
                 *
 
1437
                 * @since 4.1.0
 
1438
                 *
 
1439
                 * @param {event} event The event to trigger the toggle.
 
1440
                 *
 
1441
                 * @returns {void}
 
1442
                 */
1078
1443
                function toggleViaKeyboard( event ) {
1079
1444
                        if ( event.altKey && event.shiftKey && 87 === event.keyCode ) {
1080
1445
                                toggle();
1085
1450
                        $content.on( 'keydown.focus-shortcut', toggleViaKeyboard );
1086
1451
                }
1087
1452
 
 
1453
                /**
 
1454
                 * @summary Adds the distraction free writing button when setting up TinyMCE.
 
1455
                 *
 
1456
                 * @since 4.1.0
 
1457
                 *
 
1458
                 * @param {event} event The TinyMCE editor setup event.
 
1459
                 * @param {object} editor The editor to add the button to.
 
1460
                 *
 
1461
                 * @returns {void}
 
1462
                 */
1088
1463
                $document.on( 'tinymce-editor-setup.focus', function( event, editor ) {
1089
1464
                        editor.addButton( 'dfw', {
1090
1465
                                active: _isOn,
1116
1491
                        editor.addShortcut( 'access+w', '', 'wpToggleDFW' );
1117
1492
                } );
1118
1493
 
 
1494
                /**
 
1495
                 * @summary Binds and unbinds events on the editor.
 
1496
                 *
 
1497
                 * @since 4.1.0
 
1498
                 *
 
1499
                 * @param {event} event The TinyMCE editor init event.
 
1500
                 * @param {object} editor The editor to bind events on.
 
1501
                 *
 
1502
                 * @returns {void}
 
1503
                 */
1119
1504
                $document.on( 'tinymce-editor-init.focus', function( event, editor ) {
1120
1505
                        var mceBind, mceUnbind;
1121
1506
 
1151
1536
                                        mceBind();
1152
1537
                                }
1153
1538
 
 
1539
                                // Bind and unbind based on the distraction free writing focus.
1154
1540
                                $document.on( 'dfw-on.focus', mceBind ).on( 'dfw-off.focus', mceUnbind );
1155
1541
 
1156
 
                                // Make sure the body focuses when clicking outside it.
 
1542
                                // Focuse the editor when it is the target of the click event.
1157
1543
                                editor.on( 'click', function( event ) {
1158
1544
                                        if ( event.target === editor.getDoc().documentElement ) {
1159
1545
                                                editor.focus();
1162
1548
                        }
1163
1549
                } );
1164
1550
 
 
1551
                /**
 
1552
                 * @summary  Binds events on quicktags init.
 
1553
                 *
 
1554
                 * @since 4.1.0
 
1555
                 *
 
1556
                 * @param {event} event The quicktags init event.
 
1557
                 * @param {object} editor The editor to bind events on.
 
1558
                 *
 
1559
                 * @returns {void}
 
1560
                 */
1165
1561
                $document.on( 'quicktags-init', function( event, editor ) {
1166
1562
                        var $button;
1167
1563
 
 
1564
                        // Bind the distraction free writing events if the distraction free writing button is available.
1168
1565
                        if ( editor.settings.buttons && ( ',' + editor.settings.buttons + ',' ).indexOf( ',dfw,' ) !== -1 ) {
1169
1566
                                $button = $( '#' + editor.name + '_dfw' );
1170
1567