94
122
oldTextLength = length;
126
* @summary Gets the height and widths of elements.
128
* Gets the heights of the window, the adminbar, the tools, the menu,
129
* the visualTop, the textTop, the bottom, the statusbar and sideSortables
130
* and stores these in the heights object. Defaults to 0.
131
* Gets the width of the window and stores this in the heights object.
97
137
function getHeights() {
98
138
var windowWidth = $window.width();
110
150
sideSortablesHeight: $sideSortables.height() || 0
153
// Adjust for hidden menubar.
114
154
if ( heights.menuBarHeight < 3 ) {
115
155
heights.menuBarHeight = 0;
119
159
// We need to wait for TinyMCE to initialize.
161
* @summary Binds all necessary functions for editor expand to the editor
162
* when the editor is initialized.
166
* @param {event} event The TinyMCE editor init event.
167
* @param {object} editor The editor to bind the vents on.
120
171
$document.on( 'tinymce-editor-init.editor-expand', function( event, editor ) {
172
// VK contains the type of key pressed. VK = virtual keyboard.
121
173
var VK = window.tinymce.util.VK,
175
* @summary Hides any float panel with a hover state. Additionally hides tooltips.
122
179
hideFloatPanels = _.debounce( function() {
123
180
! $( '.mce-floatpanel:hover' ).length && window.tinymce.ui.FloatPanel.hideAll();
124
181
$( '.mce-tooltip' ).hide();
141
198
$statusBar = $contentWrap.find( '.mce-statusbar' );
142
199
$menuBar = $contentWrap.find( '.mce-menubar' );
202
* @summary Gets the offset of the editor.
204
* @returns {Number|Boolean} Returns the offset of the editor
205
* or false if there is no offset height.
144
207
function mceGetCursorOffset() {
145
208
var node = editor.selection.getNode(),
146
209
range, view, offset;
212
* If editor.wp.getView and the selection node from the editor selection
213
* are defined, use this as a view for the offset.
148
215
if ( editor.wp && editor.wp.getView && ( view = editor.wp.getView( node ) ) ) {
149
216
offset = view.getBoundingClientRect();
151
218
range = editor.selection.getRng();
220
// Try to get the offset from a range.
154
222
offset = range.getClientRects()[0];
225
// Get the offset from the bounding client rectangle of the node.
157
226
if ( ! offset ) {
158
227
offset = node.getBoundingClientRect();
162
231
return offset.height ? offset : false;
165
// Make sure the cursor is always visible.
166
// This is not only necessary to keep the cursor between the toolbars,
167
// but also to scroll the window when the cursor moves out of the viewport to a wpview.
168
// Setting a buffer > 0 will prevent the browser default.
169
// Some browsers will scroll to the middle,
170
// others to the top/bottom of the *window* when moving the cursor out of the viewport.
235
* @summary Filters the special keys that should not be used for scrolling.
239
* @param {event} event The event to get the key code from.
171
243
function mceKeyup( event ) {
172
244
var key = event.keyCode;
174
// Bail on special keys.
246
// Bail on special keys. Key code 47 is a /
175
247
if ( key <= 47 && ! ( key === VK.SPACEBAR || key === VK.ENTER || key === VK.DELETE || key === VK.BACKSPACE || key === VK.UP || key === VK.LEFT || key === VK.DOWN || key === VK.UP ) ) {
177
// OS keys, function keys, num lock, scroll lock
249
// OS keys, function keys, num lock, scroll lock. Key code 91-93 are OS keys. Key code 112-123 are F1 to F12. Key code 144 is num lock. Key code 145 is scroll lock.
178
250
} else if ( ( key >= 91 && key <= 93 ) || ( key >= 112 && key <= 123 ) || key === 144 || key === 145 ) {
182
254
mceScroll( key );
258
* @summary Makes sure the cursor is always visible in the editor.
260
* Makes sure the cursor is kept between the toolbars of the editor and scrolls
261
* the window when the cursor moves out of the viewport to a wpview.
262
* Setting a buffer > 0 will prevent the browser default.
263
* Some browsers will scroll to the middle,
264
* others to the top/bottom of the *window* when moving the cursor out of the viewport.
268
* @param {string} key The key code of the pressed key.
185
272
function mceScroll( key ) {
186
273
var offset = mceGetCursorOffset(),
188
275
cursorTop, cursorBottom, editorTop, editorBottom;
277
// Don't scroll if there is no offset.
190
278
if ( ! offset ) {
282
// Determine the cursorTop based on the offset and the top of the editor iframe.
194
283
cursorTop = offset.top + editor.iframeElement.getBoundingClientRect().top;
285
// Determine the cursorBottom based on the cursorTop and offset height.
195
286
cursorBottom = cursorTop + offset.height;
288
// Subtract the buffer from the cursorTop.
196
289
cursorTop = cursorTop - buffer;
291
// Add the buffer to the cursorBottom.
197
292
cursorBottom = cursorBottom + buffer;
198
293
editorTop = heights.adminBarHeight + heights.toolsHeight + heights.menuBarHeight + heights.visualTopHeight;
296
* Set the editorBottom based on the window Height, and add the bottomHeight and statusBarHeight if the
297
* advanced editor is enabled.
199
299
editorBottom = heights.windowHeight - ( advanced ? heights.bottomHeight + heights.statusBarHeight : 0 );
201
// Don't scroll if the node is taller than the visible part of the editor
301
// Don't scroll if the node is taller than the visible part of the editor.
202
302
if ( editorBottom - editorTop < offset.height ) {
307
* If the cursorTop is smaller than the editorTop and the up, left
308
* or backspace key is pressed, scroll the editor to the position defined
309
* by the cursorTop, pageYOffset and editorTop.
206
311
if ( cursorTop < editorTop && ( key === VK.UP || key === VK.LEFT || key === VK.BACKSPACE ) ) {
207
312
window.scrollTo( window.pageXOffset, cursorTop + window.pageYOffset - editorTop );
315
* If any other key is pressed or the cursorTop is bigger than the editorTop,
316
* scroll the editor to the position defined by the cursorBottom,
317
* pageYOffset and editorBottom.
208
319
} else if ( cursorBottom > editorBottom ) {
209
320
window.scrollTo( window.pageXOffset, cursorBottom + window.pageYOffset - editorBottom );
325
* @summary If the editor is fullscreen, calls adjust.
329
* @param {event} event The FullscreenStateChanged event.
213
333
function mceFullscreenToggled( event ) {
334
// event.state is true if the editor is fullscreen.
214
335
if ( ! event.state ) {
219
// Adjust when switching editor modes.
341
* @summary Shows the editor when scrolled.
343
* Binds the hideFloatPanels function on the window scroll.mce-float-panels event.
344
* Executes the wpAutoResize on the active editor.
220
350
function mceShow() {
221
351
$window.on( 'scroll.mce-float-panels', hideFloatPanels );
387
* @summary Toggles advanced states.
246
393
function toggleAdvanced() {
247
394
advanced = ! advanced;
398
* @summary Binds events of the editor and window.
250
404
mceBind = function() {
251
405
editor.on( 'keyup', mceKeyup );
252
406
editor.on( 'show', mceShow );
253
407
editor.on( 'hide', mceHide );
254
408
editor.on( 'wp-toolbar-toggle', toggleAdvanced );
255
410
// Adjust when the editor resizes.
256
411
editor.on( 'setcontent wp-autoresize wp-toolbar-toggle', adjust );
257
413
// Don't hide the caret after undo/redo.
258
414
editor.on( 'undo redo', mceScroll );
259
416
// Adjust when exiting TinyMCE's fullscreen mode.
260
417
editor.on( 'FullscreenStateChanged', mceFullscreenToggled );
262
419
$window.off( 'scroll.mce-float-panels' ).on( 'scroll.mce-float-panels', hideFloatPanels );
423
* @summary Unbinds the events of the editor and window.
265
429
mceUnbind = function() {
266
430
editor.off( 'keyup', mceKeyup );
267
431
editor.off( 'show', mceShow );
277
441
if ( $wrap.hasClass( 'wp-editor-expand' ) ) {
278
// Adjust "immediately"
443
// Adjust "immediately".
280
445
initialResize( adjust );
284
// Adjust the toolbars based on the active editor mode.
450
* @summary Adjusts the toolbars heights and positions.
452
* Adjusts the toolbar heights and positions based on the scroll position on the page,
453
* the active editor mode and the heights of the editor, admin bar and side bar.
457
* @param {event} event The event that calls this function.
285
461
function adjust( event ) {
286
// Make sure we're not in fullscreen mode.
463
// Makes sure we're not in fullscreen mode.
287
464
if ( fullscreen && fullscreen.settings.visible ) {
299
476
$top, $editor, sidebarTop, footerTop, canPin,
300
477
topPos, topHeight, editorPos, editorHeight;
302
// Refresh the heights
480
* Refresh the heights if type isn't 'scroll'
481
* or heights.windowHeight isn't set.
303
483
if ( resize || ! heights.windowHeight ) {
487
// Resize on resize event when the editor is in text mode.
307
488
if ( ! visual && type === 'resize' ) {
308
489
textEditorResize();
438
// Maybe adjust the bottom bar.
618
// Check if the bottom is not already in a fixed position.
439
619
if ( ( ! fixedBottom || ( resize && advanced ) ) &&
440
// +[n] for the border around the .wp-editor-container.
620
// Add borderWidth for the border around the .wp-editor-container.
441
621
( windowPos + heights.windowHeight ) <= ( editorPos + editorHeight + heights.bottomHeight + heights.statusBarHeight + borderWidth ) ) {
443
623
if ( event && event.deltaHeight > 0 && event.deltaHeight < 100 ) {
472
if ( $postboxContainer.width() < 300 && heights.windowWidth > 600 && // sidebar position is changed with @media from CSS, make sure it is on the side
473
$document.height() > ( $sideSortables.height() + postBodyTop + 120 ) && // the sidebar is not the tallest element
474
heights.windowHeight < editorHeight ) { // the editor is taller than the viewport
651
// The postbox container is positioned with @media from CSS. Ensure it is pinned on the side.
652
if ( $postboxContainer.width() < 300 && heights.windowWidth > 600 &&
654
// Check if the sidebar is not taller than the document height.
655
$document.height() > ( $sideSortables.height() + postBodyTop + 120 ) &&
657
// Check if the editor is taller than the viewport.
658
heights.windowHeight < editorHeight ) {
476
660
if ( ( heights.sideSortablesHeight + pinnedToolsTop + sidebarBottom ) > heights.windowHeight || fixedSideTop || fixedSideBottom ) {
477
// Reset when scrolling to the top
662
// Reset the sideSortables style when scrolling to the top.
478
663
if ( windowPos + pinnedToolsTop <= postBodyTop ) {
479
664
$sideSortables.attr( 'style', '' );
480
665
fixedSideTop = fixedSideBottom = false;
668
// When scrolling down.
482
669
if ( windowPos > lastScrollPosition ) {
484
670
if ( fixedSideTop ) {
486
673
fixedSideTop = false;
487
674
sidebarTop = $sideSortables.offset().top - heights.adminBarHeight;
488
675
footerTop = $footer.offset().top;
490
// don't get over the footer
677
// Don't get over the footer.
491
678
if ( footerTop < sidebarTop + heights.sideSortablesHeight + sidebarBottom ) {
492
679
sidebarTop = footerTop - heights.sideSortablesHeight - 12;
767
* @summary Resizes the editor and adjusts the toolbars.
578
773
function fullscreenHide() {
579
774
textEditorResize();
779
* @summary Runs the passed function with 500ms intervals.
783
* @param {function} callback The function to run in the timeout.
583
787
function initialResize( callback ) {
584
788
for ( var i = 1; i < 6; i++ ) {
585
789
setTimeout( callback, 500 * i );
794
* @summary Runs adjust after 100ms.
589
800
function afterScroll() {
590
801
clearTimeout( scrollTimer );
591
802
scrollTimer = setTimeout( adjust, 100 );
806
* @summary Binds editor expand events on elements.
595
// Scroll to the top when triggering this from JS.
596
// Ensures toolbars are pinned properly.
814
* Scroll to the top when triggering this from JS.
815
* Ensure the toolbars are pinned properly.
597
817
if ( window.pageYOffset && window.pageYOffset > pageYOffsetAtTop ) {
598
818
window.scrollTo( window.pageXOffset, 0 );
609
// Adjust when collapsing the menu, changing the columns, changing the body class.
830
* Adjust when collapsing the menu, changing the columns
831
* or changing the body class.
610
833
$document.on( 'wp-collapse-menu.editor-expand postboxes-columnchange.editor-expand editor-classchange.editor-expand', adjust )
611
834
.on( 'postbox-toggled.editor-expand postbox-moved.editor-expand', function() {
612
835
if ( ! fixedSideTop && ! fixedSideBottom && window.pageYOffset > pinnedToolsTop ) {
1139
* @summary Returns the value of _isOn.
1143
* @returns {boolean} Returns true if _isOn is true.
850
1145
function isOn() {
1150
* @summary Fades out all elements except for the editor.
1152
* The fading is done based on key presses and mouse movements.
1153
* Also calls the fadeIn on certain key presses
1154
* or if the mouse leaves the editor.
1158
* @param event The event that triggers this function.
854
1162
function fadeOut( event ) {
856
1164
key = event && event.keyCode;
859
1167
isMac = ( window.navigator.platform.indexOf( 'Mac' ) > -1 );
862
// fadeIn and return on Escape and keyboard shortcut Alt+Shift+W and Ctrl+Opt+W.
1170
// Fade in and returns on Escape and keyboard shortcut Alt+Shift+W and Ctrl+Opt+W.
863
1171
if ( key === 27 || ( key === 87 && event.altKey && ( ( ! isMac && event.shiftKey ) || ( isMac && event.ctrlKey ) ) ) ) {
864
1172
fadeIn( event );
1176
// Return if any of the following keys or combinations of keys is pressed.
868
1177
if ( event && ( event.metaKey || ( event.ctrlKey && ! event.altKey ) || ( event.altKey && event.shiftKey ) || ( key && (
869
1178
// Special keys ( tab, ctrl, alt, esc, arrow keys... )
870
1179
( key <= 47 && key !== 8 && key !== 13 && key !== 32 && key !== 46 ) ||
1085
1450
$content.on( 'keydown.focus-shortcut', toggleViaKeyboard );
1454
* @summary Adds the distraction free writing button when setting up TinyMCE.
1458
* @param {event} event The TinyMCE editor setup event.
1459
* @param {object} editor The editor to add the button to.
1088
1463
$document.on( 'tinymce-editor-setup.focus', function( event, editor ) {
1089
1464
editor.addButton( 'dfw', {
1539
// Bind and unbind based on the distraction free writing focus.
1154
1540
$document.on( 'dfw-on.focus', mceBind ).on( 'dfw-off.focus', mceUnbind );
1156
// Make sure the body focuses when clicking outside it.
1542
// Focuse the editor when it is the target of the click event.
1157
1543
editor.on( 'click', function( event ) {
1158
1544
if ( event.target === editor.getDoc().documentElement ) {
1159
1545
editor.focus();
1552
* @summary Binds events on quicktags init.
1556
* @param {event} event The quicktags init event.
1557
* @param {object} editor The editor to bind events on.
1165
1561
$document.on( 'quicktags-init', function( event, editor ) {
1564
// Bind the distraction free writing events if the distraction free writing button is available.
1168
1565
if ( editor.settings.buttons && ( ',' + editor.settings.buttons + ',' ).indexOf( ',dfw,' ) !== -1 ) {
1169
1566
$button = $( '#' + editor.name + '_dfw' );