~canonical-sysadmins/wordpress/4.7

« back to all changes in this revision

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

  • Committer: Nick Moffitt
  • Date: 2015-01-15 11:04:26 UTC
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: nick.moffitt@canonical.com-20150115110426-5stm1p14cfnxrtme
New Upstream Version 4.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* global tinymce */
2
 
 
3
 
window.wp = window.wp || {};
4
 
 
5
 
jQuery( document ).ready( function( $ ) {
 
1
( function( window, $, undefined ) {
 
2
        'use strict';
 
3
 
6
4
        var $window = $( window ),
7
5
                $document = $( document ),
8
6
                $adminBar = $( '#wpadminbar' ),
9
 
                $footer = $( '#wpfooter' ),
10
 
                $wrap = $( '#postdivrich' ),
11
 
                $contentWrap = $( '#wp-content-wrap' ),
12
 
                $tools = $( '#wp-content-editor-tools' ),
13
 
                $visualTop = $(),
14
 
                $visualEditor = $(),
15
 
                $textTop = $( '#ed_toolbar' ),
16
 
                $textEditor = $( '#content' ),
17
 
                $textEditorClone = $( '<div id="content-textarea-clone"></div>' ),
18
 
                $bottom = $( '#post-status-info' ),
19
 
                $menuBar = $(),
20
 
                $statusBar = $(),
21
 
                $sideSortables = $( '#side-sortables' ),
22
 
                $postboxContainer = $( '#postbox-container-1' ),
23
 
                $postBody = $('#post-body'),
24
 
                fullscreen = window.wp.editor && window.wp.editor.fullscreen,
25
 
                mceEditor,
26
 
                mceBind = function(){},
27
 
                mceUnbind = function(){},
28
 
                fixedTop = false,
29
 
                fixedBottom = false,
30
 
                fixedSideTop = false,
31
 
                fixedSideBottom = false,
32
 
                scrollTimer,
33
 
                lastScrollPosition = 0,
34
 
                pageYOffsetAtTop = 130,
35
 
                pinnedToolsTop = 56,
36
 
                sidebarBottom = 20,
37
 
                autoresizeMinHeight = 300,
38
 
                initialMode = window.getUserSetting( 'editor' ),
39
 
                // These are corrected when adjust() runs, except on scrolling if already set.
40
 
                heights = {
41
 
                        windowHeight: 0,
42
 
                        windowWidth: 0,
43
 
                        adminBarHeight: 0,
44
 
                        toolsHeight: 0,
45
 
                        menuBarHeight: 0,
46
 
                        visualTopHeight: 0,
47
 
                        textTopHeight: 0,
48
 
                        bottomHeight: 0,
49
 
                        statusBarHeight: 0,
50
 
                        sideSortablesHeight: 0
51
 
                };
52
 
 
53
 
        $textEditorClone.insertAfter( $textEditor );
54
 
 
55
 
        $textEditorClone.css( {
56
 
                'font-family': $textEditor.css( 'font-family' ),
57
 
                'font-size': $textEditor.css( 'font-size' ),
58
 
                'line-height': $textEditor.css( 'line-height' ),
59
 
                'white-space': 'pre-wrap',
60
 
                'word-wrap': 'break-word'
61
 
        } );
62
 
 
63
 
        function getHeights() {
64
 
                var windowWidth = $window.width();
65
 
 
66
 
                heights = {
67
 
                        windowHeight: $window.height(),
68
 
                        windowWidth: windowWidth,
69
 
                        adminBarHeight: ( windowWidth > 600 ? $adminBar.outerHeight() : 0 ),
70
 
                        toolsHeight: $tools.outerHeight() || 0,
71
 
                        menuBarHeight: $menuBar.outerHeight() || 0,
72
 
                        visualTopHeight: $visualTop.outerHeight() || 0,
73
 
                        textTopHeight: $textTop.outerHeight() || 0,
74
 
                        bottomHeight: $bottom.outerHeight() || 0,
75
 
                        statusBarHeight: $statusBar.outerHeight() || 0,
76
 
                        sideSortablesHeight: $sideSortables.height() || 0
77
 
                };
78
 
 
79
 
                // Adjust for hidden
80
 
                if ( heights.menuBarHeight < 3 ) {
81
 
                        heights.menuBarHeight = 0;
82
 
                }
83
 
        }
84
 
 
85
 
        function textEditorKeyup( event ) {
86
 
                var VK = jQuery.ui.keyCode,
87
 
                        key = event.keyCode,
88
 
                        range = document.createRange(),
89
 
                        selStart = $textEditor[0].selectionStart,
90
 
                        selEnd = $textEditor[0].selectionEnd,
91
 
                        textNode = $textEditorClone[0].firstChild,
92
 
                        buffer = 10,
93
 
                        offset, cursorTop, cursorBottom, editorTop, editorBottom;
94
 
 
95
 
                if ( selStart && selEnd && selStart !== selEnd ) {
96
 
                        return;
97
 
                }
98
 
 
99
 
                // These are not TinyMCE ranges.
100
 
                try {
101
 
                        range.setStart( textNode, selStart );
102
 
                        range.setEnd( textNode, selEnd + 1 );
103
 
                } catch ( ex ) {}
104
 
 
105
 
                offset = range.getBoundingClientRect();
106
 
 
107
 
                if ( ! offset.height ) {
108
 
                        return;
109
 
                }
110
 
 
111
 
                cursorTop = offset.top - buffer;
112
 
                cursorBottom = cursorTop + offset.height + buffer;
113
 
                editorTop = heights.adminBarHeight + heights.toolsHeight + heights.textTopHeight;
114
 
                editorBottom = heights.windowHeight - heights.bottomHeight;
115
 
 
116
 
                if ( cursorTop < editorTop && ( key === VK.UP || key === VK.LEFT || key === VK.BACKSPACE ) ) {
117
 
                        window.scrollTo( window.pageXOffset, cursorTop + window.pageYOffset - editorTop );
118
 
                } else if ( cursorBottom > editorBottom ) {
119
 
                        window.scrollTo( window.pageXOffset, cursorBottom + window.pageYOffset - editorBottom );
120
 
                }
121
 
        }
122
 
 
123
 
        function textEditorResize() {
124
 
                if ( ( mceEditor && ! mceEditor.isHidden() ) || ( ! mceEditor && initialMode === 'tinymce' ) ) {
125
 
                        return;
126
 
                }
127
 
 
128
 
                var textEditorHeight = $textEditor.height(),
129
 
                        hiddenHeight;
130
 
 
131
 
                $textEditorClone.width( $textEditor.width() - 22 );
132
 
                $textEditorClone.text( $textEditor.val() + '&nbsp;' );
133
 
 
134
 
                hiddenHeight = $textEditorClone.height();
135
 
 
136
 
                if ( hiddenHeight < autoresizeMinHeight ) {
137
 
                        hiddenHeight = autoresizeMinHeight;
138
 
                }
139
 
 
140
 
                if ( hiddenHeight === textEditorHeight ) {
141
 
                        return;
142
 
                }
143
 
 
144
 
                $textEditor.height( hiddenHeight );
145
 
 
146
 
                adjust();
147
 
        }
148
 
 
149
 
        // We need to wait for TinyMCE to initialize.
150
 
        $document.on( 'tinymce-editor-init.editor-expand', function( event, editor ) {
151
 
                var hideFloatPanels = _.debounce( function() {
152
 
                        ! $( '.mce-floatpanel:hover' ).length && tinymce.ui.FloatPanel.hideAll();
153
 
                        $( '.mce-tooltip' ).hide();
154
 
                }, 1000, true );
155
 
 
156
 
                // Make sure it's the main editor.
157
 
                if ( editor.id !== 'content' ) {
158
 
                        return;
159
 
                }
160
 
 
161
 
                // Copy the editor instance.
162
 
                mceEditor = editor;
163
 
 
164
 
                // Set the minimum height to the initial viewport height.
165
 
                editor.settings.autoresize_min_height = autoresizeMinHeight;
166
 
 
167
 
                // Get the necessary UI elements.
168
 
                $visualTop = $contentWrap.find( '.mce-toolbar-grp' );
169
 
                $visualEditor = $contentWrap.find( '.mce-edit-area' );
170
 
                $statusBar = $contentWrap.find( '.mce-statusbar' );
171
 
                $menuBar = $contentWrap.find( '.mce-menubar' );
172
 
 
173
 
                function mceGetCursorOffset() {
174
 
                        var node = editor.selection.getNode(),
175
 
                                view, offset;
176
 
 
177
 
                        if ( editor.plugins.wpview && ( view = editor.plugins.wpview.getView( node ) ) ) {
178
 
                                offset = view.getBoundingClientRect();
179
 
                        } else {
180
 
                                offset = node.getBoundingClientRect();
 
7
                $footer = $( '#wpfooter' );
 
8
 
 
9
        /* Autoresize editor. */
 
10
        $( function() {
 
11
                var $wrap = $( '#postdivrich' ),
 
12
                        $contentWrap = $( '#wp-content-wrap' ),
 
13
                        $tools = $( '#wp-content-editor-tools' ),
 
14
                        $visualTop = $(),
 
15
                        $visualEditor = $(),
 
16
                        $textTop = $( '#ed_toolbar' ),
 
17
                        $textEditor = $( '#content' ),
 
18
                        $textEditorClone = $( '<div id="content-textarea-clone"></div>' ),
 
19
                        $bottom = $( '#post-status-info' ),
 
20
                        $menuBar = $(),
 
21
                        $statusBar = $(),
 
22
                        $sideSortables = $( '#side-sortables' ),
 
23
                        $postboxContainer = $( '#postbox-container-1' ),
 
24
                        $postBody = $('#post-body'),
 
25
                        fullscreen = window.wp.editor && window.wp.editor.fullscreen,
 
26
                        mceEditor,
 
27
                        mceBind = function(){},
 
28
                        mceUnbind = function(){},
 
29
                        fixedTop = false,
 
30
                        fixedBottom = false,
 
31
                        fixedSideTop = false,
 
32
                        fixedSideBottom = false,
 
33
                        scrollTimer,
 
34
                        lastScrollPosition = 0,
 
35
                        pageYOffsetAtTop = 130,
 
36
                        pinnedToolsTop = 56,
 
37
                        sidebarBottom = 20,
 
38
                        autoresizeMinHeight = 300,
 
39
                        initialMode = $contentWrap.hasClass( 'tmce-active' ) ? 'tinymce' : 'html',
 
40
                        advanced = !! parseInt( window.getUserSetting( 'hidetb' ), 10 ),
 
41
                        // These are corrected when adjust() runs, except on scrolling if already set.
 
42
                        heights = {
 
43
                                windowHeight: 0,
 
44
                                windowWidth: 0,
 
45
                                adminBarHeight: 0,
 
46
                                toolsHeight: 0,
 
47
                                menuBarHeight: 0,
 
48
                                visualTopHeight: 0,
 
49
                                textTopHeight: 0,
 
50
                                bottomHeight: 0,
 
51
                                statusBarHeight: 0,
 
52
                                sideSortablesHeight: 0
 
53
                        };
 
54
 
 
55
                $textEditorClone.insertAfter( $textEditor );
 
56
 
 
57
                $textEditorClone.css( {
 
58
                        'font-family': $textEditor.css( 'font-family' ),
 
59
                        'font-size': $textEditor.css( 'font-size' ),
 
60
                        'line-height': $textEditor.css( 'line-height' ),
 
61
                        'white-space': 'pre-wrap',
 
62
                        'word-wrap': 'break-word'
 
63
                } );
 
64
 
 
65
                function getHeights() {
 
66
                        var windowWidth = $window.width();
 
67
 
 
68
                        heights = {
 
69
                                windowHeight: $window.height(),
 
70
                                windowWidth: windowWidth,
 
71
                                adminBarHeight: ( windowWidth > 600 ? $adminBar.outerHeight() : 0 ),
 
72
                                toolsHeight: $tools.outerHeight() || 0,
 
73
                                menuBarHeight: $menuBar.outerHeight() || 0,
 
74
                                visualTopHeight: $visualTop.outerHeight() || 0,
 
75
                                textTopHeight: $textTop.outerHeight() || 0,
 
76
                                bottomHeight: $bottom.outerHeight() || 0,
 
77
                                statusBarHeight: $statusBar.outerHeight() || 0,
 
78
                                sideSortablesHeight: $sideSortables.height() || 0
 
79
                        };
 
80
 
 
81
                        // Adjust for hidden
 
82
                        if ( heights.menuBarHeight < 3 ) {
 
83
                                heights.menuBarHeight = 0;
181
84
                        }
182
 
 
183
 
                        return offset.height ? offset : false;
184
85
                }
185
86
 
186
 
                // Make sure the cursor is always visible.
187
 
                // This is not only necessary to keep the cursor between the toolbars,
188
 
                // but also to scroll the window when the cursor moves out of the viewport to a wpview.
189
 
                // Setting a buffer > 0 will prevent the browser default.
190
 
                // Some browsers will scroll to the middle,
191
 
                // others to the top/bottom of the *window* when moving the cursor out of the viewport.
192
 
                function mceKeyup( event ) {
193
 
                        var VK = tinymce.util.VK,
 
87
                function textEditorKeyup( event ) {
 
88
                        var VK = jQuery.ui.keyCode,
194
89
                                key = event.keyCode,
195
 
                                offset = mceGetCursorOffset(),
 
90
                                range = document.createRange(),
 
91
                                selStart = $textEditor[0].selectionStart,
 
92
                                selEnd = $textEditor[0].selectionEnd,
 
93
                                textNode = $textEditorClone[0].firstChild,
196
94
                                buffer = 10,
197
 
                                cursorTop, cursorBottom, editorTop, editorBottom;
198
 
 
199
 
                        if ( ! offset ) {
200
 
                                return;
201
 
                        }
202
 
 
203
 
                        // Bail on special keys.
204
 
                        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 ) ) {
205
 
                                return;
206
 
                        // OS keys, function keys, num lock, scroll lock
207
 
                        } else if ( ( key >= 91 && key <= 93 ) || ( key >= 112 && key <= 123 ) || key === 144 || key === 145 ) {
208
 
                                return;
209
 
                        }
210
 
 
211
 
                        cursorTop = offset.top + editor.iframeElement.getBoundingClientRect().top;
212
 
                        cursorBottom = cursorTop + offset.height;
213
 
                        cursorTop = cursorTop - buffer;
214
 
                        cursorBottom = cursorBottom + buffer;
215
 
                        editorTop = heights.adminBarHeight + heights.toolsHeight + heights.menuBarHeight + heights.visualTopHeight;
216
 
                        editorBottom = heights.windowHeight - heights.bottomHeight - heights.statusBarHeight;
217
 
 
218
 
                        // Don't scroll if the node is taller than the visible part of the editor
219
 
                        if ( editorBottom - editorTop < offset.height ) {
220
 
                                return;
221
 
                        }
 
95
                                offset, cursorTop, cursorBottom, editorTop, editorBottom;
 
96
 
 
97
                        if ( selStart && selEnd && selStart !== selEnd ) {
 
98
                                return;
 
99
                        }
 
100
 
 
101
                        // These are not TinyMCE ranges.
 
102
                        try {
 
103
                                range.setStart( textNode, selStart );
 
104
                                range.setEnd( textNode, selEnd + 1 );
 
105
                        } catch ( ex ) {}
 
106
 
 
107
                        offset = range.getBoundingClientRect();
 
108
 
 
109
                        if ( ! offset.height ) {
 
110
                                return;
 
111
                        }
 
112
 
 
113
                        cursorTop = offset.top - buffer;
 
114
                        cursorBottom = cursorTop + offset.height + buffer;
 
115
                        editorTop = heights.adminBarHeight + heights.toolsHeight + heights.textTopHeight;
 
116
                        editorBottom = heights.windowHeight - heights.bottomHeight;
222
117
 
223
118
                        if ( cursorTop < editorTop && ( key === VK.UP || key === VK.LEFT || key === VK.BACKSPACE ) ) {
224
119
                                window.scrollTo( window.pageXOffset, cursorTop + window.pageYOffset - editorTop );
227
122
                        }
228
123
                }
229
124
 
230
 
                // Adjust when switching editor modes.
231
 
                function mceShow() {
232
 
                        $window.on( 'scroll.mce-float-panels', hideFloatPanels );
233
 
 
234
 
                        setTimeout( function() {
235
 
                                editor.execCommand( 'wpAutoResize' );
 
125
                function textEditorResize() {
 
126
                        if ( ( mceEditor && ! mceEditor.isHidden() ) || ( ! mceEditor && initialMode === 'tinymce' ) ) {
 
127
                                return;
 
128
                        }
 
129
 
 
130
                        var textEditorHeight = $textEditor.height(),
 
131
                                hiddenHeight;
 
132
 
 
133
                        $textEditorClone.width( $textEditor.width() - 22 );
 
134
                        $textEditorClone.text( $textEditor.val() + '&nbsp;' );
 
135
 
 
136
                        hiddenHeight = $textEditorClone.height();
 
137
 
 
138
                        if ( hiddenHeight < autoresizeMinHeight ) {
 
139
                                hiddenHeight = autoresizeMinHeight;
 
140
                        }
 
141
 
 
142
                        if ( hiddenHeight === textEditorHeight ) {
 
143
                                return;
 
144
                        }
 
145
 
 
146
                        $textEditor.height( hiddenHeight );
 
147
 
 
148
                        adjust();
 
149
                }
 
150
 
 
151
                // We need to wait for TinyMCE to initialize.
 
152
                $document.on( 'tinymce-editor-init.editor-expand', function( event, editor ) {
 
153
                        var VK = window.tinymce.util.VK,
 
154
                                hideFloatPanels = _.debounce( function() {
 
155
                                        ! $( '.mce-floatpanel:hover' ).length && window.tinymce.ui.FloatPanel.hideAll();
 
156
                                        $( '.mce-tooltip' ).hide();
 
157
                                }, 1000, true );
 
158
 
 
159
                        // Make sure it's the main editor.
 
160
                        if ( editor.id !== 'content' ) {
 
161
                                return;
 
162
                        }
 
163
 
 
164
                        // Copy the editor instance.
 
165
                        mceEditor = editor;
 
166
 
 
167
                        // Set the minimum height to the initial viewport height.
 
168
                        editor.settings.autoresize_min_height = autoresizeMinHeight;
 
169
 
 
170
                        // Get the necessary UI elements.
 
171
                        $visualTop = $contentWrap.find( '.mce-toolbar-grp' );
 
172
                        $visualEditor = $contentWrap.find( '.mce-edit-area' );
 
173
                        $statusBar = $contentWrap.find( '.mce-statusbar' );
 
174
                        $menuBar = $contentWrap.find( '.mce-menubar' );
 
175
 
 
176
                        function mceGetCursorOffset() {
 
177
                                var node = editor.selection.getNode(),
 
178
                                        range, view, offset;
 
179
 
 
180
                                if ( editor.plugins.wpview && ( view = editor.plugins.wpview.getView( node ) ) ) {
 
181
                                        offset = view.getBoundingClientRect();
 
182
                                } else {
 
183
                                        range = editor.selection.getRng();
 
184
 
 
185
                                        try {
 
186
                                                offset = range.getClientRects()[0];
 
187
                                        } catch( er ) {}
 
188
 
 
189
                                        if ( ! offset ) {
 
190
                                                offset = node.getBoundingClientRect();
 
191
                                        }
 
192
                                }
 
193
 
 
194
                                return offset.height ? offset : false;
 
195
                        }
 
196
 
 
197
                        // Make sure the cursor is always visible.
 
198
                        // This is not only necessary to keep the cursor between the toolbars,
 
199
                        // but also to scroll the window when the cursor moves out of the viewport to a wpview.
 
200
                        // Setting a buffer > 0 will prevent the browser default.
 
201
                        // Some browsers will scroll to the middle,
 
202
                        // others to the top/bottom of the *window* when moving the cursor out of the viewport.
 
203
                        function mceKeyup( event ) {
 
204
                                var key = event.keyCode;
 
205
 
 
206
                                // Bail on special keys.
 
207
                                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 ) ) {
 
208
                                        return;
 
209
                                // OS keys, function keys, num lock, scroll lock
 
210
                                } else if ( ( key >= 91 && key <= 93 ) || ( key >= 112 && key <= 123 ) || key === 144 || key === 145 ) {
 
211
                                        return;
 
212
                                }
 
213
 
 
214
                                mceScroll( key );
 
215
                        }
 
216
 
 
217
                        function mceScroll( key ) {
 
218
                                var offset = mceGetCursorOffset(),
 
219
                                        buffer = 50,
 
220
                                        cursorTop, cursorBottom, editorTop, editorBottom;
 
221
 
 
222
                                if ( ! offset ) {
 
223
                                        return;
 
224
                                }
 
225
 
 
226
                                cursorTop = offset.top + editor.iframeElement.getBoundingClientRect().top;
 
227
                                cursorBottom = cursorTop + offset.height;
 
228
                                cursorTop = cursorTop - buffer;
 
229
                                cursorBottom = cursorBottom + buffer;
 
230
                                editorTop = heights.adminBarHeight + heights.toolsHeight + heights.menuBarHeight + heights.visualTopHeight;
 
231
                                editorBottom = heights.windowHeight - ( advanced ? heights.bottomHeight + heights.statusBarHeight : 0 );
 
232
 
 
233
                                // Don't scroll if the node is taller than the visible part of the editor
 
234
                                if ( editorBottom - editorTop < offset.height ) {
 
235
                                        return;
 
236
                                }
 
237
 
 
238
                                if ( cursorTop < editorTop && ( key === VK.UP || key === VK.LEFT || key === VK.BACKSPACE ) ) {
 
239
                                        window.scrollTo( window.pageXOffset, cursorTop + window.pageYOffset - editorTop );
 
240
                                } else if ( cursorBottom > editorBottom ) {
 
241
                                        window.scrollTo( window.pageXOffset, cursorBottom + window.pageYOffset - editorBottom );
 
242
                                }
 
243
                        }
 
244
 
 
245
                        function mceFullscreenToggled( event ) {
 
246
                                if ( ! event.state ) {
 
247
                                        adjust();
 
248
                                }
 
249
                        }
 
250
 
 
251
                        // Adjust when switching editor modes.
 
252
                        function mceShow() {
 
253
                                $window.on( 'scroll.mce-float-panels', hideFloatPanels );
 
254
 
 
255
                                setTimeout( function() {
 
256
                                        editor.execCommand( 'wpAutoResize' );
 
257
                                        adjust();
 
258
                                }, 300 );
 
259
                        }
 
260
 
 
261
                        function mceHide() {
 
262
                                $window.off( 'scroll.mce-float-panels' );
 
263
 
 
264
                                setTimeout( function() {
 
265
                                        var top = $contentWrap.offset().top;
 
266
 
 
267
                                        if ( window.pageYOffset > top ) {
 
268
                                                window.scrollTo( window.pageXOffset, top - heights.adminBarHeight );
 
269
                                        }
 
270
 
 
271
                                        textEditorResize();
 
272
                                        adjust();
 
273
                                }, 100 );
 
274
 
236
275
                                adjust();
237
 
                        }, 300 );
238
 
                }
239
 
 
240
 
                function mceHide() {
241
 
                        $window.off( 'scroll.mce-float-panels' );
242
 
 
243
 
                        setTimeout( function() {
244
 
                                var top = $contentWrap.offset().top;
245
 
 
246
 
                                if ( window.pageYOffset > top ) {
247
 
                                        window.scrollTo( window.pageXOffset, top - heights.adminBarHeight );
248
 
                                }
249
 
 
 
276
                        }
 
277
 
 
278
                        function toggleAdvanced() {
 
279
                                advanced = ! advanced;
 
280
                        }
 
281
 
 
282
                        mceBind = function() {
 
283
                                editor.on( 'keyup', mceKeyup );
 
284
                                editor.on( 'show', mceShow );
 
285
                                editor.on( 'hide', mceHide );
 
286
                                editor.on( 'wp-toolbar-toggle', toggleAdvanced );
 
287
                                // Adjust when the editor resizes.
 
288
                                editor.on( 'setcontent wp-autoresize wp-toolbar-toggle', adjust );
 
289
                                // Don't hide the caret after undo/redo.
 
290
                                editor.on( 'undo redo', mceScroll );
 
291
                                // Adjust when exiting TinyMCE's fullscreen mode.
 
292
                                editor.on( 'FullscreenStateChanged', mceFullscreenToggled );
 
293
 
 
294
                                $window.off( 'scroll.mce-float-panels' ).on( 'scroll.mce-float-panels', hideFloatPanels );
 
295
                        };
 
296
 
 
297
                        mceUnbind = function() {
 
298
                                editor.off( 'keyup', mceKeyup );
 
299
                                editor.off( 'show', mceShow );
 
300
                                editor.off( 'hide', mceHide );
 
301
                                editor.off( 'wp-toolbar-toggle', toggleAdvanced );
 
302
                                editor.off( 'setcontent wp-autoresize wp-toolbar-toggle', adjust );
 
303
                                editor.off( 'undo redo', mceScroll );
 
304
                                editor.off( 'FullscreenStateChanged', mceFullscreenToggled );
 
305
 
 
306
                                $window.off( 'scroll.mce-float-panels' );
 
307
                        };
 
308
 
 
309
                        if ( $wrap.hasClass( 'wp-editor-expand' ) ) {
 
310
                                // Adjust "immediately"
 
311
                                mceBind();
 
312
                                initialResize( adjust );
 
313
                        }
 
314
                } );
 
315
 
 
316
                // Adjust the toolbars based on the active editor mode.
 
317
                function adjust( event ) {
 
318
                        // Make sure we're not in fullscreen mode.
 
319
                        if ( fullscreen && fullscreen.settings.visible ) {
 
320
                                return;
 
321
                        }
 
322
 
 
323
                        var windowPos = $window.scrollTop(),
 
324
                                type = event && event.type,
 
325
                                resize = type !== 'scroll',
 
326
                                visual = ( mceEditor && ! mceEditor.isHidden() ),
 
327
                                buffer = autoresizeMinHeight,
 
328
                                postBodyTop = $postBody.offset().top,
 
329
                                borderWidth = 1,
 
330
                                contentWrapWidth = $contentWrap.width(),
 
331
                                $top, $editor, sidebarTop, footerTop, canPin,
 
332
                                topPos, topHeight, editorPos, editorHeight;
 
333
 
 
334
                        // Refresh the heights
 
335
                        if ( resize || ! heights.windowHeight ) {
 
336
                                getHeights();
 
337
                        }
 
338
 
 
339
                        if ( ! visual && type === 'resize' ) {
250
340
                                textEditorResize();
251
 
                                adjust();
252
 
                        }, 100 );
253
 
 
254
 
                        adjust();
255
 
                }
256
 
 
257
 
                mceBind = function() {
258
 
                        editor.on( 'keyup', mceKeyup );
259
 
                        editor.on( 'show', mceShow );
260
 
                        editor.on( 'hide', mceHide );
261
 
                        // Adjust when the editor resizes.
262
 
                        editor.on( 'setcontent wp-autoresize wp-toolbar-toggle', adjust );
263
 
 
264
 
                        $window.off( 'scroll.mce-float-panels' ).on( 'scroll.mce-float-panels', hideFloatPanels );
265
 
                };
266
 
 
267
 
                mceUnbind = function() {
268
 
                        editor.off( 'keyup', mceKeyup );
269
 
                        editor.off( 'show', mceShow );
270
 
                        editor.off( 'hide', mceHide );
271
 
                        editor.off( 'setcontent wp-autoresize wp-toolbar-toggle', adjust );
272
 
 
273
 
                        $window.off( 'scroll.mce-float-panels' );
274
 
                };
275
 
 
276
 
                if ( $wrap.hasClass( 'wp-editor-expand' ) ) {
277
 
                        // Adjust "immediately"
278
 
                        mceBind();
279
 
                        initialResize( adjust );
280
 
                }
281
 
        } );
282
 
 
283
 
        // Adjust the toolbars based on the active editor mode.
284
 
        function adjust( type ) {
285
 
                // Make sure we're not in fullscreen mode.
286
 
                if ( fullscreen && fullscreen.settings.visible ) {
287
 
                        return;
288
 
                }
289
 
 
290
 
                var windowPos = $window.scrollTop(),
291
 
                        resize = type !== 'scroll',
292
 
                        visual = ( mceEditor && ! mceEditor.isHidden() ),
293
 
                        buffer = autoresizeMinHeight,
294
 
                        postBodyTop = $postBody.offset().top,
295
 
                        borderWidth = 1,
296
 
                        contentWrapWidth = $contentWrap.width(),
297
 
                        $top, $editor, sidebarTop, footerTop, canPin,
298
 
                        topPos, topHeight, editorPos, editorHeight;
299
 
 
300
 
                // Refresh the heights
301
 
                if ( resize || ! heights.windowHeight ) {
302
 
                        getHeights();
303
 
                }
304
 
 
305
 
                if ( ! visual && type === 'resize' ) {
306
 
                        textEditorResize();
307
 
                }
308
 
 
309
 
                if ( visual ) {
310
 
                        $top = $visualTop;
311
 
                        $editor = $visualEditor;
312
 
                        topHeight = heights.visualTopHeight;
313
 
                } else {
314
 
                        $top = $textTop;
315
 
                        $editor = $textEditor;
316
 
                        topHeight = heights.textTopHeight;
317
 
                }
318
 
 
319
 
                topPos = $top.parent().offset().top;
320
 
                editorPos = $editor.offset().top;
321
 
                editorHeight = $editor.outerHeight();
322
 
 
323
 
                // Should we pin?
324
 
                canPin = visual ? autoresizeMinHeight + topHeight : autoresizeMinHeight + 20; // 20px from textarea padding
325
 
                canPin = editorHeight > ( canPin + 5 );
326
 
 
327
 
                if ( ! canPin ) {
328
 
                        if ( resize ) {
329
 
                                $tools.css( {
330
 
                                        position: 'absolute',
331
 
                                        top: 0,
332
 
                                        width: contentWrapWidth
333
 
                                } );
334
 
 
335
 
                                if ( visual && $menuBar.length ) {
336
 
                                        $menuBar.css( {
337
 
                                                position: 'absolute',
338
 
                                                top: 0,
339
 
                                                width: contentWrapWidth - ( borderWidth * 2 )
340
 
                                        } );
341
 
                                }
342
 
 
343
 
                                $top.css( {
344
 
                                        position: 'absolute',
345
 
                                        top: heights.menuBarHeight,
346
 
                                        width: contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top.outerWidth() - $top.width() ) )
347
 
                                } );
348
 
 
349
 
                                $statusBar.add( $bottom ).attr( 'style', '' );
350
 
                        }
351
 
                } else {
352
 
                        // Maybe pin the top.
353
 
                        if ( ( ! fixedTop || resize ) &&
354
 
                                // Handle scrolling down.
355
 
                                ( windowPos >= ( topPos - heights.toolsHeight - heights.adminBarHeight ) &&
356
 
                                // Handle scrolling up.
357
 
                                windowPos <= ( topPos - heights.toolsHeight - heights.adminBarHeight + editorHeight - buffer ) ) ) {
358
 
                                fixedTop = true;
359
 
 
360
 
                                $tools.css( {
361
 
                                        position: 'fixed',
362
 
                                        top: heights.adminBarHeight,
363
 
                                        width: contentWrapWidth
364
 
                                } );
365
 
 
366
 
                                if ( visual && $menuBar.length ) {
367
 
                                        $menuBar.css( {
368
 
                                                position: 'fixed',
369
 
                                                top: heights.adminBarHeight + heights.toolsHeight,
370
 
                                                width: contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top.outerWidth() - $top.width() ) )
371
 
                                        } );
372
 
                                }
373
 
 
374
 
                                $top.css( {
375
 
                                        position: 'fixed',
376
 
                                        top: heights.adminBarHeight + heights.toolsHeight + heights.menuBarHeight,
377
 
                                        width: contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top.outerWidth() - $top.width() ) )
378
 
                                } );
379
 
                        // Maybe unpin the top.
380
 
                        } else if ( fixedTop || resize ) {
381
 
                                // Handle scrolling up.
382
 
                                if ( windowPos <= ( topPos - heights.toolsHeight - heights.adminBarHeight ) ) {
383
 
                                        fixedTop = false;
384
 
 
 
341
                        }
 
342
 
 
343
                        if ( visual ) {
 
344
                                $top = $visualTop;
 
345
                                $editor = $visualEditor;
 
346
                                topHeight = heights.visualTopHeight;
 
347
                        } else {
 
348
                                $top = $textTop;
 
349
                                $editor = $textEditor;
 
350
                                topHeight = heights.textTopHeight;
 
351
                        }
 
352
 
 
353
                        topPos = $top.parent().offset().top;
 
354
                        editorPos = $editor.offset().top;
 
355
                        editorHeight = $editor.outerHeight();
 
356
 
 
357
                        // Should we pin?
 
358
                        canPin = visual ? autoresizeMinHeight + topHeight : autoresizeMinHeight + 20; // 20px from textarea padding
 
359
                        canPin = editorHeight > ( canPin + 5 );
 
360
 
 
361
                        if ( ! canPin ) {
 
362
                                if ( resize ) {
385
363
                                        $tools.css( {
386
364
                                                position: 'absolute',
387
365
                                                top: 0,
401
379
                                                top: heights.menuBarHeight,
402
380
                                                width: contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top.outerWidth() - $top.width() ) )
403
381
                                        } );
404
 
                                // Handle scrolling down.
405
 
                                } else if ( windowPos >= ( topPos - heights.toolsHeight - heights.adminBarHeight + editorHeight - buffer ) ) {
406
 
                                        fixedTop = false;
 
382
 
 
383
                                        $statusBar.add( $bottom ).attr( 'style', '' );
 
384
                                }
 
385
                        } else {
 
386
                                // Maybe pin the top.
 
387
                                if ( ( ! fixedTop || resize ) &&
 
388
                                        // Handle scrolling down.
 
389
                                        ( windowPos >= ( topPos - heights.toolsHeight - heights.adminBarHeight ) &&
 
390
                                        // Handle scrolling up.
 
391
                                        windowPos <= ( topPos - heights.toolsHeight - heights.adminBarHeight + editorHeight - buffer ) ) ) {
 
392
                                        fixedTop = true;
407
393
 
408
394
                                        $tools.css( {
409
 
                                                position: 'absolute',
410
 
                                                top: editorHeight - buffer,
 
395
                                                position: 'fixed',
 
396
                                                top: heights.adminBarHeight,
411
397
                                                width: contentWrapWidth
412
398
                                        } );
413
399
 
414
400
                                        if ( visual && $menuBar.length ) {
415
401
                                                $menuBar.css( {
 
402
                                                        position: 'fixed',
 
403
                                                        top: heights.adminBarHeight + heights.toolsHeight,
 
404
                                                        width: contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top.outerWidth() - $top.width() ) )
 
405
                                                } );
 
406
                                        }
 
407
 
 
408
                                        $top.css( {
 
409
                                                position: 'fixed',
 
410
                                                top: heights.adminBarHeight + heights.toolsHeight + heights.menuBarHeight,
 
411
                                                width: contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top.outerWidth() - $top.width() ) )
 
412
                                        } );
 
413
                                // Maybe unpin the top.
 
414
                                } else if ( fixedTop || resize ) {
 
415
                                        // Handle scrolling up.
 
416
                                        if ( windowPos <= ( topPos - heights.toolsHeight - heights.adminBarHeight ) ) {
 
417
                                                fixedTop = false;
 
418
 
 
419
                                                $tools.css( {
 
420
                                                        position: 'absolute',
 
421
                                                        top: 0,
 
422
                                                        width: contentWrapWidth
 
423
                                                } );
 
424
 
 
425
                                                if ( visual && $menuBar.length ) {
 
426
                                                        $menuBar.css( {
 
427
                                                                position: 'absolute',
 
428
                                                                top: 0,
 
429
                                                                width: contentWrapWidth - ( borderWidth * 2 )
 
430
                                                        } );
 
431
                                                }
 
432
 
 
433
                                                $top.css( {
 
434
                                                        position: 'absolute',
 
435
                                                        top: heights.menuBarHeight,
 
436
                                                        width: contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top.outerWidth() - $top.width() ) )
 
437
                                                } );
 
438
                                        // Handle scrolling down.
 
439
                                        } else if ( windowPos >= ( topPos - heights.toolsHeight - heights.adminBarHeight + editorHeight - buffer ) ) {
 
440
                                                fixedTop = false;
 
441
 
 
442
                                                $tools.css( {
416
443
                                                        position: 'absolute',
417
444
                                                        top: editorHeight - buffer,
 
445
                                                        width: contentWrapWidth
 
446
                                                } );
 
447
 
 
448
                                                if ( visual && $menuBar.length ) {
 
449
                                                        $menuBar.css( {
 
450
                                                                position: 'absolute',
 
451
                                                                top: editorHeight - buffer,
 
452
                                                                width: contentWrapWidth - ( borderWidth * 2 )
 
453
                                                        } );
 
454
                                                }
 
455
 
 
456
                                                $top.css( {
 
457
                                                        position: 'absolute',
 
458
                                                        top: editorHeight - buffer + heights.menuBarHeight,
 
459
                                                        width: contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top.outerWidth() - $top.width() ) )
 
460
                                                } );
 
461
                                        }
 
462
                                }
 
463
 
 
464
                                // Maybe adjust the bottom bar.
 
465
                                if ( ( ! fixedBottom || ( resize && advanced ) ) &&
 
466
                                                // +[n] for the border around the .wp-editor-container.
 
467
                                                ( windowPos + heights.windowHeight ) <= ( editorPos + editorHeight + heights.bottomHeight + heights.statusBarHeight + borderWidth ) ) {
 
468
 
 
469
                                        if ( event && event.deltaHeight > 0 && event.deltaHeight < 100 ) {
 
470
                                                window.scrollBy( 0, event.deltaHeight );
 
471
                                        } else if ( advanced ) {
 
472
                                                fixedBottom = true;
 
473
 
 
474
                                                $statusBar.css( {
 
475
                                                        position: 'fixed',
 
476
                                                        bottom: heights.bottomHeight,
 
477
                                                        visibility: '',
418
478
                                                        width: contentWrapWidth - ( borderWidth * 2 )
419
479
                                                } );
420
 
                                        }
421
 
 
422
 
                                        $top.css( {
423
 
                                                position: 'absolute',
424
 
                                                top: editorHeight - buffer + heights.menuBarHeight,
425
 
                                                width: contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top.outerWidth() - $top.width() ) )
426
 
                                        } );
 
480
 
 
481
                                                $bottom.css( {
 
482
                                                        position: 'fixed',
 
483
                                                        bottom: 0,
 
484
                                                        width: contentWrapWidth
 
485
                                                } );
 
486
                                        }
 
487
                                } else if ( ( ! advanced && fixedBottom ) ||
 
488
                                                ( ( fixedBottom || resize ) &&
 
489
                                                ( windowPos + heights.windowHeight ) > ( editorPos + editorHeight + heights.bottomHeight + heights.statusBarHeight - borderWidth ) ) ) {
 
490
                                        fixedBottom = false;
 
491
 
 
492
                                        $statusBar.add( $bottom ).attr( 'style', '' );
 
493
 
 
494
                                        if ( ! advanced ) {
 
495
                                                $statusBar.css( 'visibility', 'hidden' );
 
496
                                        }
427
497
                                }
428
498
                        }
429
499
 
430
 
                        // Maybe adjust the bottom bar.
431
 
                        if ( ( ! fixedBottom || resize ) &&
432
 
                                // +[n] for the border around the .wp-editor-container.
433
 
                                ( windowPos + heights.windowHeight ) <= ( editorPos + editorHeight + heights.bottomHeight + heights.statusBarHeight + borderWidth ) ) {
434
 
                                fixedBottom = true;
435
 
 
436
 
                                $statusBar.css( {
437
 
                                        position: 'fixed',
438
 
                                        bottom: heights.bottomHeight,
439
 
                                        width: contentWrapWidth - ( borderWidth * 2 )
440
 
                                } );
441
 
 
442
 
                                $bottom.css( {
443
 
                                        position: 'fixed',
444
 
                                        bottom: 0,
445
 
                                        width: contentWrapWidth
446
 
                                } );
447
 
                        } else if ( ( fixedBottom || resize ) &&
448
 
                                        ( windowPos + heights.windowHeight ) > ( editorPos + editorHeight + heights.bottomHeight + heights.statusBarHeight - borderWidth ) ) {
449
 
                                fixedBottom = false;
450
 
 
451
 
                                $statusBar.add( $bottom ).attr( 'style', '' );
452
 
                        }
453
 
                }
454
 
 
455
 
                // Sidebar pinning
456
 
                if ( $postboxContainer.width() < 300 && heights.windowWidth > 600 && // sidebar position is changed with @media from CSS, make sure it is on the side
457
 
                        $document.height() > ( $sideSortables.height() + postBodyTop + 120 ) && // the sidebar is not the tallest element
458
 
                        heights.windowHeight < editorHeight ) { // the editor is taller than the viewport
459
 
 
460
 
                        if ( ( heights.sideSortablesHeight + pinnedToolsTop + sidebarBottom ) > heights.windowHeight || fixedSideTop || fixedSideBottom ) {
461
 
                                // Reset when scrolling to the top
462
 
                                if ( windowPos + pinnedToolsTop <= postBodyTop ) {
463
 
                                        $sideSortables.attr( 'style', '' );
 
500
                        // Sidebar pinning
 
501
                        if ( $postboxContainer.width() < 300 && heights.windowWidth > 600 && // sidebar position is changed with @media from CSS, make sure it is on the side
 
502
                                $document.height() > ( $sideSortables.height() + postBodyTop + 120 ) && // the sidebar is not the tallest element
 
503
                                heights.windowHeight < editorHeight ) { // the editor is taller than the viewport
 
504
 
 
505
                                if ( ( heights.sideSortablesHeight + pinnedToolsTop + sidebarBottom ) > heights.windowHeight || fixedSideTop || fixedSideBottom ) {
 
506
                                        // Reset when scrolling to the top
 
507
                                        if ( windowPos + pinnedToolsTop <= postBodyTop ) {
 
508
                                                $sideSortables.attr( 'style', '' );
 
509
                                                fixedSideTop = fixedSideBottom = false;
 
510
                                        } else {
 
511
                                                if ( windowPos > lastScrollPosition ) {
 
512
                                                        // Scrolling down
 
513
                                                        if ( fixedSideTop ) {
 
514
                                                                // let it scroll
 
515
                                                                fixedSideTop = false;
 
516
                                                                sidebarTop = $sideSortables.offset().top - heights.adminBarHeight;
 
517
                                                                footerTop = $footer.offset().top;
 
518
 
 
519
                                                                // don't get over the footer
 
520
                                                                if ( footerTop < sidebarTop + heights.sideSortablesHeight + sidebarBottom ) {
 
521
                                                                        sidebarTop = footerTop - heights.sideSortablesHeight - 12;
 
522
                                                                }
 
523
 
 
524
                                                                $sideSortables.css({
 
525
                                                                        position: 'absolute',
 
526
                                                                        top: sidebarTop,
 
527
                                                                        bottom: ''
 
528
                                                                });
 
529
                                                        } else if ( ! fixedSideBottom && heights.sideSortablesHeight + $sideSortables.offset().top + sidebarBottom < windowPos + heights.windowHeight ) {
 
530
                                                                // pin the bottom
 
531
                                                                fixedSideBottom = true;
 
532
 
 
533
                                                                $sideSortables.css({
 
534
                                                                        position: 'fixed',
 
535
                                                                        top: 'auto',
 
536
                                                                        bottom: sidebarBottom
 
537
                                                                });
 
538
                                                        }
 
539
                                                } else if ( windowPos < lastScrollPosition ) {
 
540
                                                        // Scrolling up
 
541
                                                        if ( fixedSideBottom ) {
 
542
                                                                // let it scroll
 
543
                                                                fixedSideBottom = false;
 
544
                                                                sidebarTop = $sideSortables.offset().top - sidebarBottom;
 
545
                                                                footerTop = $footer.offset().top;
 
546
 
 
547
                                                                // don't get over the footer
 
548
                                                                if ( footerTop < sidebarTop + heights.sideSortablesHeight + sidebarBottom ) {
 
549
                                                                        sidebarTop = footerTop - heights.sideSortablesHeight - 12;
 
550
                                                                }
 
551
 
 
552
                                                                $sideSortables.css({
 
553
                                                                        position: 'absolute',
 
554
                                                                        top: sidebarTop,
 
555
                                                                        bottom: ''
 
556
                                                                });
 
557
                                                        } else if ( ! fixedSideTop && $sideSortables.offset().top >= windowPos + pinnedToolsTop ) {
 
558
                                                                // pin the top
 
559
                                                                fixedSideTop = true;
 
560
 
 
561
                                                                $sideSortables.css({
 
562
                                                                        position: 'fixed',
 
563
                                                                        top: pinnedToolsTop,
 
564
                                                                        bottom: ''
 
565
                                                                });
 
566
                                                        }
 
567
                                                }
 
568
                                        }
 
569
                                } else {
 
570
                                        // if the sidebar container is smaller than the viewport, then pin/unpin the top when scrolling
 
571
                                        if ( windowPos >= ( postBodyTop - pinnedToolsTop ) ) {
 
572
 
 
573
                                                $sideSortables.css( {
 
574
                                                        position: 'fixed',
 
575
                                                        top: pinnedToolsTop
 
576
                                                } );
 
577
                                        } else {
 
578
                                                $sideSortables.attr( 'style', '' );
 
579
                                        }
 
580
 
464
581
                                        fixedSideTop = fixedSideBottom = false;
465
 
                                } else {
466
 
                                        if ( windowPos > lastScrollPosition ) {
467
 
                                                // Scrolling down
468
 
                                                if ( fixedSideTop ) {
469
 
                                                        // let it scroll
470
 
                                                        fixedSideTop = false;
471
 
                                                        sidebarTop = $sideSortables.offset().top - heights.adminBarHeight;
472
 
                                                        footerTop = $footer.offset().top;
473
 
 
474
 
                                                        // don't get over the footer
475
 
                                                        if ( footerTop < sidebarTop + heights.sideSortablesHeight + sidebarBottom ) {
476
 
                                                                sidebarTop = footerTop - heights.sideSortablesHeight - 12;
477
 
                                                        }
478
 
 
479
 
                                                        $sideSortables.css({
480
 
                                                                position: 'absolute',
481
 
                                                                top: sidebarTop,
482
 
                                                                bottom: ''
483
 
                                                        });
484
 
                                                } else if ( ! fixedSideBottom && heights.sideSortablesHeight + $sideSortables.offset().top + sidebarBottom < windowPos + heights.windowHeight ) {
485
 
                                                        // pin the bottom
486
 
                                                        fixedSideBottom = true;
487
 
 
488
 
                                                        $sideSortables.css({
489
 
                                                                position: 'fixed',
490
 
                                                                top: 'auto',
491
 
                                                                bottom: sidebarBottom
492
 
                                                        });
493
 
                                                }
494
 
                                        } else if ( windowPos < lastScrollPosition ) {
495
 
                                                // Scrolling up
496
 
                                                if ( fixedSideBottom ) {
497
 
                                                        // let it scroll
498
 
                                                        fixedSideBottom = false;
499
 
                                                        sidebarTop = $sideSortables.offset().top - sidebarBottom;
500
 
                                                        footerTop = $footer.offset().top;
501
 
 
502
 
                                                        // don't get over the footer
503
 
                                                        if ( footerTop < sidebarTop + heights.sideSortablesHeight + sidebarBottom ) {
504
 
                                                                sidebarTop = footerTop - heights.sideSortablesHeight - 12;
505
 
                                                        }
506
 
 
507
 
                                                        $sideSortables.css({
508
 
                                                                position: 'absolute',
509
 
                                                                top: sidebarTop,
510
 
                                                                bottom: ''
511
 
                                                        });
512
 
                                                } else if ( ! fixedSideTop && $sideSortables.offset().top >= windowPos + pinnedToolsTop ) {
513
 
                                                        // pin the top
514
 
                                                        fixedSideTop = true;
515
 
 
516
 
                                                        $sideSortables.css({
517
 
                                                                position: 'fixed',
518
 
                                                                top: pinnedToolsTop,
519
 
                                                                bottom: ''
520
 
                                                        });
521
 
                                                }
522
 
                                        }
523
582
                                }
 
583
 
 
584
                                lastScrollPosition = windowPos;
524
585
                        } else {
525
 
                                // if the sidebar container is smaller than the viewport, then pin/unpin the top when scrolling
526
 
                                if ( windowPos >= ( postBodyTop - pinnedToolsTop ) ) {
527
 
 
528
 
                                        $sideSortables.css( {
529
 
                                                position: 'fixed',
530
 
                                                top: pinnedToolsTop
531
 
                                        } );
532
 
                                } else {
533
 
                                        $sideSortables.attr( 'style', '' );
534
 
                                }
535
 
 
 
586
                                $sideSortables.attr( 'style', '' );
536
587
                                fixedSideTop = fixedSideBottom = false;
537
588
                        }
538
589
 
539
 
                        lastScrollPosition = windowPos;
540
 
                } else {
541
 
                        $sideSortables.attr( 'style', '' );
542
 
                        fixedSideTop = fixedSideBottom = false;
543
 
                }
544
 
 
545
 
                if ( resize ) {
546
 
                        $contentWrap.css( {
547
 
                                paddingTop: heights.toolsHeight
 
590
                        if ( resize ) {
 
591
                                $contentWrap.css( {
 
592
                                        paddingTop: heights.toolsHeight
 
593
                                } );
 
594
 
 
595
                                if ( visual ) {
 
596
                                        $visualEditor.css( {
 
597
                                                paddingTop: heights.visualTopHeight + heights.menuBarHeight
 
598
                                        } );
 
599
                                } else {
 
600
                                        $textEditor.css( {
 
601
                                                marginTop: heights.textTopHeight
 
602
                                        } );
 
603
 
 
604
                                        $textEditorClone.width( contentWrapWidth - 20 - ( borderWidth * 2 ) );
 
605
                                }
 
606
                        }
 
607
                }
 
608
 
 
609
                function fullscreenHide() {
 
610
                        textEditorResize();
 
611
                        adjust();
 
612
                }
 
613
 
 
614
                function initialResize( callback ) {
 
615
                        for ( var i = 1; i < 6; i++ ) {
 
616
                                setTimeout( callback, 500 * i );
 
617
                        }
 
618
                }
 
619
 
 
620
                function afterScroll() {
 
621
                        clearTimeout( scrollTimer );
 
622
                        scrollTimer = setTimeout( adjust, 100 );
 
623
                }
 
624
 
 
625
                function on() {
 
626
                        // Scroll to the top when triggering this from JS.
 
627
                        // Ensures toolbars are pinned properly.
 
628
                        if ( window.pageYOffset && window.pageYOffset > pageYOffsetAtTop ) {
 
629
                                window.scrollTo( window.pageXOffset, 0 );
 
630
                        }
 
631
 
 
632
                        $wrap.addClass( 'wp-editor-expand' );
 
633
 
 
634
                        // Adjust when the window is scrolled or resized.
 
635
                        $window.on( 'scroll.editor-expand resize.editor-expand', function( event ) {
 
636
                                adjust( event.type );
 
637
                                afterScroll();
548
638
                        } );
549
639
 
550
 
                        if ( visual ) {
551
 
                                $visualEditor.css( {
552
 
                                        paddingTop: heights.visualTopHeight + heights.menuBarHeight
553
 
                                } );
554
 
                        } else {
555
 
                                $textEditor.css( {
556
 
                                        marginTop: heights.textTopHeight
557
 
                                } );
558
 
 
559
 
                                $textEditorClone.width( contentWrapWidth - 20 - ( borderWidth * 2 ) );
560
 
                        }
561
 
                }
562
 
        }
563
 
 
564
 
        function fullscreenHide() {
565
 
                textEditorResize();
566
 
                adjust();
567
 
        }
568
 
 
569
 
        function initialResize( callback ) {
570
 
                for ( var i = 1; i < 6; i++ ) {
571
 
                        setTimeout( callback, 500 * i );
572
 
                }
573
 
        }
574
 
 
575
 
        function afterScroll() {
576
 
                clearTimeout( scrollTimer );
577
 
                scrollTimer = setTimeout( adjust, 100 );
578
 
        }
579
 
 
580
 
        function on() {
581
 
                // Scroll to the top when triggering this from JS.
582
 
                // Ensures toolbars are pinned properly.
583
 
                if ( window.pageYOffset && window.pageYOffset > pageYOffsetAtTop ) {
584
 
                        window.scrollTo( window.pageXOffset, 0 );
585
 
                }
586
 
 
587
 
                $wrap.addClass( 'wp-editor-expand' );
588
 
 
589
 
                // Adjust when the window is scrolled or resized.
590
 
                $window.on( 'scroll.editor-expand resize.editor-expand', function( event ) {
591
 
                        adjust( event.type );
592
 
                        afterScroll();
593
 
                } );
594
 
 
595
 
                // Adjust when collapsing the menu, changing the columns, changing the body class.
596
 
                $document.on( 'wp-collapse-menu.editor-expand postboxes-columnchange.editor-expand editor-classchange.editor-expand', adjust )
597
 
                        .on( 'postbox-toggled.editor-expand', function() {
598
 
                                if ( ! fixedSideTop && ! fixedSideBottom && window.pageYOffset > pinnedToolsTop ) {
599
 
                                        fixedSideBottom = true;
600
 
                                        window.scrollBy( 0, -1 );
 
640
                        // Adjust when collapsing the menu, changing the columns, changing the body class.
 
641
                        $document.on( 'wp-collapse-menu.editor-expand postboxes-columnchange.editor-expand editor-classchange.editor-expand', adjust )
 
642
                                .on( 'postbox-toggled.editor-expand', function() {
 
643
                                        if ( ! fixedSideTop && ! fixedSideBottom && window.pageYOffset > pinnedToolsTop ) {
 
644
                                                fixedSideBottom = true;
 
645
                                                window.scrollBy( 0, -1 );
 
646
                                                adjust();
 
647
                                                window.scrollBy( 0, 1 );
 
648
                                        }
 
649
 
601
650
                                        adjust();
602
 
                                        window.scrollBy( 0, 1 );
603
 
                                }
604
 
 
605
 
                                adjust();
606
 
                        }).on( 'wp-window-resized.editor-expand', function() {
607
 
                                if ( mceEditor && ! mceEditor.isHidden() ) {
 
651
                                }).on( 'wp-window-resized.editor-expand', function() {
 
652
                                        if ( mceEditor && ! mceEditor.isHidden() ) {
 
653
                                                mceEditor.execCommand( 'wpAutoResize' );
 
654
                                        } else {
 
655
                                                textEditorResize();
 
656
                                        }
 
657
                                });
 
658
 
 
659
                        $textEditor.on( 'focus.editor-expand input.editor-expand propertychange.editor-expand', textEditorResize );
 
660
                        $textEditor.on( 'keyup.editor-expand', textEditorKeyup );
 
661
                        mceBind();
 
662
 
 
663
                        // Adjust when entering/exiting fullscreen mode.
 
664
                        fullscreen && fullscreen.pubsub.subscribe( 'hidden', fullscreenHide );
 
665
 
 
666
                        if ( mceEditor ) {
 
667
                                mceEditor.settings.wp_autoresize_on = true;
 
668
                                mceEditor.execCommand( 'wpAutoResizeOn' );
 
669
 
 
670
                                if ( ! mceEditor.isHidden() ) {
608
671
                                        mceEditor.execCommand( 'wpAutoResize' );
609
 
                                } else {
610
 
                                        textEditorResize();
611
672
                                }
 
673
                        }
 
674
 
 
675
                        if ( ! mceEditor || mceEditor.isHidden() ) {
 
676
                                textEditorResize();
 
677
                        }
 
678
 
 
679
                        adjust();
 
680
 
 
681
                        $document.trigger( 'editor-expand-on' );
 
682
                }
 
683
 
 
684
                function off() {
 
685
                        var height = window.getUserSetting('ed_size');
 
686
 
 
687
                        // Scroll to the top when triggering this from JS.
 
688
                        // Ensures toolbars are reset properly.
 
689
                        if ( window.pageYOffset && window.pageYOffset > pageYOffsetAtTop ) {
 
690
                                window.scrollTo( window.pageXOffset, 0 );
 
691
                        }
 
692
 
 
693
                        $wrap.removeClass( 'wp-editor-expand' );
 
694
 
 
695
                        $window.off( '.editor-expand' );
 
696
                        $document.off( '.editor-expand' );
 
697
                        $textEditor.off( '.editor-expand' );
 
698
                        mceUnbind();
 
699
 
 
700
                        // Adjust when entering/exiting fullscreen mode.
 
701
                        fullscreen && fullscreen.pubsub.unsubscribe( 'hidden', fullscreenHide );
 
702
 
 
703
                        // Reset all css
 
704
                        $.each( [ $visualTop, $textTop, $tools, $menuBar, $bottom, $statusBar, $contentWrap, $visualEditor, $textEditor, $sideSortables ], function( i, element ) {
 
705
                                element && element.attr( 'style', '' );
612
706
                        });
613
707
 
614
 
                $textEditor.on( 'focus.editor-expand input.editor-expand propertychange.editor-expand', textEditorResize );
615
 
                $textEditor.on( 'keyup.editor-expand', textEditorKeyup );
616
 
                mceBind();
617
 
 
618
 
                // Adjust when entering/exiting fullscreen mode.
619
 
                fullscreen && fullscreen.pubsub.subscribe( 'hidden', fullscreenHide );
620
 
 
621
 
                if ( mceEditor ) {
622
 
                        mceEditor.settings.wp_autoresize_on = true;
623
 
                        mceEditor.execCommand( 'wpAutoResizeOn' );
624
 
 
625
 
                        if ( ! mceEditor.isHidden() ) {
626
 
                                mceEditor.execCommand( 'wpAutoResize' );
627
 
                        }
628
 
                }
629
 
 
630
 
                if ( ! mceEditor || mceEditor.isHidden() ) {
631
 
                        textEditorResize();
632
 
                }
633
 
 
634
 
                adjust();
635
 
        }
636
 
 
637
 
        function off() {
638
 
                var height = window.getUserSetting('ed_size');
639
 
 
640
 
                // Scroll to the top when triggering this from JS.
641
 
                // Ensures toolbars are reset properly.
642
 
                if ( window.pageYOffset && window.pageYOffset > pageYOffsetAtTop ) {
643
 
                        window.scrollTo( window.pageXOffset, 0 );
644
 
                }
645
 
 
646
 
                $wrap.removeClass( 'wp-editor-expand' );
647
 
 
648
 
                $window.off( '.editor-expand' );
649
 
                $document.off( '.editor-expand' );
650
 
                $textEditor.off( '.editor-expand' );
651
 
                mceUnbind();
652
 
 
653
 
                // Adjust when entering/exiting fullscreen mode.
654
 
                fullscreen && fullscreen.pubsub.unsubscribe( 'hidden', fullscreenHide );
655
 
 
656
 
                // Reset all css
657
 
                $.each( [ $visualTop, $textTop, $tools, $menuBar, $bottom, $statusBar, $contentWrap, $visualEditor, $textEditor, $sideSortables ], function( i, element ) {
658
 
                        element && element.attr( 'style', '' );
 
708
                        fixedTop = fixedBottom = fixedSideTop = fixedSideBottom = false;
 
709
 
 
710
                        if ( mceEditor ) {
 
711
                                mceEditor.settings.wp_autoresize_on = false;
 
712
                                mceEditor.execCommand( 'wpAutoResizeOff' );
 
713
 
 
714
                                if ( ! mceEditor.isHidden() ) {
 
715
                                        $textEditor.hide();
 
716
 
 
717
                                        if ( height ) {
 
718
                                                mceEditor.theme.resizeTo( null, height );
 
719
                                        }
 
720
                                }
 
721
                        }
 
722
 
 
723
                        if ( height ) {
 
724
                                $textEditor.height( height );
 
725
                        }
 
726
 
 
727
                        $document.trigger( 'editor-expand-off' );
 
728
                }
 
729
 
 
730
                // Start on load
 
731
                if ( $wrap.hasClass( 'wp-editor-expand' ) ) {
 
732
                        on();
 
733
 
 
734
                        // Ideally we need to resize just after CSS has fully loaded and QuickTags is ready.
 
735
                        if ( $contentWrap.hasClass( 'html-active' ) ) {
 
736
                                initialResize( function() {
 
737
                                        adjust();
 
738
                                        textEditorResize();
 
739
                                } );
 
740
                        }
 
741
                }
 
742
 
 
743
                // Show the on/off checkbox
 
744
                $( '#adv-settings .editor-expand' ).show();
 
745
                $( '#editor-expand-toggle' ).on( 'change.editor-expand', function() {
 
746
                        if ( $(this).prop( 'checked' ) ) {
 
747
                                on();
 
748
                                window.setUserSetting( 'editor_expand', 'on' );
 
749
                        } else {
 
750
                                off();
 
751
                                window.setUserSetting( 'editor_expand', 'off' );
 
752
                        }
659
753
                });
660
754
 
661
 
                fixedTop = fixedBottom = fixedSideTop = fixedSideBottom = false;
662
 
 
663
 
                if ( mceEditor ) {
664
 
                        mceEditor.settings.wp_autoresize_on = false;
665
 
                        mceEditor.execCommand( 'wpAutoResizeOff' );
666
 
 
667
 
                        if ( ! mceEditor.isHidden() ) {
668
 
                                $textEditor.hide();
669
 
 
670
 
                                if ( height ) {
671
 
                                        mceEditor.theme.resizeTo( null, height );
672
 
                                }
673
 
                        }
674
 
                }
675
 
 
676
 
                if ( height ) {
677
 
                        $textEditor.height( height );
678
 
                }
679
 
        }
680
 
 
681
 
        // Start on load
682
 
        if ( $wrap.hasClass( 'wp-editor-expand' ) ) {
683
 
                on();
684
 
 
685
 
                // Ideally we need to resize just after CSS has fully loaded and QuickTags is ready.
686
 
                if ( $contentWrap.hasClass( 'html-active' ) ) {
687
 
                        initialResize( function() {
688
 
                                adjust();
689
 
                                textEditorResize();
 
755
                // Expose on() and off()
 
756
                window.editorExpand = {
 
757
                        on: on,
 
758
                        off: off
 
759
                };
 
760
        } );
 
761
 
 
762
        /* DFW. */
 
763
        $( function() {
 
764
                var $body = $( document.body ),
 
765
                        $wrap = $( '#wpcontent' ),
 
766
                        $editor = $( '#post-body-content' ),
 
767
                        $title = $( '#title' ),
 
768
                        $content = $( '#content' ),
 
769
                        $overlay = $( document.createElement( 'DIV' ) ),
 
770
                        $slug = $( '#edit-slug-box' ),
 
771
                        $slugFocusEl = $slug.find( 'a' )
 
772
                                .add( $slug.find( 'button' ) )
 
773
                                .add( $slug.find( 'input' ) ),
 
774
                        $menuWrap = $( '#adminmenuwrap' ),
 
775
                        $editorWindow = $(),
 
776
                        $editorIframe = $(),
 
777
                        _isActive = window.getUserSetting( 'editor_expand', 'on' ) === 'on',
 
778
                        _isOn = _isActive ? window.getUserSetting( 'post_dfw' ) === 'on' : false,
 
779
                        traveledX = 0,
 
780
                        traveledY = 0,
 
781
                        buffer = 20,
 
782
                        faded, fadedAdminBar, fadedSlug,
 
783
                        editorRect, x, y, mouseY, scrollY,
 
784
                        focusLostTimer, overlayTimer, editorHasFocus;
 
785
 
 
786
                $body.append( $overlay );
 
787
 
 
788
                $overlay.css( {
 
789
                        display: 'none',
 
790
                        position: 'fixed',
 
791
                        top: $adminBar.height(),
 
792
                        right: 0,
 
793
                        bottom: 0,
 
794
                        left: 0,
 
795
                        'z-index': 9997
 
796
                } );
 
797
 
 
798
                $editor.css( {
 
799
                        position: 'relative'
 
800
                } );
 
801
 
 
802
                $window.on( 'mousemove.focus', function( event ) {
 
803
                        mouseY = event.pageY;
 
804
                } );
 
805
 
 
806
                function recalcEditorRect() {
 
807
                        editorRect = $editor.offset();
 
808
                        editorRect.right = editorRect.left + $editor.outerWidth();
 
809
                        editorRect.bottom = editorRect.top + $editor.outerHeight();
 
810
                }
 
811
 
 
812
                function activate() {
 
813
                        if ( ! _isActive ) {
 
814
                                _isActive = true;
 
815
 
 
816
                                $document.trigger( 'dfw-activate' );
 
817
                                $content.on( 'keydown.focus-shortcut', toggleViaKeyboard );
 
818
                        }
 
819
                }
 
820
 
 
821
                function deactivate() {
 
822
                        if ( _isActive ) {
 
823
                                off();
 
824
 
 
825
                                _isActive = false;
 
826
 
 
827
                                $document.trigger( 'dfw-deactivate' );
 
828
                                $content.off( 'keydown.focus-shortcut' );
 
829
                        }
 
830
                }
 
831
 
 
832
                function isActive() {
 
833
                        return _isActive;
 
834
                }
 
835
 
 
836
                function on() {
 
837
                        if ( ! _isOn && _isActive ) {
 
838
                                _isOn = true;
 
839
 
 
840
                                $content.on( 'keydown.focus', fadeOut );
 
841
 
 
842
                                $title.add( $content ).on( 'blur.focus', maybeFadeIn );
 
843
 
 
844
                                fadeOut();
 
845
 
 
846
                                window.setUserSetting( 'post_dfw', 'on' );
 
847
 
 
848
                                $document.trigger( 'dfw-on' );
 
849
                        }
 
850
                }
 
851
 
 
852
                function off() {
 
853
                        if ( _isOn ) {
 
854
                                _isOn = false;
 
855
 
 
856
                                $title.add( $content ).off( '.focus' );
 
857
 
 
858
                                fadeIn();
 
859
 
 
860
                                $editor.off( '.focus' );
 
861
 
 
862
                                window.setUserSetting( 'post_dfw', 'off' );
 
863
 
 
864
                                $document.trigger( 'dfw-off' );
 
865
                        }
 
866
                }
 
867
 
 
868
                function toggle() {
 
869
                        if ( _isOn ) {
 
870
                                off();
 
871
                        } else {
 
872
                                on();
 
873
                        }
 
874
                }
 
875
 
 
876
                function isOn() {
 
877
                        return _isOn;
 
878
                }
 
879
 
 
880
                function fadeOut( event ) {
 
881
                        var key = event && event.keyCode;
 
882
 
 
883
                        // fadeIn and return on Escape and keyboard shortcut Alt+Shift+W.
 
884
                        if ( key === 27 || ( key === 87 && event.altKey && event.shiftKey ) ) {
 
885
                                fadeIn( event );
 
886
                                return;
 
887
                        }
 
888
 
 
889
                        if ( event && ( event.metaKey || ( event.ctrlKey && ! event.altKey ) || ( event.altKey && event.shiftKey ) || ( key && (
 
890
                                // Special keys ( tab, ctrl, alt, esc, arrow keys... )
 
891
                                ( key <= 47 && key !== 8 && key !== 13 && key !== 32 && key !== 46 ) ||
 
892
                                // Windows keys
 
893
                                ( key >= 91 && key <= 93 ) ||
 
894
                                // F keys
 
895
                                ( key >= 112 && key <= 135 ) ||
 
896
                                // Num Lock, Scroll Lock, OEM
 
897
                                ( key >= 144 && key <= 150 ) ||
 
898
                                // OEM or non-printable
 
899
                                key >= 224
 
900
                        ) ) ) ) {
 
901
                                return;
 
902
                        }
 
903
 
 
904
                        if ( ! faded ) {
 
905
                                faded = true;
 
906
 
 
907
                                clearTimeout( overlayTimer );
 
908
 
 
909
                                overlayTimer = setTimeout( function() {
 
910
                                        $overlay.show();
 
911
                                }, 600 );
 
912
 
 
913
                                $editor.css( 'z-index', 9998 );
 
914
 
 
915
                                $overlay
 
916
                                        // Always recalculate the editor area entering the overlay with the mouse.
 
917
                                        .on( 'mouseenter.focus', function() {
 
918
                                                recalcEditorRect();
 
919
 
 
920
                                                $window.on( 'scroll.focus', function() {
 
921
                                                        var nScrollY = window.pageYOffset;
 
922
 
 
923
                                                        if ( (
 
924
                                                                scrollY && mouseY &&
 
925
                                                                scrollY !== nScrollY
 
926
                                                        ) && (
 
927
                                                                mouseY < editorRect.top - buffer ||
 
928
                                                                mouseY > editorRect.bottom + buffer
 
929
                                                        ) ) {
 
930
                                                                fadeIn();
 
931
                                                        }
 
932
 
 
933
                                                        scrollY = nScrollY;
 
934
                                                } );
 
935
                                        } )
 
936
                                        .on( 'mouseleave.focus', function() {
 
937
                                                x = y =  null;
 
938
                                                traveledX = traveledY = 0;
 
939
 
 
940
                                                $window.off( 'scroll.focus' );
 
941
                                        } )
 
942
                                        // Fade in when the mouse moves away form the editor area.
 
943
                                        .on( 'mousemove.focus', function( event ) {
 
944
                                                var nx = event.clientX,
 
945
                                                        ny = event.clientY,
 
946
                                                        pageYOffset = window.pageYOffset,
 
947
                                                        pageXOffset = window.pageXOffset;
 
948
 
 
949
                                                if ( x && y && ( nx !== x || ny !== y ) ) {
 
950
                                                        if (
 
951
                                                                ( ny <= y && ny < editorRect.top - pageYOffset ) ||
 
952
                                                                ( ny >= y && ny > editorRect.bottom - pageYOffset ) ||
 
953
                                                                ( nx <= x && nx < editorRect.left - pageXOffset ) ||
 
954
                                                                ( nx >= x && nx > editorRect.right - pageXOffset )
 
955
                                                        ) {
 
956
                                                                traveledX += Math.abs( x - nx );
 
957
                                                                traveledY += Math.abs( y - ny );
 
958
 
 
959
                                                                if ( (
 
960
                                                                        ny <= editorRect.top - buffer - pageYOffset ||
 
961
                                                                        ny >= editorRect.bottom + buffer - pageYOffset ||
 
962
                                                                        nx <= editorRect.left - buffer - pageXOffset ||
 
963
                                                                        nx >= editorRect.right + buffer - pageXOffset
 
964
                                                                ) && (
 
965
                                                                        traveledX > 10 ||
 
966
                                                                        traveledY > 10
 
967
                                                                ) ) {
 
968
                                                                        fadeIn();
 
969
 
 
970
                                                                        x = y =  null;
 
971
                                                                        traveledX = traveledY = 0;
 
972
 
 
973
                                                                        return;
 
974
                                                                }
 
975
                                                        } else {
 
976
                                                                traveledX = traveledY = 0;
 
977
                                                        }
 
978
                                                }
 
979
 
 
980
                                                x = nx;
 
981
                                                y = ny;
 
982
                                        } )
 
983
                                        // When the overlay is touched, always fade in and cancel the event.
 
984
                                        .on( 'touchstart.focus', function( event ) {
 
985
                                                event.preventDefault();
 
986
                                                fadeIn();
 
987
                                        } );
 
988
 
 
989
                                $editor.off( 'mouseenter.focus' );
 
990
 
 
991
                                if ( focusLostTimer ) {
 
992
                                        clearTimeout( focusLostTimer );
 
993
                                        focusLostTimer = null;
 
994
                                }
 
995
 
 
996
                                $body.addClass( 'focus-on' ).removeClass( 'focus-off' );
 
997
                        }
 
998
 
 
999
                        fadeOutAdminBar();
 
1000
                        fadeOutSlug();
 
1001
                }
 
1002
 
 
1003
                function fadeIn( event ) {
 
1004
                        if ( faded ) {
 
1005
                                faded = false;
 
1006
 
 
1007
                                clearTimeout( overlayTimer );
 
1008
 
 
1009
                                overlayTimer = setTimeout( function() {
 
1010
                                        $overlay.hide();
 
1011
                                }, 200 );
 
1012
 
 
1013
                                $editor.css( 'z-index', '' );
 
1014
 
 
1015
                                $overlay.off( 'mouseenter.focus mouseleave.focus mousemove.focus touchstart.focus' );
 
1016
 
 
1017
                                /*
 
1018
                                 * When fading in, temporarily watch for refocus and fade back out - helps
 
1019
                                 * with 'accidental' editor exits with the mouse. When fading in and the event
 
1020
                                 * is a key event (Escape or Alt+Shift+W) don't watch for refocus.
 
1021
                                 */
 
1022
                                if ( 'undefined' === typeof event ) {
 
1023
                                        $editor.on( 'mouseenter.focus', function() {
 
1024
                                                if ( $.contains( $editor.get( 0 ), document.activeElement ) || editorHasFocus ) {
 
1025
                                                        fadeOut();
 
1026
                                                }
 
1027
                                        } );
 
1028
                                }
 
1029
 
 
1030
                                focusLostTimer = setTimeout( function() {
 
1031
                                        focusLostTimer = null;
 
1032
                                        $editor.off( 'mouseenter.focus' );
 
1033
                                }, 1000 );
 
1034
 
 
1035
                                $body.addClass( 'focus-off' ).removeClass( 'focus-on' );
 
1036
                        }
 
1037
 
 
1038
                        fadeInAdminBar();
 
1039
                        fadeInSlug();
 
1040
                }
 
1041
 
 
1042
                function maybeFadeIn() {
 
1043
                        setTimeout( function() {
 
1044
                                var position = document.activeElement.compareDocumentPosition( $editor.get( 0 ) );
 
1045
 
 
1046
                                function hasFocus( $el ) {
 
1047
                                        return $.contains( $el.get( 0 ), document.activeElement );
 
1048
                                }
 
1049
 
 
1050
                                // The focused node is before or behind the editor area, and not outside the wrap.
 
1051
                                if ( ( position === 2 || position === 4 ) && ( hasFocus( $menuWrap ) || hasFocus( $wrap ) || hasFocus( $footer ) ) ) {
 
1052
                                        fadeIn();
 
1053
                                }
 
1054
                        }, 0 );
 
1055
                }
 
1056
 
 
1057
                function fadeOutAdminBar() {
 
1058
                        if ( ! fadedAdminBar && faded ) {
 
1059
                                fadedAdminBar = true;
 
1060
 
 
1061
                                $adminBar
 
1062
                                        .on( 'mouseenter.focus', function() {
 
1063
                                                $adminBar.addClass( 'focus-off' );
 
1064
                                        } )
 
1065
                                        .on( 'mouseleave.focus', function() {
 
1066
                                                $adminBar.removeClass( 'focus-off' );
 
1067
                                        } );
 
1068
                        }
 
1069
                }
 
1070
 
 
1071
                function fadeInAdminBar() {
 
1072
                        if ( fadedAdminBar ) {
 
1073
                                fadedAdminBar = false;
 
1074
 
 
1075
                                $adminBar.off( '.focus' );
 
1076
                        }
 
1077
                }
 
1078
 
 
1079
                function fadeOutSlug() {
 
1080
                        if ( ! fadedSlug && faded && ! $slug.find( ':focus').length ) {
 
1081
                                fadedSlug = true;
 
1082
 
 
1083
                                $slug.stop().fadeTo( 'fast', 0.3 ).on( 'mouseenter.focus', fadeInSlug ).off( 'mouseleave.focus' );
 
1084
 
 
1085
                                $slugFocusEl.on( 'focus.focus', fadeInSlug ).off( 'blur.focus' );
 
1086
                        }
 
1087
                }
 
1088
 
 
1089
                function fadeInSlug() {
 
1090
                        if ( fadedSlug ) {
 
1091
                                fadedSlug = false;
 
1092
 
 
1093
                                $slug.stop().fadeTo( 'fast', 1 ).on( 'mouseleave.focus', fadeOutSlug ).off( 'mouseenter.focus' );
 
1094
 
 
1095
                                $slugFocusEl.on( 'blur.focus', fadeOutSlug ).off( 'focus.focus' );
 
1096
                        }
 
1097
                }
 
1098
 
 
1099
                function toggleViaKeyboard( event ) {
 
1100
                        if ( event.altKey && event.shiftKey && 87 === event.keyCode ) {
 
1101
                                toggle();
 
1102
                        }
 
1103
                }
 
1104
 
 
1105
                if ( $( '#postdivrich' ).hasClass( 'wp-editor-expand' ) ) {
 
1106
                        $content.on( 'keydown.focus-shortcut', toggleViaKeyboard );
 
1107
                }
 
1108
 
 
1109
                $document.on( 'tinymce-editor-setup.focus', function( event, editor ) {
 
1110
                        editor.addButton( 'dfw', {
 
1111
                                active: _isOn,
 
1112
                                classes: 'wp-dfw btn widget',
 
1113
                                disabled: ! _isActive,
 
1114
                                onclick: toggle,
 
1115
                                onPostRender: function() {
 
1116
                                        var button = this;
 
1117
 
 
1118
                                        $document
 
1119
                                        .on( 'dfw-activate.focus', function() {
 
1120
                                                button.disabled( false );
 
1121
                                        } )
 
1122
                                        .on( 'dfw-deactivate.focus', function() {
 
1123
                                                button.disabled( true );
 
1124
                                        } )
 
1125
                                        .on( 'dfw-on.focus', function() {
 
1126
                                                button.active( true );
 
1127
                                        } )
 
1128
                                        .on( 'dfw-off.focus', function() {
 
1129
                                                button.active( false );
 
1130
                                        } );
 
1131
                                },
 
1132
                                tooltip: 'Distraction-free writing mode',
 
1133
                                shortcut: 'Alt+Shift+W'
690
1134
                        } );
691
 
                }
692
 
        }
693
 
 
694
 
        // Show the on/off checkbox
695
 
        $( '#adv-settings .editor-expand' ).show();
696
 
        $( '#editor-expand-toggle' ).on( 'change.editor-expand', function() {
697
 
                if ( $(this).prop( 'checked' ) ) {
698
 
                        on();
699
 
                        window.setUserSetting( 'editor_expand', 'on' );
700
 
                } else {
701
 
                        off();
702
 
                        window.setUserSetting( 'editor_expand', 'off' );
703
 
                }
704
 
        });
705
 
 
706
 
        // Expose on() and off()
707
 
        window.editorExpand = {
708
 
                on: on,
709
 
                off: off
710
 
        };
711
 
});
 
1135
 
 
1136
                        editor.addCommand( 'wpToggleDFW', toggle );
 
1137
                        editor.addShortcut( 'alt+shift+w', '', 'wpToggleDFW' );
 
1138
                } );
 
1139
 
 
1140
                $document.on( 'tinymce-editor-init.focus', function( event, editor ) {
 
1141
                        var mceBind, mceUnbind;
 
1142
 
 
1143
                        function focus() {
 
1144
                                editorHasFocus = true;
 
1145
                        }
 
1146
 
 
1147
                        function blur() {
 
1148
                                editorHasFocus = false;
 
1149
                        }
 
1150
 
 
1151
                        if ( editor.id === 'content' ) {
 
1152
                                $editorWindow = $( editor.getWin() );
 
1153
                                $editorIframe = $( editor.getContentAreaContainer() ).find( 'iframe' );
 
1154
 
 
1155
                                mceBind = function() {
 
1156
                                        editor.on( 'keydown', fadeOut );
 
1157
                                        editor.on( 'blur', maybeFadeIn );
 
1158
                                        editor.on( 'focus', focus );
 
1159
                                        editor.on( 'blur', blur );
 
1160
                                        editor.on( 'wp-autoresize', recalcEditorRect );
 
1161
                                };
 
1162
 
 
1163
                                mceUnbind = function() {
 
1164
                                        editor.off( 'keydown', fadeOut );
 
1165
                                        editor.off( 'blur', maybeFadeIn );
 
1166
                                        editor.off( 'focus', focus );
 
1167
                                        editor.off( 'blur', blur );
 
1168
                                        editor.off( 'wp-autoresize', recalcEditorRect );
 
1169
                                };
 
1170
 
 
1171
                                if ( _isOn ) {
 
1172
                                        mceBind();
 
1173
                                }
 
1174
 
 
1175
                                $document.on( 'dfw-on.focus', mceBind ).on( 'dfw-off.focus', mceUnbind );
 
1176
 
 
1177
                                // Make sure the body focuses when clicking outside it.
 
1178
                                editor.on( 'click', function( event ) {
 
1179
                                        if ( event.target === editor.getDoc().documentElement ) {
 
1180
                                                editor.focus();
 
1181
                                        }
 
1182
                                } );
 
1183
                        }
 
1184
                } );
 
1185
 
 
1186
                $document.on( 'quicktags-init', function( event, editor ) {
 
1187
                        var $button;
 
1188
 
 
1189
                        if ( editor.settings.buttons && ( ',' + editor.settings.buttons + ',' ).indexOf( ',dfw,' ) !== -1 ) {
 
1190
                                $button = $( '#' + editor.name + '_dfw' );
 
1191
 
 
1192
                                $( document )
 
1193
                                .on( 'dfw-activate', function() {
 
1194
                                        $button.prop( 'disabled', false );
 
1195
                                } )
 
1196
                                .on( 'dfw-deactivate', function() {
 
1197
                                        $button.prop( 'disabled', true );
 
1198
                                } )
 
1199
                                .on( 'dfw-on', function() {
 
1200
                                        $button.addClass( 'active' );
 
1201
                                } )
 
1202
                                .on( 'dfw-off', function() {
 
1203
                                        $button.removeClass( 'active' );
 
1204
                                } );
 
1205
                        }
 
1206
                } );
 
1207
 
 
1208
                $document.on( 'editor-expand-on.focus', activate ).on( 'editor-expand-off.focus', deactivate );
 
1209
 
 
1210
                if ( _isOn ) {
 
1211
                        $content.on( 'keydown.focus', fadeOut );
 
1212
 
 
1213
                        $title.add( $content ).on( 'blur.focus', maybeFadeIn );
 
1214
                }
 
1215
 
 
1216
                window.wp = window.wp || {};
 
1217
                window.wp.editor = window.wp.editor || {};
 
1218
                window.wp.editor.dfw = {
 
1219
                        activate: activate,
 
1220
                        deactivate: deactivate,
 
1221
                        isActive: isActive,
 
1222
                        on: on,
 
1223
                        off: off,
 
1224
                        toggle: toggle,
 
1225
                        isOn: isOn
 
1226
                };
 
1227
        } );
 
1228
} )( window, window.jQuery );