From 0a73faec469857d80ad7e062f982498ad57a4afd Mon Sep 17 00:00:00 2001 From: Andrew Ozz Date: Thu, 24 Jul 2014 01:32:29 +0000 Subject: [PATCH] Editor scrolling: - Improve TinyMCE resizing when a floated block is at the end of the content. - Improve setting the padding/margin under the toolbar on loading. - Add custom event on TinyMCE resizing and use it to adjust the pinning (if needed). Part props avryl, see #28328. git-svn-id: https://develop.svn.wordpress.org/trunk@29279 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-admin/css/edit.css | 18 ++ src/wp-admin/js/editor-expand.js | 171 +++++++++--------- .../js/tinymce/plugins/wpautoresize/plugin.js | 21 ++- 3 files changed, 119 insertions(+), 91 deletions(-) diff --git a/src/wp-admin/css/edit.css b/src/wp-admin/css/edit.css index 33d65574cc..e32407f42c 100644 --- a/src/wp-admin/css/edit.css +++ b/src/wp-admin/css/edit.css @@ -378,6 +378,24 @@ td.plugin-title p { overflow: hidden; } +.wp-fullscreen-wrap #content-textarea-clone { + display: none; +} + +/* editor-expand.js override */ +.wp-fullscreen-wrap { + padding-top: 0 !important; +} + +.wp-fullscreen-wrap .wp-editor-area { + margin-top: 0 !important; +} + +.wp-fullscreen-wrap .mce-edit-area { + padding-top: 0 !important; +} +/* end editor-expand.js override */ + #timestampdiv select { height: 21px; line-height: 14px; diff --git a/src/wp-admin/js/editor-expand.js b/src/wp-admin/js/editor-expand.js index bf4ce56dc3..bc255553c8 100644 --- a/src/wp-admin/js/editor-expand.js +++ b/src/wp-admin/js/editor-expand.js @@ -41,20 +41,26 @@ jQuery( document ).ready( function($) { textEditorResize(); } ); - $textEditor.on( 'keyup', function() { - var range = document.createRange(), - start = $textEditor[0].selectionStart, - end = $textEditor[0].selectionEnd, + $textEditor.on( 'keyup', function( event ) { + var VK = jQuery.ui.keyCode, + key = event.keyCode, + range = document.createRange(), + selStart = $textEditor[0].selectionStart, + selEnd = $textEditor[0].selectionEnd, textNode = $textEditorClone[0].firstChild, windowHeight = $window.height(), + buffer = 10, offset, cursorTop, cursorBottom, editorTop, editorBottom; - if ( start && end && start !== end ) { + if ( selStart && selEnd && selStart !== selEnd ) { return; } - range.setStart( textNode, start ); - range.setEnd( textNode, end + 1 ); + // These are not TinyMCE ranges. + try { + range.setStart( textNode, selStart ); + range.setEnd( textNode, selEnd + 1 ); + } catch ( ex ) {} offset = range.getBoundingClientRect(); @@ -62,13 +68,15 @@ jQuery( document ).ready( function($) { return; } - cursorTop = offset.top; - cursorBottom = cursorTop + offset.height; - editorTop = $adminBar.outerHeight() + $textTop.outerHeight(); + cursorTop = offset.top - buffer; + cursorBottom = cursorTop + offset.height + buffer; + editorTop = $adminBar.outerHeight() + $tools.outerHeight() + $textTop.outerHeight(); editorBottom = windowHeight - $bottom.outerHeight(); - if ( cursorTop < editorTop || cursorBottom > editorBottom ) { - window.scrollTo( window.pageXOffset, cursorTop + window.pageYOffset - windowHeight / 2 ); + if ( cursorTop < editorTop && ( key === VK.UP || key === VK.LEFT || key === VK.BACKSPACE ) ) { + window.scrollTo( window.pageXOffset, cursorTop + window.pageYOffset - editorTop ); + } else if ( cursorBottom > editorBottom ) { + window.scrollTo( window.pageXOffset, cursorBottom + window.pageYOffset - editorBottom ); } } ); @@ -77,8 +85,13 @@ jQuery( document ).ready( function($) { return; } - var hiddenHeight = $textEditorClone.width( $textEditor.width() ).text( $textEditor.val() + ' ' ).height(), - textEditorHeight = $textEditor.height(); + var textEditorHeight = $textEditor.height(), + hiddenHeight; + + $textEditorClone.width( $textEditor.width() ); + $textEditorClone.text( $textEditor.val() + ' ' ); + + hiddenHeight = $textEditorClone.height(); if ( hiddenHeight < 300 ) { hiddenHeight = 300; @@ -90,7 +103,7 @@ jQuery( document ).ready( function($) { $textEditor.height( hiddenHeight ); - adjust( 'resize' ); + adjust(); } // We need to wait for TinyMCE to initialize. @@ -103,9 +116,6 @@ jQuery( document ).ready( function($) { // Copy the editor instance. editorInstance = editor; - // Resizing will be handled by the autoresize plugin. - editor.theme.resizeTo = function() {}; - // Set the minimum height to the initial viewport height. editor.settings.autoresize_min_height = 300; @@ -118,8 +128,8 @@ jQuery( document ).ready( function($) { editor.on( 'show', function() { setTimeout( function() { editor.execCommand( 'wpAutoResize' ); - adjust( 'resize' ); - }, 200 ); + adjust(); + }, 300 ); } ); // Make sure the cursor is always visible. @@ -195,58 +205,21 @@ jQuery( document ).ready( function($) { editor.on( 'hide', function() { textEditorResize(); - adjust( 'resize' ); + adjust(); } ); // Adjust when the editor resizes. - editor.on( 'nodechange setcontent keyup FullscreenStateChanged', function() { - adjust( 'resize' ); - } ); - - editor.on( 'wp-toolbar-toggle', function() { - $visualEditor.css( { - paddingTop: $visualTop.outerHeight() - } ); + editor.on( 'setcontent wp-autoresize wp-toolbar-toggle', function() { + adjust(); } ); // And adjust "immediately". // Allow some time to load CSS etc. - setTimeout( function() { - $visualEditor.css( { - paddingTop: $visualTop.outerHeight() - } ); - - adjust( 'resize' ); - }, 500 ); - } ); - - // Adjust when the window is scrolled or resized. - $window.on( 'scroll resize', function( event ) { - adjust( event.type ); - } ); - - // Adjust when exiting fullscreen mode. - fullscreen && fullscreen.pubsub.subscribe( 'hidden', function() { - adjust( 'resize' ); - } ); - - // Adjust when collapsing the menu. - $document.on( 'wp-collapse-menu.editor-expand', function() { - adjust( 'resize' ); - } ) - - // Adjust when changing the columns. - .on( 'postboxes-columnchange.editor-expand', function() { - adjust( 'resize' ); - } ) - - // Adjust when changing the body class. - .on( 'editor-classchange.editor-expand', function() { - adjust( 'resize' ); + initialResize( adjust ); } ); // Adjust the toolbars based on the active editor mode. - function adjust( eventType ) { + function adjust( type ) { // Make sure we're not in fullscreen mode. if ( fullscreen && fullscreen.settings.visible ) { return; @@ -257,22 +230,14 @@ jQuery( document ).ready( function($) { windowHeight = $window.height(), windowWidth = $window.width(), adminBarHeight = windowWidth > 600 ? $adminBar.height() : 0, - $top, $editor, visual, + resize = type !== 'scroll', + visual = ( editorInstance && ! editorInstance.isHidden() ), + $top, $editor, toolsHeight, topPos, topHeight, editorPos, editorHeight, editorWidth, statusBarHeight; - // Visual editor. - if ( editorInstance && ! editorInstance.isHidden() ) { + if ( visual ) { $top = $visualTop; $editor = $visualEditor; - visual = true; - - // Doesn't hide the panel of 'styleselect'. :( - tinymce.each( editorInstance.controlManager.buttons, function( button ) { - if ( button._active && ( button.type === 'colorbutton' || button.type === 'panelbutton' || button.type === 'menubutton' ) ) { - button.hidePanel(); - } - } ); - // Text editor. } else { $top = $textTop; $editor = $textEditor; @@ -287,7 +252,7 @@ jQuery( document ).ready( function($) { statusBarHeight = visual ? $statusBar.outerHeight() : 0; // Maybe pin the top. - if ( ( ! fixedTop || eventType === 'resize' ) && + if ( ( ! fixedTop || resize ) && // Handle scrolling down. ( windowPos >= ( topPos - toolsHeight - adminBarHeight ) && // Handle scrolling up. @@ -307,7 +272,7 @@ jQuery( document ).ready( function($) { width: editorWidth + 2 } ); // Maybe unpin the top. - } else if ( fixedTop || eventType === 'resize' ) { + } else if ( fixedTop || resize ) { // Handle scrolling up. if ( windowPos <= ( topPos - toolsHeight - adminBarHeight ) ) { fixedTop = false; @@ -342,7 +307,7 @@ jQuery( document ).ready( function($) { } // Maybe adjust the bottom bar. - if ( ( ! fixedBottom || eventType === 'resize' ) && + if ( ( ! fixedBottom || resize ) && // + 1 for the border around the .wp-editor-container. ( windowPos + windowHeight ) <= ( editorPos + editorHeight + bottomHeight + statusBarHeight + 1 ) ) { fixedBottom = true; @@ -353,7 +318,7 @@ jQuery( document ).ready( function($) { width: editorWidth + 2, borderTop: '1px solid #dedede' } ); - } else if ( fixedBottom && + } else if ( ( fixedBottom || resize ) && ( windowPos + windowHeight ) > ( editorPos + editorHeight + bottomHeight + statusBarHeight - 1 ) ) { fixedBottom = false; @@ -364,24 +329,50 @@ jQuery( document ).ready( function($) { borderTop: 'none' } ); } + + if ( resize ) { + $contentWrap.css( { + paddingTop: $tools.outerHeight() + } ); + + if ( visual ) { + $visualEditor.css( { + paddingTop: $visualTop.outerHeight() + } ); + } else { + $textEditor.css( { + marginTop: $textTop.outerHeight() + } ); + $textEditorClone.width( $textEditor.width() ); + } + } } - textEditorResize(); + function initialResize( callback ) { + for ( var i = 1; i < 6; i++ ) { + setTimeout( callback, 500 * i ); + } + } - $tools.css( { - position: 'absolute', - top: 0, - width: $contentWrap.width() + // Adjust when the window is scrolled or resized. + $window.on( 'scroll.editor-expand resize.editor-expand', function( event ) { + adjust( event.type ); } ); - $contentWrap.css( { - paddingTop: $tools.outerHeight() + // Adjust when entering/exiting fullscreen mode. + fullscreen && fullscreen.pubsub.subscribe( 'hidden', function() { + textEditorResize(); + adjust(); } ); - // This needs to execute after quicktags is ready or a button is added... - setTimeout( function() { - $textEditor.css( { - paddingTop: $textTop.outerHeight() + parseInt( $textEditor.css( 'padding-top' ), 10 ) + // Adjust when collapsing the menu, changing the columns, changing the body class. + $document.on( 'wp-collapse-menu.editor-expand postboxes-columnchange.editor-expand editor-classchange.editor-expand', adjust ); + + // Ideally we need to resize just after CSS has fully loaded and QuickTags is ready. + if ( $contentWrap.hasClass( 'html-active' ) ) { + initialResize( function() { + adjust(); + textEditorResize(); } ); - }, 500 ); + } }); diff --git a/src/wp-includes/js/tinymce/plugins/wpautoresize/plugin.js b/src/wp-includes/js/tinymce/plugins/wpautoresize/plugin.js index df4bc5b7e7..47eb295c65 100644 --- a/src/wp-includes/js/tinymce/plugins/wpautoresize/plugin.js +++ b/src/wp-includes/js/tinymce/plugins/wpautoresize/plugin.js @@ -42,6 +42,7 @@ tinymce.PluginManager.add( 'wpautoresize', function( editor ) { return; } + e = e || {}; body = doc.body; docElm = doc.documentElement; resizeHeight = settings.autoresize_min_height; @@ -60,6 +61,11 @@ tinymce.PluginManager.add( 'wpautoresize', function( editor ) { marginBottom = editor.dom.getStyle( body, 'margin-bottom', true ); myHeight = body.offsetHeight + parseInt( marginTop, 10 ) + parseInt( marginBottom, 10 ); + // IE < 11, other? + if ( myHeight && myHeight < docElm.offsetHeight ) { + myHeight = docElm.offsetHeight; + } + // Make sure we have a valid height if ( isNaN( myHeight ) || myHeight <= 0 ) { // Get height differently depending on the browser used @@ -93,6 +99,8 @@ tinymce.PluginManager.add( 'wpautoresize', function( editor ) { if ( tinymce.isWebKit && deltaSize < 0 ) { resize( e ); } + + editor.fire( 'wp-autoresize', { height: resizeHeight } ); } } @@ -102,7 +110,7 @@ tinymce.PluginManager.add( 'wpautoresize', function( editor ) { */ function wait( times, interval, callback ) { setTimeout( function() { - resize({}); + resize(); if ( times-- ) { wait( times, interval, callback ); @@ -123,14 +131,20 @@ tinymce.PluginManager.add( 'wpautoresize', function( editor ) { editor.dom.addClass( editor.getBody(), 'wp-autoresize' ); // Add appropriate listeners for resizing the content area editor.on( 'nodechange setcontent keyup FullscreenStateChanged', resize ); + resize(); } } function off() { + var doc; + // Don't turn off if the setting is 'on' if ( ! settings.wp_autoresize_on ) { + doc = editor.getDoc(); editor.dom.removeClass( editor.getBody(), 'wp-autoresize' ); editor.off( 'nodechange setcontent keyup FullscreenStateChanged', resize ); + doc.body.style.overflowY = 'auto'; + doc.documentElement.style.overflowY = 'auto'; // Old IE oldSize = 0; } } @@ -158,6 +172,11 @@ tinymce.PluginManager.add( 'wpautoresize', function( editor ) { } } + // Reset the stored size + editor.on( 'show', function() { + oldSize = 0; + }); + // Register the command editor.addCommand( 'wpAutoResize', resize );