2014-11-13 17:31:22 -05:00
( function ( window , $ , undefined ) {
'use strict' ;
2014-07-09 18:06:15 -04:00
var $window = $ ( window ) ,
$document = $ ( document ) ,
$adminBar = $ ( '#wpadminbar' ) ,
2014-11-13 17:31:22 -05:00
$footer = $ ( '#wpfooter' ) ;
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Handles the resizing of the editor .
*
* @ since 4.0 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
$ ( function ( ) {
var $wrap = $ ( '#postdivrich' ) ,
$contentWrap = $ ( '#wp-content-wrap' ) ,
$tools = $ ( '#wp-content-editor-tools' ) ,
$visualTop = $ ( ) ,
$visualEditor = $ ( ) ,
$textTop = $ ( '#ed_toolbar' ) ,
$textEditor = $ ( '#content' ) ,
2016-05-30 16:32:30 -04:00
textEditor = $textEditor [ 0 ] ,
2016-06-01 06:24:30 -04:00
oldTextLength = 0 ,
2014-11-13 17:31:22 -05:00
$bottom = $ ( '#post-status-info' ) ,
$menuBar = $ ( ) ,
$statusBar = $ ( ) ,
$sideSortables = $ ( '#side-sortables' ) ,
$postboxContainer = $ ( '#postbox-container-1' ) ,
$postBody = $ ( '#post-body' ) ,
fullscreen = window . wp . editor && window . wp . editor . fullscreen ,
mceEditor ,
mceBind = function ( ) { } ,
mceUnbind = function ( ) { } ,
fixedTop = false ,
fixedBottom = false ,
fixedSideTop = false ,
fixedSideBottom = false ,
scrollTimer ,
lastScrollPosition = 0 ,
pageYOffsetAtTop = 130 ,
pinnedToolsTop = 56 ,
sidebarBottom = 20 ,
autoresizeMinHeight = 300 ,
2014-12-04 20:53:22 -05:00
initialMode = $contentWrap . hasClass ( 'tmce-active' ) ? 'tinymce' : 'html' ,
2014-11-13 17:31:22 -05:00
advanced = ! ! parseInt ( window . getUserSetting ( 'hidetb' ) , 10 ) ,
// These are corrected when adjust() runs, except on scrolling if already set.
heights = {
windowHeight : 0 ,
windowWidth : 0 ,
adminBarHeight : 0 ,
toolsHeight : 0 ,
menuBarHeight : 0 ,
visualTopHeight : 0 ,
textTopHeight : 0 ,
bottomHeight : 0 ,
statusBarHeight : 0 ,
sideSortablesHeight : 0
} ;
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Resizes textarea based on scroll height and width .
*
* Resizes textarea based on scroll height and width . Doesn ' t shrink the
* editor size below the 300 px auto resize minimum height .
*
* @ since 4.6 . 1
*
* @ returns { void }
* /
2016-08-28 14:40:31 -04:00
var shrinkTextarea = window . _ . throttle ( function ( ) {
var x = window . scrollX || document . documentElement . scrollLeft ;
var y = window . scrollY || document . documentElement . scrollTop ;
var height = parseInt ( textEditor . style . height , 10 ) ;
textEditor . style . height = autoresizeMinHeight + 'px' ;
if ( textEditor . scrollHeight > autoresizeMinHeight ) {
textEditor . style . height = textEditor . scrollHeight + 'px' ;
}
if ( typeof x !== 'undefined' ) {
window . scrollTo ( x , y ) ;
}
if ( textEditor . scrollHeight < height ) {
adjust ( ) ;
}
} , 300 ) ;
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Resizes the text editor depending on the old text length .
*
* If there is an mceEditor and it is hidden , it resizes the editor depending
* on the old text length . If the current length of the text is smaller than
* the old text length , it shrinks the text area . Otherwise it resizes the editor to
* the scroll height .
*
* @ since 4.6 . 1
*
* @ returns { void }
* /
2016-08-28 14:40:31 -04:00
function textEditorResize ( ) {
var length = textEditor . value . length ;
if ( mceEditor && ! mceEditor . isHidden ( ) ) {
return ;
}
if ( ! mceEditor && initialMode === 'tinymce' ) {
return ;
}
if ( length < oldTextLength ) {
shrinkTextarea ( ) ;
} else if ( parseInt ( textEditor . style . height , 10 ) < textEditor . scrollHeight ) {
textEditor . style . height = Math . ceil ( textEditor . scrollHeight ) + 'px' ;
adjust ( ) ;
}
oldTextLength = length ;
}
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Gets the height and widths of elements .
*
* Gets the heights of the window , the adminbar , the tools , the menu ,
* the visualTop , the textTop , the bottom , the statusbar and sideSortables
* and stores these in the heights object . Defaults to 0.
* Gets the width of the window and stores this in the heights object .
*
* @ since 4.0 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function getHeights ( ) {
var windowWidth = $window . width ( ) ;
heights = {
windowHeight : $window . height ( ) ,
windowWidth : windowWidth ,
adminBarHeight : ( windowWidth > 600 ? $adminBar . outerHeight ( ) : 0 ) ,
toolsHeight : $tools . outerHeight ( ) || 0 ,
menuBarHeight : $menuBar . outerHeight ( ) || 0 ,
visualTopHeight : $visualTop . outerHeight ( ) || 0 ,
textTopHeight : $textTop . outerHeight ( ) || 0 ,
bottomHeight : $bottom . outerHeight ( ) || 0 ,
statusBarHeight : $statusBar . outerHeight ( ) || 0 ,
sideSortablesHeight : $sideSortables . height ( ) || 0
} ;
2017-08-24 13:48:45 -04:00
// Adjust for hidden menubar.
2014-11-13 17:31:22 -05:00
if ( heights . menuBarHeight < 3 ) {
heights . menuBarHeight = 0 ;
}
2014-07-09 18:06:15 -04:00
}
2014-11-13 17:31:22 -05:00
// We need to wait for TinyMCE to initialize.
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Binds all necessary functions for editor expand to the editor
* when the editor is initialized .
*
* @ since 4.0 . 0
*
* @ param { event } event The TinyMCE editor init event .
* @ param { object } editor The editor to bind the vents on .
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
$document . on ( 'tinymce-editor-init.editor-expand' , function ( event , editor ) {
2017-08-24 13:48:45 -04:00
// VK contains the type of key pressed. VK = virtual keyboard.
2014-11-13 17:31:22 -05:00
var VK = window . tinymce . util . VK ,
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Hides any float panel with a hover state . Additionally hides tooltips .
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
hideFloatPanels = _ . debounce ( function ( ) {
! $ ( '.mce-floatpanel:hover' ) . length && window . tinymce . ui . FloatPanel . hideAll ( ) ;
$ ( '.mce-tooltip' ) . hide ( ) ;
} , 1000 , true ) ;
2014-10-16 17:31:18 -04:00
2014-11-13 17:31:22 -05:00
// Make sure it's the main editor.
if ( editor . id !== 'content' ) {
2014-09-03 05:38:16 -04:00
return ;
}
2014-11-13 17:31:22 -05:00
// Copy the editor instance.
mceEditor = editor ;
2014-10-16 17:31:18 -04:00
2014-11-13 17:31:22 -05:00
// Set the minimum height to the initial viewport height.
editor . settings . autoresize _min _height = autoresizeMinHeight ;
2014-10-16 17:31:18 -04:00
2014-11-13 17:31:22 -05:00
// Get the necessary UI elements.
$visualTop = $contentWrap . find ( '.mce-toolbar-grp' ) ;
$visualEditor = $contentWrap . find ( '.mce-edit-area' ) ;
$statusBar = $contentWrap . find ( '.mce-statusbar' ) ;
$menuBar = $contentWrap . find ( '.mce-menubar' ) ;
2014-10-16 17:31:18 -04:00
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Gets the offset of the editor .
*
* @ returns { Number | Boolean } Returns the offset of the editor
* or false if there is no offset height .
* /
2014-11-13 17:31:22 -05:00
function mceGetCursorOffset ( ) {
var node = editor . selection . getNode ( ) ,
range , view , offset ;
2014-07-09 18:06:15 -04:00
2017-08-24 13:48:45 -04:00
/ *
* If editor . wp . getView and the selection node from the editor selection
* are defined , use this as a view for the offset .
* /
2015-03-11 15:12:28 -04:00
if ( editor . wp && editor . wp . getView && ( view = editor . wp . getView ( node ) ) ) {
2014-11-13 17:31:22 -05:00
offset = view . getBoundingClientRect ( ) ;
} else {
range = editor . selection . getRng ( ) ;
2014-07-25 20:08:19 -04:00
2017-08-24 13:48:45 -04:00
// Try to get the offset from a range.
2014-11-13 17:31:22 -05:00
try {
offset = range . getClientRects ( ) [ 0 ] ;
} catch ( er ) { }
2014-10-16 17:31:18 -04:00
2017-08-24 13:48:45 -04:00
// Get the offset from the bounding client rectangle of the node.
2014-11-13 17:31:22 -05:00
if ( ! offset ) {
offset = node . getBoundingClientRect ( ) ;
}
}
2014-07-09 18:06:15 -04:00
2014-11-13 17:31:22 -05:00
return offset . height ? offset : false ;
}
2014-09-11 21:21:15 -04:00
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Filters the special keys that should not be used for scrolling .
*
* @ since 4.0 . 0
*
* @ param { event } event The event to get the key code from .
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function mceKeyup ( event ) {
var key = event . keyCode ;
2017-08-24 13:48:45 -04:00
// Bail on special keys. Key code 47 is a /
2014-11-13 17:31:22 -05:00
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 ) ) {
return ;
2017-08-24 13:48:45 -04:00
// 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.
2014-11-13 17:31:22 -05:00
} else if ( ( key >= 91 && key <= 93 ) || ( key >= 112 && key <= 123 ) || key === 144 || key === 145 ) {
return ;
}
2014-07-09 18:06:15 -04:00
2014-11-13 17:31:22 -05:00
mceScroll ( key ) ;
}
2014-09-11 21:21:15 -04:00
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Makes sure the cursor is always visible in the editor .
*
* Makes sure the cursor is kept between the toolbars of the editor and scrolls
* the window when the cursor moves out of the viewport to a wpview .
* Setting a buffer > 0 will prevent the browser default .
* Some browsers will scroll to the middle ,
* others to the top / bottom of the * window * when moving the cursor out of the viewport .
*
* @ since 4.1 . 0
*
* @ param { string } key The key code of the pressed key .
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function mceScroll ( key ) {
var offset = mceGetCursorOffset ( ) ,
buffer = 50 ,
cursorTop , cursorBottom , editorTop , editorBottom ;
2014-08-24 19:12:15 -04:00
2017-08-24 13:48:45 -04:00
// Don't scroll if there is no offset.
2014-11-13 17:31:22 -05:00
if ( ! offset ) {
return ;
2014-09-03 05:58:16 -04:00
}
2017-08-24 13:48:45 -04:00
// Determine the cursorTop based on the offset and the top of the editor iframe.
2014-11-13 17:31:22 -05:00
cursorTop = offset . top + editor . iframeElement . getBoundingClientRect ( ) . top ;
2017-08-24 13:48:45 -04:00
// Determine the cursorBottom based on the cursorTop and offset height.
2014-11-13 17:31:22 -05:00
cursorBottom = cursorTop + offset . height ;
2017-08-24 13:48:45 -04:00
// Subtract the buffer from the cursorTop.
2014-11-13 17:31:22 -05:00
cursorTop = cursorTop - buffer ;
2017-08-24 13:48:45 -04:00
// Add the buffer to the cursorBottom.
2014-11-13 17:31:22 -05:00
cursorBottom = cursorBottom + buffer ;
editorTop = heights . adminBarHeight + heights . toolsHeight + heights . menuBarHeight + heights . visualTopHeight ;
2017-08-24 13:48:45 -04:00
/ *
* Set the editorBottom based on the window Height , and add the bottomHeight and statusBarHeight if the
* advanced editor is enabled .
* /
2014-11-13 17:31:22 -05:00
editorBottom = heights . windowHeight - ( advanced ? heights . bottomHeight + heights . statusBarHeight : 0 ) ;
2014-08-24 19:12:15 -04:00
2017-08-24 13:48:45 -04:00
// Don't scroll if the node is taller than the visible part of the editor.
2014-11-13 17:31:22 -05:00
if ( editorBottom - editorTop < offset . height ) {
return ;
}
2014-07-09 18:06:15 -04:00
2017-08-24 13:48:45 -04:00
/ *
* If the cursorTop is smaller than the editorTop and the up , left
* or backspace key is pressed , scroll the editor to the position defined
* by the cursorTop , pageYOffset and editorTop .
* /
2014-11-13 17:31:22 -05:00
if ( cursorTop < editorTop && ( key === VK . UP || key === VK . LEFT || key === VK . BACKSPACE ) ) {
window . scrollTo ( window . pageXOffset , cursorTop + window . pageYOffset - editorTop ) ;
2017-08-24 13:48:45 -04:00
/ *
* If any other key is pressed or the cursorTop is bigger than the editorTop ,
* scroll the editor to the position defined by the cursorBottom ,
* pageYOffset and editorBottom .
* /
2014-11-13 17:31:22 -05:00
} else if ( cursorBottom > editorBottom ) {
window . scrollTo ( window . pageXOffset , cursorBottom + window . pageYOffset - editorBottom ) ;
}
}
2014-09-11 21:21:15 -04:00
2017-08-24 13:48:45 -04:00
/ * *
* @ summary If the editor is fullscreen , calls adjust .
*
* @ since 4.1 . 0
*
* @ param { event } event The FullscreenStateChanged event .
*
* @ returns { void }
* /
2014-11-25 21:50:24 -05:00
function mceFullscreenToggled ( event ) {
2017-08-24 13:48:45 -04:00
// event.state is true if the editor is fullscreen.
2014-11-25 21:50:24 -05:00
if ( ! event . state ) {
adjust ( ) ;
}
}
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Shows the editor when scrolled .
*
* Binds the hideFloatPanels function on the window scroll . mce - float - panels event .
* Executes the wpAutoResize on the active editor .
*
* @ since 4.0 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function mceShow ( ) {
$window . on ( 'scroll.mce-float-panels' , hideFloatPanels ) ;
2014-07-31 22:43:17 -04:00
2014-11-13 17:31:22 -05:00
setTimeout ( function ( ) {
editor . execCommand ( 'wpAutoResize' ) ;
adjust ( ) ;
} , 300 ) ;
}
2014-09-11 21:21:15 -04:00
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Resizes the editor .
*
* Removes all functions from the window scroll . mce - float - panels event .
* Resizes the text editor and scrolls to a position based on the pageXOffset and adminBarHeight .
*
* @ since 4.0 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function mceHide ( ) {
$window . off ( 'scroll.mce-float-panels' ) ;
2014-07-31 22:43:17 -04:00
2014-11-13 17:31:22 -05:00
setTimeout ( function ( ) {
var top = $contentWrap . offset ( ) . top ;
2014-07-09 18:06:15 -04:00
2014-11-13 17:31:22 -05:00
if ( window . pageYOffset > top ) {
window . scrollTo ( window . pageXOffset , top - heights . adminBarHeight ) ;
}
2014-07-09 18:06:15 -04:00
2014-11-13 17:31:22 -05:00
textEditorResize ( ) ;
adjust ( ) ;
} , 100 ) ;
2014-07-09 18:06:15 -04:00
2014-11-13 17:31:22 -05:00
adjust ( ) ;
}
2014-08-24 23:43:17 -04:00
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Toggles advanced states .
*
* @ since 4.1 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function toggleAdvanced ( ) {
advanced = ! advanced ;
}
2014-07-09 18:06:15 -04:00
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Binds events of the editor and window .
*
* @ since 4.0 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
mceBind = function ( ) {
editor . on ( 'keyup' , mceKeyup ) ;
editor . on ( 'show' , mceShow ) ;
editor . on ( 'hide' , mceHide ) ;
editor . on ( 'wp-toolbar-toggle' , toggleAdvanced ) ;
2017-08-24 13:48:45 -04:00
2014-11-13 17:31:22 -05:00
// Adjust when the editor resizes.
editor . on ( 'setcontent wp-autoresize wp-toolbar-toggle' , adjust ) ;
2017-08-24 13:48:45 -04:00
2014-11-25 21:50:24 -05:00
// Don't hide the caret after undo/redo.
2014-11-13 17:31:22 -05:00
editor . on ( 'undo redo' , mceScroll ) ;
2017-08-24 13:48:45 -04:00
2014-11-25 21:50:24 -05:00
// Adjust when exiting TinyMCE's fullscreen mode.
editor . on ( 'FullscreenStateChanged' , mceFullscreenToggled ) ;
2014-11-13 17:31:22 -05:00
$window . off ( 'scroll.mce-float-panels' ) . on ( 'scroll.mce-float-panels' , hideFloatPanels ) ;
} ;
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Unbinds the events of the editor and window .
*
* @ since 4.0 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
mceUnbind = function ( ) {
editor . off ( 'keyup' , mceKeyup ) ;
editor . off ( 'show' , mceShow ) ;
editor . off ( 'hide' , mceHide ) ;
editor . off ( 'wp-toolbar-toggle' , toggleAdvanced ) ;
editor . off ( 'setcontent wp-autoresize wp-toolbar-toggle' , adjust ) ;
editor . off ( 'undo redo' , mceScroll ) ;
2014-11-25 21:50:24 -05:00
editor . off ( 'FullscreenStateChanged' , mceFullscreenToggled ) ;
2014-11-13 17:31:22 -05:00
$window . off ( 'scroll.mce-float-panels' ) ;
} ;
if ( $wrap . hasClass ( 'wp-editor-expand' ) ) {
2017-08-24 13:48:45 -04:00
// Adjust "immediately".
2014-11-13 17:31:22 -05:00
mceBind ( ) ;
initialResize ( adjust ) ;
}
} ) ;
2014-07-09 18:06:15 -04:00
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Adjusts the toolbars heights and positions .
*
* Adjusts the toolbar heights and positions based on the scroll position on the page ,
* the active editor mode and the heights of the editor , admin bar and side bar .
*
* @ since 4.0 . 0
*
* @ param { event } event The event that calls this function .
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function adjust ( event ) {
2017-08-24 13:48:45 -04:00
// Makes sure we're not in fullscreen mode.
2014-11-13 17:31:22 -05:00
if ( fullscreen && fullscreen . settings . visible ) {
return ;
}
2014-08-17 20:35:18 -04:00
2014-11-13 17:31:22 -05:00
var windowPos = $window . scrollTop ( ) ,
2014-11-26 20:00:25 -05:00
type = event && event . type ,
2014-11-13 17:31:22 -05:00
resize = type !== 'scroll' ,
2015-02-06 17:25:23 -05:00
visual = mceEditor && ! mceEditor . isHidden ( ) ,
2014-11-13 17:31:22 -05:00
buffer = autoresizeMinHeight ,
postBodyTop = $postBody . offset ( ) . top ,
borderWidth = 1 ,
contentWrapWidth = $contentWrap . width ( ) ,
$top , $editor , sidebarTop , footerTop , canPin ,
topPos , topHeight , editorPos , editorHeight ;
2017-08-24 13:48:45 -04:00
/ *
* Refresh the heights if type isn 't ' scroll '
* or heights . windowHeight isn ' t set .
* /
2014-11-13 17:31:22 -05:00
if ( resize || ! heights . windowHeight ) {
getHeights ( ) ;
}
2014-08-24 01:11:16 -04:00
2017-08-24 13:48:45 -04:00
// Resize on resize event when the editor is in text mode.
2014-11-13 17:31:22 -05:00
if ( ! visual && type === 'resize' ) {
textEditorResize ( ) ;
}
2014-08-24 01:11:16 -04:00
2014-11-13 17:31:22 -05:00
if ( visual ) {
$top = $visualTop ;
$editor = $visualEditor ;
topHeight = heights . visualTopHeight ;
} else {
$top = $textTop ;
$editor = $textEditor ;
topHeight = heights . textTopHeight ;
}
2014-07-09 18:43:14 -04:00
2017-08-24 13:48:45 -04:00
// Return if TinyMCE is still intializing.
2015-02-06 17:25:23 -05:00
if ( ! visual && ! $top . length ) {
return ;
}
2014-11-13 17:31:22 -05:00
topPos = $top . parent ( ) . offset ( ) . top ;
editorPos = $editor . offset ( ) . top ;
editorHeight = $editor . outerHeight ( ) ;
2014-08-24 01:11:16 -04:00
2017-08-24 13:48:45 -04:00
/ *
* If in visual mode , checks if the editorHeight is greater than the autoresizeMinHeight + topHeight .
* If not in visual mode , checks if the editorHeight is greater than the autoresizeMinHeight + 20.
* /
2014-11-13 17:31:22 -05:00
canPin = visual ? autoresizeMinHeight + topHeight : autoresizeMinHeight + 20 ; // 20px from textarea padding
canPin = editorHeight > ( canPin + 5 ) ;
2014-08-17 20:35:18 -04:00
2014-11-13 17:31:22 -05:00
if ( ! canPin ) {
if ( resize ) {
2014-08-17 20:35:18 -04:00
$tools . css ( {
position : 'absolute' ,
top : 0 ,
width : contentWrapWidth
} ) ;
2014-08-24 01:11:16 -04:00
if ( visual && $menuBar . length ) {
$menuBar . css ( {
position : 'absolute' ,
top : 0 ,
width : contentWrapWidth - ( borderWidth * 2 )
} ) ;
}
2014-08-17 20:35:18 -04:00
$top . css ( {
position : 'absolute' ,
2014-08-24 01:11:16 -04:00
top : heights . menuBarHeight ,
2014-08-17 20:35:18 -04:00
width : contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top . outerWidth ( ) - $top . width ( ) ) )
} ) ;
2014-11-13 17:31:22 -05:00
2015-01-09 20:32:26 -05:00
$statusBar . attr ( 'style' , advanced ? '' : 'visibility: hidden;' ) ;
$bottom . attr ( 'style' , '' ) ;
2014-11-13 17:31:22 -05:00
}
} else {
2017-08-24 13:48:45 -04:00
// Check if the top is not already in a fixed position.
2014-11-13 17:31:22 -05:00
if ( ( ! fixedTop || resize ) &&
( windowPos >= ( topPos - heights . toolsHeight - heights . adminBarHeight ) &&
windowPos <= ( topPos - heights . toolsHeight - heights . adminBarHeight + editorHeight - buffer ) ) ) {
fixedTop = true ;
2014-08-17 20:35:18 -04:00
$tools . css ( {
2014-11-13 17:31:22 -05:00
position : 'fixed' ,
top : heights . adminBarHeight ,
2014-08-17 20:35:18 -04:00
width : contentWrapWidth
} ) ;
2014-08-24 01:11:16 -04:00
if ( visual && $menuBar . length ) {
$menuBar . css ( {
2014-11-13 17:31:22 -05:00
position : 'fixed' ,
top : heights . adminBarHeight + heights . toolsHeight ,
width : contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top . outerWidth ( ) - $top . width ( ) ) )
2014-08-24 01:11:16 -04:00
} ) ;
}
$top . css ( {
2014-11-13 17:31:22 -05:00
position : 'fixed' ,
top : heights . adminBarHeight + heights . toolsHeight + heights . menuBarHeight ,
2014-08-24 01:11:16 -04:00
width : contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top . outerWidth ( ) - $top . width ( ) ) )
} ) ;
2017-08-24 13:48:45 -04:00
// Check if the top is already in a fixed position.
2014-11-13 17:31:22 -05:00
} else if ( fixedTop || resize ) {
if ( windowPos <= ( topPos - heights . toolsHeight - heights . adminBarHeight ) ) {
fixedTop = false ;
$tools . css ( {
position : 'absolute' ,
top : 0 ,
width : contentWrapWidth
} ) ;
if ( visual && $menuBar . length ) {
$menuBar . css ( {
position : 'absolute' ,
top : 0 ,
width : contentWrapWidth - ( borderWidth * 2 )
} ) ;
}
$top . css ( {
position : 'absolute' ,
top : heights . menuBarHeight ,
width : contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top . outerWidth ( ) - $top . width ( ) ) )
} ) ;
} else if ( windowPos >= ( topPos - heights . toolsHeight - heights . adminBarHeight + editorHeight - buffer ) ) {
fixedTop = false ;
$tools . css ( {
position : 'absolute' ,
top : editorHeight - buffer ,
width : contentWrapWidth
} ) ;
if ( visual && $menuBar . length ) {
$menuBar . css ( {
position : 'absolute' ,
top : editorHeight - buffer ,
width : contentWrapWidth - ( borderWidth * 2 )
} ) ;
}
$top . css ( {
position : 'absolute' ,
top : editorHeight - buffer + heights . menuBarHeight ,
width : contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top . outerWidth ( ) - $top . width ( ) ) )
} ) ;
}
2014-08-17 20:35:18 -04:00
}
2014-07-09 18:06:15 -04:00
2017-08-24 13:48:45 -04:00
// Check if the bottom is not already in a fixed position.
2014-11-13 17:31:22 -05:00
if ( ( ! fixedBottom || ( resize && advanced ) ) &&
2017-08-24 13:48:45 -04:00
// Add borderWidth for the border around the .wp-editor-container.
2014-11-13 17:31:22 -05:00
( windowPos + heights . windowHeight ) <= ( editorPos + editorHeight + heights . bottomHeight + heights . statusBarHeight + borderWidth ) ) {
2014-07-09 18:06:15 -04:00
2014-11-26 20:00:25 -05:00
if ( event && event . deltaHeight > 0 && event . deltaHeight < 100 ) {
2014-11-13 17:31:22 -05:00
window . scrollBy ( 0 , event . deltaHeight ) ;
2016-05-30 16:32:30 -04:00
} else if ( visual && advanced ) {
2014-11-13 17:31:22 -05:00
fixedBottom = true ;
2014-08-24 01:11:16 -04:00
2014-11-13 17:31:22 -05:00
$statusBar . css ( {
position : 'fixed' ,
bottom : heights . bottomHeight ,
visibility : '' ,
width : contentWrapWidth - ( borderWidth * 2 )
} ) ;
2014-08-17 20:35:18 -04:00
2014-11-13 17:31:22 -05:00
$bottom . css ( {
position : 'fixed' ,
bottom : 0 ,
width : contentWrapWidth
} ) ;
}
} else if ( ( ! advanced && fixedBottom ) ||
( ( fixedBottom || resize ) &&
( windowPos + heights . windowHeight ) > ( editorPos + editorHeight + heights . bottomHeight + heights . statusBarHeight - borderWidth ) ) ) {
fixedBottom = false ;
2014-07-23 21:33:15 -04:00
2015-01-09 20:32:26 -05:00
$statusBar . attr ( 'style' , advanced ? '' : 'visibility: hidden;' ) ;
$bottom . attr ( 'style' , '' ) ;
2014-11-13 17:31:22 -05:00
}
}
2014-08-14 23:17:15 -04:00
2017-08-24 13:48:45 -04:00
// The postbox container is positioned with @media from CSS. Ensure it is pinned on the side.
if ( $postboxContainer . width ( ) < 300 && heights . windowWidth > 600 &&
// Check if the sidebar is not taller than the document height.
$document . height ( ) > ( $sideSortables . height ( ) + postBodyTop + 120 ) &&
// Check if the editor is taller than the viewport.
heights . windowHeight < editorHeight ) {
2014-11-13 17:31:22 -05:00
if ( ( heights . sideSortablesHeight + pinnedToolsTop + sidebarBottom ) > heights . windowHeight || fixedSideTop || fixedSideBottom ) {
2017-08-24 13:48:45 -04:00
// Reset the sideSortables style when scrolling to the top.
2014-11-13 17:31:22 -05:00
if ( windowPos + pinnedToolsTop <= postBodyTop ) {
$sideSortables . attr ( 'style' , '' ) ;
fixedSideTop = fixedSideBottom = false ;
} else {
2017-08-24 13:48:45 -04:00
// When scrolling down.
2014-11-13 17:31:22 -05:00
if ( windowPos > lastScrollPosition ) {
if ( fixedSideTop ) {
2017-08-24 13:48:45 -04:00
// Let it scroll.
2014-11-13 17:31:22 -05:00
fixedSideTop = false ;
sidebarTop = $sideSortables . offset ( ) . top - heights . adminBarHeight ;
footerTop = $footer . offset ( ) . top ;
2017-08-24 13:48:45 -04:00
// Don't get over the footer.
2014-11-13 17:31:22 -05:00
if ( footerTop < sidebarTop + heights . sideSortablesHeight + sidebarBottom ) {
sidebarTop = footerTop - heights . sideSortablesHeight - 12 ;
}
$sideSortables . css ( {
position : 'absolute' ,
top : sidebarTop ,
bottom : ''
} ) ;
} else if ( ! fixedSideBottom && heights . sideSortablesHeight + $sideSortables . offset ( ) . top + sidebarBottom < windowPos + heights . windowHeight ) {
2017-08-24 13:48:45 -04:00
// Pin the bottom.
2014-11-13 17:31:22 -05:00
fixedSideBottom = true ;
$sideSortables . css ( {
position : 'fixed' ,
top : 'auto' ,
bottom : sidebarBottom
} ) ;
}
2017-08-24 13:48:45 -04:00
// When scrolling up.
2014-11-13 17:31:22 -05:00
} else if ( windowPos < lastScrollPosition ) {
if ( fixedSideBottom ) {
2017-08-24 13:48:45 -04:00
// Let it scroll.
2014-11-13 17:31:22 -05:00
fixedSideBottom = false ;
sidebarTop = $sideSortables . offset ( ) . top - sidebarBottom ;
footerTop = $footer . offset ( ) . top ;
2017-08-24 13:48:45 -04:00
// Don't get over the footer.
2014-11-13 17:31:22 -05:00
if ( footerTop < sidebarTop + heights . sideSortablesHeight + sidebarBottom ) {
sidebarTop = footerTop - heights . sideSortablesHeight - 12 ;
}
$sideSortables . css ( {
position : 'absolute' ,
top : sidebarTop ,
bottom : ''
} ) ;
} else if ( ! fixedSideTop && $sideSortables . offset ( ) . top >= windowPos + pinnedToolsTop ) {
2017-08-24 13:48:45 -04:00
// Pin the top.
2014-11-13 17:31:22 -05:00
fixedSideTop = true ;
$sideSortables . css ( {
position : 'fixed' ,
top : pinnedToolsTop ,
bottom : ''
} ) ;
2014-08-14 23:17:15 -04:00
}
}
}
2014-11-13 17:31:22 -05:00
} else {
2017-08-24 13:48:45 -04:00
// If the sidebar container is smaller than the viewport, then pin/unpin the top when scrolling.
2014-11-13 17:31:22 -05:00
if ( windowPos >= ( postBodyTop - pinnedToolsTop ) ) {
$sideSortables . css ( {
position : 'fixed' ,
top : pinnedToolsTop
} ) ;
} else {
$sideSortables . attr ( 'style' , '' ) ;
}
fixedSideTop = fixedSideBottom = false ;
2014-08-14 23:17:15 -04:00
}
2014-11-13 17:31:22 -05:00
lastScrollPosition = windowPos ;
2014-08-14 23:17:15 -04:00
} else {
2014-11-13 17:31:22 -05:00
$sideSortables . attr ( 'style' , '' ) ;
fixedSideTop = fixedSideBottom = false ;
}
2014-09-01 14:49:15 -04:00
2014-11-13 17:31:22 -05:00
if ( resize ) {
$contentWrap . css ( {
paddingTop : heights . toolsHeight
} ) ;
if ( visual ) {
$visualEditor . css ( {
paddingTop : heights . visualTopHeight + heights . menuBarHeight
2014-08-14 23:17:15 -04:00
} ) ;
} else {
2014-11-13 17:31:22 -05:00
$textEditor . css ( {
marginTop : heights . textTopHeight
} ) ;
2014-08-14 23:17:15 -04:00
}
2014-11-13 17:31:22 -05:00
}
}
2014-08-14 23:17:15 -04:00
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Resizes the editor and adjusts the toolbars .
*
* @ since 4.0 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function fullscreenHide ( ) {
textEditorResize ( ) ;
adjust ( ) ;
}
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Runs the passed function with 500 ms intervals .
*
* @ since 4.0 . 0
*
* @ param { function } callback The function to run in the timeout .
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function initialResize ( callback ) {
for ( var i = 1 ; i < 6 ; i ++ ) {
setTimeout ( callback , 500 * i ) ;
2014-08-14 23:17:15 -04:00
}
2014-11-13 17:31:22 -05:00
}
2014-08-14 23:17:15 -04:00
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Runs adjust after 100 ms .
*
* @ since 4.0 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function afterScroll ( ) {
clearTimeout ( scrollTimer ) ;
scrollTimer = setTimeout ( adjust , 100 ) ;
2014-08-14 23:17:15 -04:00
}
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Binds editor expand events on elements .
*
* @ since 4.0 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function on ( ) {
2017-08-24 13:48:45 -04:00
/ *
* Scroll to the top when triggering this from JS .
* Ensure the toolbars are pinned properly .
* /
2014-11-13 17:31:22 -05:00
if ( window . pageYOffset && window . pageYOffset > pageYOffsetAtTop ) {
window . scrollTo ( window . pageXOffset , 0 ) ;
}
$wrap . addClass ( 'wp-editor-expand' ) ;
// Adjust when the window is scrolled or resized.
$window . on ( 'scroll.editor-expand resize.editor-expand' , function ( event ) {
adjust ( event . type ) ;
afterScroll ( ) ;
2014-07-23 21:33:15 -04:00
} ) ;
2017-08-24 13:48:45 -04:00
/ *
* Adjust when collapsing the menu , changing the columns
* or changing the body class .
* /
2014-11-13 17:31:22 -05:00
$document . on ( 'wp-collapse-menu.editor-expand postboxes-columnchange.editor-expand editor-classchange.editor-expand' , adjust )
2016-06-08 18:37:29 -04:00
. on ( 'postbox-toggled.editor-expand postbox-moved.editor-expand' , function ( ) {
2014-11-13 17:31:22 -05:00
if ( ! fixedSideTop && ! fixedSideBottom && window . pageYOffset > pinnedToolsTop ) {
fixedSideBottom = true ;
window . scrollBy ( 0 , - 1 ) ;
adjust ( ) ;
window . scrollBy ( 0 , 1 ) ;
}
adjust ( ) ;
} ) . on ( 'wp-window-resized.editor-expand' , function ( ) {
if ( mceEditor && ! mceEditor . isHidden ( ) ) {
mceEditor . execCommand ( 'wpAutoResize' ) ;
} else {
textEditorResize ( ) ;
}
} ) ;
$textEditor . on ( 'focus.editor-expand input.editor-expand propertychange.editor-expand' , textEditorResize ) ;
mceBind ( ) ;
2017-08-24 13:48:45 -04:00
// Adjust when entering or exiting fullscreen mode.
2014-11-13 17:31:22 -05:00
fullscreen && fullscreen . pubsub . subscribe ( 'hidden' , fullscreenHide ) ;
if ( mceEditor ) {
mceEditor . settings . wp _autoresize _on = true ;
mceEditor . execCommand ( 'wpAutoResizeOn' ) ;
if ( ! mceEditor . isHidden ( ) ) {
mceEditor . execCommand ( 'wpAutoResize' ) ;
}
}
if ( ! mceEditor || mceEditor . isHidden ( ) ) {
textEditorResize ( ) ;
}
adjust ( ) ;
$document . trigger ( 'editor-expand-on' ) ;
}
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Unbinds editor expand events .
*
* @ since 4.0 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function off ( ) {
2014-12-20 14:33:23 -05:00
var height = parseInt ( window . getUserSetting ( 'ed_size' , 300 ) , 10 ) ;
if ( height < 50 ) {
height = 50 ;
} else if ( height > 5000 ) {
height = 5000 ;
}
2014-11-13 17:31:22 -05:00
2017-08-24 13:48:45 -04:00
/ *
* Scroll to the top when triggering this from JS .
* Ensure the toolbars are reset properly .
* /
2014-11-13 17:31:22 -05:00
if ( window . pageYOffset && window . pageYOffset > pageYOffsetAtTop ) {
window . scrollTo ( window . pageXOffset , 0 ) ;
}
$wrap . removeClass ( 'wp-editor-expand' ) ;
$window . off ( '.editor-expand' ) ;
$document . off ( '.editor-expand' ) ;
$textEditor . off ( '.editor-expand' ) ;
mceUnbind ( ) ;
2017-08-24 13:48:45 -04:00
// Adjust when entering or exiting fullscreen mode.
2014-11-13 17:31:22 -05:00
fullscreen && fullscreen . pubsub . unsubscribe ( 'hidden' , fullscreenHide ) ;
// Reset all css
$ . each ( [ $visualTop , $textTop , $tools , $menuBar , $bottom , $statusBar , $contentWrap , $visualEditor , $textEditor , $sideSortables ] , function ( i , element ) {
element && element . attr ( 'style' , '' ) ;
} ) ;
fixedTop = fixedBottom = fixedSideTop = fixedSideBottom = false ;
if ( mceEditor ) {
mceEditor . settings . wp _autoresize _on = false ;
mceEditor . execCommand ( 'wpAutoResizeOff' ) ;
if ( ! mceEditor . isHidden ( ) ) {
$textEditor . hide ( ) ;
if ( height ) {
mceEditor . theme . resizeTo ( null , height ) ;
}
}
}
2017-08-24 13:48:45 -04:00
// If there is a height found in the user setting.
2014-11-13 17:31:22 -05:00
if ( height ) {
$textEditor . height ( height ) ;
}
$document . trigger ( 'editor-expand-off' ) ;
}
2017-08-24 13:48:45 -04:00
// Start on load.
2014-11-13 17:31:22 -05:00
if ( $wrap . hasClass ( 'wp-editor-expand' ) ) {
on ( ) ;
2017-08-24 13:48:45 -04:00
// Resize just after CSS has fully loaded and QuickTags is ready.
2014-11-13 17:31:22 -05:00
if ( $contentWrap . hasClass ( 'html-active' ) ) {
initialResize ( function ( ) {
adjust ( ) ;
textEditorResize ( ) ;
2014-07-23 21:33:15 -04:00
} ) ;
2014-11-13 17:31:22 -05:00
}
}
2017-08-24 13:48:45 -04:00
// Show the on/off checkbox.
2014-11-13 17:31:22 -05:00
$ ( '#adv-settings .editor-expand' ) . show ( ) ;
$ ( '#editor-expand-toggle' ) . on ( 'change.editor-expand' , function ( ) {
if ( $ ( this ) . prop ( 'checked' ) ) {
on ( ) ;
window . setUserSetting ( 'editor_expand' , 'on' ) ;
2014-07-23 21:33:15 -04:00
} else {
2014-11-13 17:31:22 -05:00
off ( ) ;
window . setUserSetting ( 'editor_expand' , 'off' ) ;
}
} ) ;
2017-08-24 13:48:45 -04:00
// Expose on() and off().
2014-11-13 17:31:22 -05:00
window . editorExpand = {
on : on ,
off : off
} ;
} ) ;
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Handles the distraction free writing of TinyMCE .
*
* @ since 4.1 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
$ ( function ( ) {
var $body = $ ( document . body ) ,
$wrap = $ ( '#wpcontent' ) ,
$editor = $ ( '#post-body-content' ) ,
$title = $ ( '#title' ) ,
$content = $ ( '#content' ) ,
$overlay = $ ( document . createElement ( 'DIV' ) ) ,
$slug = $ ( '#edit-slug-box' ) ,
$slugFocusEl = $slug . find ( 'a' )
. add ( $slug . find ( 'button' ) )
. add ( $slug . find ( 'input' ) ) ,
$menuWrap = $ ( '#adminmenuwrap' ) ,
$editorWindow = $ ( ) ,
$editorIframe = $ ( ) ,
_isActive = window . getUserSetting ( 'editor_expand' , 'on' ) === 'on' ,
2014-11-25 21:50:24 -05:00
_isOn = _isActive ? window . getUserSetting ( 'post_dfw' ) === 'on' : false ,
2014-11-13 17:31:22 -05:00
traveledX = 0 ,
traveledY = 0 ,
buffer = 20 ,
faded , fadedAdminBar , fadedSlug ,
editorRect , x , y , mouseY , scrollY ,
focusLostTimer , overlayTimer , editorHasFocus ;
$body . append ( $overlay ) ;
$overlay . css ( {
display : 'none' ,
position : 'fixed' ,
top : $adminBar . height ( ) ,
right : 0 ,
bottom : 0 ,
left : 0 ,
'z-index' : 9997
} ) ;
$editor . css ( {
position : 'relative'
} ) ;
$window . on ( 'mousemove.focus' , function ( event ) {
mouseY = event . pageY ;
} ) ;
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Recalculates the bottom and right position of the editor in the DOM .
*
* @ since 4.1 . 0
*
* @ returns { void }
* /
2014-12-11 04:34:26 -05:00
function recalcEditorRect ( ) {
editorRect = $editor . offset ( ) ;
editorRect . right = editorRect . left + $editor . outerWidth ( ) ;
editorRect . bottom = editorRect . top + $editor . outerHeight ( ) ;
}
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Activates the distraction free writing mode .
*
* @ since 4.1 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function activate ( ) {
if ( ! _isActive ) {
_isActive = true ;
2014-08-17 21:13:16 -04:00
2014-11-13 17:31:22 -05:00
$document . trigger ( 'dfw-activate' ) ;
2014-11-27 20:44:22 -05:00
$content . on ( 'keydown.focus-shortcut' , toggleViaKeyboard ) ;
2014-07-23 21:33:15 -04:00
}
}
2014-07-09 18:06:15 -04:00
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Deactivates the distraction free writing mode .
*
* @ since 4.1 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function deactivate ( ) {
if ( _isActive ) {
off ( ) ;
2014-07-31 22:43:17 -04:00
2014-11-13 17:31:22 -05:00
_isActive = false ;
$document . trigger ( 'dfw-deactivate' ) ;
2014-11-27 20:44:22 -05:00
$content . off ( 'keydown.focus-shortcut' ) ;
2014-11-13 17:31:22 -05:00
}
2014-07-23 21:33:15 -04:00
}
2014-11-13 17:31:22 -05:00
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Returns _isActive .
*
* @ since 4.1 . 0
*
* @ returns { boolean } Returns true is _isActive is true .
* /
2014-11-13 17:31:22 -05:00
function isActive ( ) {
return _isActive ;
2014-07-31 22:43:17 -04:00
}
2014-07-09 18:06:15 -04:00
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Binds events on the editor for distraction free writing .
*
* @ since 4.1 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function on ( ) {
if ( ! _isOn && _isActive ) {
_isOn = true ;
2014-07-09 18:06:15 -04:00
2014-11-13 17:31:22 -05:00
$content . on ( 'keydown.focus' , fadeOut ) ;
2014-07-23 21:33:15 -04:00
2014-11-13 17:31:22 -05:00
$title . add ( $content ) . on ( 'blur.focus' , maybeFadeIn ) ;
2014-08-17 20:35:18 -04:00
2014-11-13 17:31:22 -05:00
fadeOut ( ) ;
2014-11-25 21:50:24 -05:00
window . setUserSetting ( 'post_dfw' , 'on' ) ;
2014-11-13 17:31:22 -05:00
$document . trigger ( 'dfw-on' ) ;
}
}
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Unbinds events on the editor for distraction free writing .
*
* @ since 4.1 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function off ( ) {
if ( _isOn ) {
_isOn = false ;
2014-07-31 22:43:17 -04:00
2014-11-13 17:31:22 -05:00
$title . add ( $content ) . off ( '.focus' ) ;
2014-07-31 22:43:17 -04:00
2014-11-13 17:31:22 -05:00
fadeIn ( ) ;
2014-07-31 22:43:17 -04:00
2014-11-13 17:31:22 -05:00
$editor . off ( '.focus' ) ;
2014-07-31 22:43:17 -04:00
2014-11-25 21:50:24 -05:00
window . setUserSetting ( 'post_dfw' , 'off' ) ;
2014-11-13 17:31:22 -05:00
$document . trigger ( 'dfw-off' ) ;
2014-07-31 22:43:17 -04:00
}
}
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Binds or unbinds the editor expand events .
*
* @ since 4.1 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function toggle ( ) {
2014-11-27 20:44:22 -05:00
if ( _isOn ) {
off ( ) ;
} else {
on ( ) ;
}
2014-07-31 22:43:17 -04:00
}
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Returns the value of _isOn .
*
* @ since 4.1 . 0
*
* @ returns { boolean } Returns true if _isOn is true .
* /
2014-11-13 17:31:22 -05:00
function isOn ( ) {
return _isOn ;
}
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Fades out all elements except for the editor .
*
* The fading is done based on key presses and mouse movements .
* Also calls the fadeIn on certain key presses
* or if the mouse leaves the editor .
*
* @ since 4.1 . 0
*
* @ param event The event that triggers this function .
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function fadeOut ( event ) {
2016-03-15 22:48:25 -04:00
var isMac ,
key = event && event . keyCode ;
2014-11-13 17:31:22 -05:00
2016-03-15 22:48:25 -04:00
if ( window . navigator . platform ) {
isMac = ( window . navigator . platform . indexOf ( 'Mac' ) > - 1 ) ;
}
2017-08-24 13:48:45 -04:00
// Fade in and returns on Escape and keyboard shortcut Alt+Shift+W and Ctrl+Opt+W.
2016-03-15 22:48:25 -04:00
if ( key === 27 || ( key === 87 && event . altKey && ( ( ! isMac && event . shiftKey ) || ( isMac && event . ctrlKey ) ) ) ) {
2014-11-28 21:45:22 -05:00
fadeIn ( event ) ;
2014-11-13 17:31:22 -05:00
return ;
}
2017-08-24 13:48:45 -04:00
// Return if any of the following keys or combinations of keys is pressed.
2014-12-01 17:53:24 -05:00
if ( event && ( event . metaKey || ( event . ctrlKey && ! event . altKey ) || ( event . altKey && event . shiftKey ) || ( key && (
2014-11-13 17:31:22 -05:00
// Special keys ( tab, ctrl, alt, esc, arrow keys... )
( key <= 47 && key !== 8 && key !== 13 && key !== 32 && key !== 46 ) ||
// Windows keys
( key >= 91 && key <= 93 ) ||
// F keys
( key >= 112 && key <= 135 ) ||
// Num Lock, Scroll Lock, OEM
( key >= 144 && key <= 150 ) ||
// OEM or non-printable
key >= 224
) ) ) ) {
return ;
}
if ( ! faded ) {
faded = true ;
clearTimeout ( overlayTimer ) ;
overlayTimer = setTimeout ( function ( ) {
$overlay . show ( ) ;
} , 600 ) ;
$editor . css ( 'z-index' , 9998 ) ;
$overlay
2017-08-24 13:48:45 -04:00
// Always recalculate the editor area when entering the overlay with the mouse.
2014-11-13 17:31:22 -05:00
. on ( 'mouseenter.focus' , function ( ) {
2014-12-11 04:34:26 -05:00
recalcEditorRect ( ) ;
2014-11-13 17:31:22 -05:00
$window . on ( 'scroll.focus' , function ( ) {
var nScrollY = window . pageYOffset ;
2014-07-31 22:43:17 -04:00
2014-11-13 17:31:22 -05:00
if ( (
scrollY && mouseY &&
scrollY !== nScrollY
) && (
mouseY < editorRect . top - buffer ||
mouseY > editorRect . bottom + buffer
) ) {
fadeIn ( ) ;
}
scrollY = nScrollY ;
} ) ;
} )
. on ( 'mouseleave.focus' , function ( ) {
x = y = null ;
traveledX = traveledY = 0 ;
$window . off ( 'scroll.focus' ) ;
} )
// Fade in when the mouse moves away form the editor area.
. on ( 'mousemove.focus' , function ( event ) {
2014-12-11 04:34:26 -05:00
var nx = event . clientX ,
ny = event . clientY ,
pageYOffset = window . pageYOffset ,
pageXOffset = window . pageXOffset ;
2014-11-13 17:31:22 -05:00
if ( x && y && ( nx !== x || ny !== y ) ) {
if (
2014-12-11 04:34:26 -05:00
( ny <= y && ny < editorRect . top - pageYOffset ) ||
( ny >= y && ny > editorRect . bottom - pageYOffset ) ||
( nx <= x && nx < editorRect . left - pageXOffset ) ||
( nx >= x && nx > editorRect . right - pageXOffset )
2014-11-13 17:31:22 -05:00
) {
traveledX += Math . abs ( x - nx ) ;
traveledY += Math . abs ( y - ny ) ;
if ( (
2014-12-11 04:34:26 -05:00
ny <= editorRect . top - buffer - pageYOffset ||
ny >= editorRect . bottom + buffer - pageYOffset ||
nx <= editorRect . left - buffer - pageXOffset ||
nx >= editorRect . right + buffer - pageXOffset
2014-11-13 17:31:22 -05:00
) && (
traveledX > 10 ||
traveledY > 10
) ) {
fadeIn ( ) ;
x = y = null ;
traveledX = traveledY = 0 ;
return ;
}
} else {
traveledX = traveledY = 0 ;
}
}
x = nx ;
y = ny ;
} )
2017-08-24 13:48:45 -04:00
// When the overlay is touched, fade in and cancel the event.
2014-11-13 17:31:22 -05:00
. on ( 'touchstart.focus' , function ( event ) {
event . preventDefault ( ) ;
fadeIn ( ) ;
} ) ;
$editor . off ( 'mouseenter.focus' ) ;
if ( focusLostTimer ) {
clearTimeout ( focusLostTimer ) ;
focusLostTimer = null ;
}
$body . addClass ( 'focus-on' ) . removeClass ( 'focus-off' ) ;
}
2014-07-31 22:43:17 -04:00
2014-11-13 17:31:22 -05:00
fadeOutAdminBar ( ) ;
fadeOutSlug ( ) ;
2014-07-31 22:43:17 -04:00
}
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Fades all elements back in .
*
* @ since 4.1 . 0
*
* @ param event The event that triggers this function .
*
* @ returns { void }
* /
2014-11-28 21:45:22 -05:00
function fadeIn ( event ) {
2014-11-13 17:31:22 -05:00
if ( faded ) {
faded = false ;
2014-07-31 22:43:17 -04:00
2014-11-13 17:31:22 -05:00
clearTimeout ( overlayTimer ) ;
2014-07-31 22:43:17 -04:00
2014-11-13 17:31:22 -05:00
overlayTimer = setTimeout ( function ( ) {
$overlay . hide ( ) ;
} , 200 ) ;
2014-07-31 22:43:17 -04:00
2014-11-13 17:31:22 -05:00
$editor . css ( 'z-index' , '' ) ;
$overlay . off ( 'mouseenter.focus mouseleave.focus mousemove.focus touchstart.focus' ) ;
2014-11-28 21:45:22 -05:00
/ *
* When fading in , temporarily watch for refocus and fade back out - helps
* with 'accidental' editor exits with the mouse . When fading in and the event
* is a key event ( Escape or Alt + Shift + W ) don ' t watch for refocus .
* /
if ( 'undefined' === typeof event ) {
$editor . on ( 'mouseenter.focus' , function ( ) {
if ( $ . contains ( $editor . get ( 0 ) , document . activeElement ) || editorHasFocus ) {
fadeOut ( ) ;
}
} ) ;
}
2014-07-31 22:43:17 -04:00
2014-11-13 17:31:22 -05:00
focusLostTimer = setTimeout ( function ( ) {
focusLostTimer = null ;
$editor . off ( 'mouseenter.focus' ) ;
} , 1000 ) ;
2014-08-14 23:17:15 -04:00
2014-11-13 17:31:22 -05:00
$body . addClass ( 'focus-off' ) . removeClass ( 'focus-on' ) ;
}
fadeInAdminBar ( ) ;
fadeInSlug ( ) ;
}
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Fades in if the focused element based on it position .
*
* @ since 4.1 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function maybeFadeIn ( ) {
setTimeout ( function ( ) {
var position = document . activeElement . compareDocumentPosition ( $editor . get ( 0 ) ) ;
2014-07-31 22:43:17 -04:00
2014-11-13 17:31:22 -05:00
function hasFocus ( $el ) {
return $ . contains ( $el . get ( 0 ) , document . activeElement ) ;
}
2014-07-31 22:43:17 -04:00
2014-11-27 20:44:22 -05:00
// The focused node is before or behind the editor area, and not outside the wrap.
2014-11-13 17:31:22 -05:00
if ( ( position === 2 || position === 4 ) && ( hasFocus ( $menuWrap ) || hasFocus ( $wrap ) || hasFocus ( $footer ) ) ) {
fadeIn ( ) ;
2014-07-31 22:43:17 -04:00
}
2014-11-13 17:31:22 -05:00
} , 0 ) ;
}
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Fades out the admin bar based on focus on the admin bar .
*
* @ since 4.1 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function fadeOutAdminBar ( ) {
if ( ! fadedAdminBar && faded ) {
fadedAdminBar = true ;
$adminBar
. on ( 'mouseenter.focus' , function ( ) {
$adminBar . addClass ( 'focus-off' ) ;
} )
. on ( 'mouseleave.focus' , function ( ) {
$adminBar . removeClass ( 'focus-off' ) ;
} ) ;
2014-07-31 22:43:17 -04:00
}
}
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Fades in the admin bar .
*
* @ since 4.1 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function fadeInAdminBar ( ) {
if ( fadedAdminBar ) {
fadedAdminBar = false ;
$adminBar . off ( '.focus' ) ;
}
2014-07-31 22:43:17 -04:00
}
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Fades out the edit slug box .
*
* @ since 4.1 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function fadeOutSlug ( ) {
if ( ! fadedSlug && faded && ! $slug . find ( ':focus' ) . length ) {
fadedSlug = true ;
2014-07-31 22:43:17 -04:00
2014-11-13 17:31:22 -05:00
$slug . stop ( ) . fadeTo ( 'fast' , 0.3 ) . on ( 'mouseenter.focus' , fadeInSlug ) . off ( 'mouseleave.focus' ) ;
$slugFocusEl . on ( 'focus.focus' , fadeInSlug ) . off ( 'blur.focus' ) ;
}
2014-07-31 22:43:17 -04:00
}
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Fades in the edit slug box .
*
* @ since 4.1 . 0
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
function fadeInSlug ( ) {
if ( fadedSlug ) {
fadedSlug = false ;
$slug . stop ( ) . fadeTo ( 'fast' , 1 ) . on ( 'mouseleave.focus' , fadeOutSlug ) . off ( 'mouseenter.focus' ) ;
$slugFocusEl . on ( 'blur.focus' , fadeOutSlug ) . off ( 'focus.focus' ) ;
}
}
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Triggers the toggle on Alt + Shift + W .
*
* Keycode 87 = w .
*
* @ since 4.1 . 0
*
* @ param { event } event The event to trigger the toggle .
*
* @ returns { void }
* /
2014-11-27 20:44:22 -05:00
function toggleViaKeyboard ( event ) {
if ( event . altKey && event . shiftKey && 87 === event . keyCode ) {
toggle ( ) ;
}
}
if ( $ ( '#postdivrich' ) . hasClass ( 'wp-editor-expand' ) ) {
$content . on ( 'keydown.focus-shortcut' , toggleViaKeyboard ) ;
}
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Adds the distraction free writing button when setting up TinyMCE .
*
* @ since 4.1 . 0
*
* @ param { event } event The TinyMCE editor setup event .
* @ param { object } editor The editor to add the button to .
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
$document . on ( 'tinymce-editor-setup.focus' , function ( event , editor ) {
editor . addButton ( 'dfw' , {
active : _isOn ,
classes : 'wp-dfw btn widget' ,
disabled : ! _isActive ,
onclick : toggle ,
onPostRender : function ( ) {
var button = this ;
$document
. on ( 'dfw-activate.focus' , function ( ) {
button . disabled ( false ) ;
} )
. on ( 'dfw-deactivate.focus' , function ( ) {
button . disabled ( true ) ;
} )
. on ( 'dfw-on.focus' , function ( ) {
button . active ( true ) ;
} )
. on ( 'dfw-off.focus' , function ( ) {
button . active ( false ) ;
} ) ;
} ,
2014-12-16 05:07:23 -05:00
tooltip : 'Distraction-free writing mode' ,
2014-11-27 20:44:22 -05:00
shortcut : 'Alt+Shift+W'
2014-11-13 17:31:22 -05:00
} ) ;
2014-11-27 20:44:22 -05:00
editor . addCommand ( 'wpToggleDFW' , toggle ) ;
2016-03-12 12:44:26 -05:00
editor . addShortcut ( 'access+w' , '' , 'wpToggleDFW' ) ;
2014-11-13 17:31:22 -05:00
} ) ;
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Binds and unbinds events on the editor .
*
* @ since 4.1 . 0
*
* @ param { event } event The TinyMCE editor init event .
* @ param { object } editor The editor to bind events on .
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
$document . on ( 'tinymce-editor-init.focus' , function ( event , editor ) {
var mceBind , mceUnbind ;
function focus ( ) {
editorHasFocus = true ;
}
function blur ( ) {
editorHasFocus = false ;
}
if ( editor . id === 'content' ) {
$editorWindow = $ ( editor . getWin ( ) ) ;
$editorIframe = $ ( editor . getContentAreaContainer ( ) ) . find ( 'iframe' ) ;
mceBind = function ( ) {
editor . on ( 'keydown' , fadeOut ) ;
editor . on ( 'blur' , maybeFadeIn ) ;
editor . on ( 'focus' , focus ) ;
editor . on ( 'blur' , blur ) ;
2014-12-11 04:34:26 -05:00
editor . on ( 'wp-autoresize' , recalcEditorRect ) ;
2014-11-13 17:31:22 -05:00
} ;
mceUnbind = function ( ) {
editor . off ( 'keydown' , fadeOut ) ;
editor . off ( 'blur' , maybeFadeIn ) ;
editor . off ( 'focus' , focus ) ;
editor . off ( 'blur' , blur ) ;
2014-12-11 04:34:26 -05:00
editor . off ( 'wp-autoresize' , recalcEditorRect ) ;
2014-11-13 17:31:22 -05:00
} ;
if ( _isOn ) {
mceBind ( ) ;
}
2017-08-24 13:48:45 -04:00
// Bind and unbind based on the distraction free writing focus.
2014-11-13 17:31:22 -05:00
$document . on ( 'dfw-on.focus' , mceBind ) . on ( 'dfw-off.focus' , mceUnbind ) ;
2017-08-24 13:48:45 -04:00
// Focuse the editor when it is the target of the click event.
2015-11-12 07:04:27 -05:00
editor . on ( 'click' , function ( event ) {
2014-11-13 17:31:22 -05:00
if ( event . target === editor . getDoc ( ) . documentElement ) {
editor . focus ( ) ;
}
} ) ;
}
} ) ;
2017-08-24 13:48:45 -04:00
/ * *
* @ summary Binds events on quicktags init .
*
* @ since 4.1 . 0
*
* @ param { event } event The quicktags init event .
* @ param { object } editor The editor to bind events on .
*
* @ returns { void }
* /
2014-11-13 17:31:22 -05:00
$document . on ( 'quicktags-init' , function ( event , editor ) {
var $button ;
2017-08-24 13:48:45 -04:00
// Bind the distraction free writing events if the distraction free writing button is available.
2014-11-13 17:31:22 -05:00
if ( editor . settings . buttons && ( ',' + editor . settings . buttons + ',' ) . indexOf ( ',dfw,' ) !== - 1 ) {
$button = $ ( '#' + editor . name + '_dfw' ) ;
$ ( document )
. on ( 'dfw-activate' , function ( ) {
$button . prop ( 'disabled' , false ) ;
} )
. on ( 'dfw-deactivate' , function ( ) {
$button . prop ( 'disabled' , true ) ;
} )
. on ( 'dfw-on' , function ( ) {
$button . addClass ( 'active' ) ;
} )
. on ( 'dfw-off' , function ( ) {
$button . removeClass ( 'active' ) ;
} ) ;
}
} ) ;
$document . on ( 'editor-expand-on.focus' , activate ) . on ( 'editor-expand-off.focus' , deactivate ) ;
if ( _isOn ) {
$content . on ( 'keydown.focus' , fadeOut ) ;
$title . add ( $content ) . on ( 'blur.focus' , maybeFadeIn ) ;
2014-07-31 22:43:17 -04:00
}
2014-11-13 17:31:22 -05:00
window . wp = window . wp || { } ;
window . wp . editor = window . wp . editor || { } ;
window . wp . editor . dfw = {
activate : activate ,
deactivate : deactivate ,
isActive : isActive ,
on : on ,
off : off ,
toggle : toggle ,
isOn : isOn
} ;
} ) ;
} ) ( window , window . jQuery ) ;