TinyMCE: improve reposition method inline toolbars
* Make sure the toolbar does not overlap the target, unless it is higher than half the visible editor area's height. * Allow the toolbar to have the preference to position itself above or below the target. * Cache DOM lookups. * Simplify the logic and fix various positioning issues. See #32604. git-svn-id: https://develop.svn.wordpress.org/trunk@32816 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
2b857dfdc3
commit
33e63b7bda
@ -447,9 +447,21 @@ tinymce.PluginManager.add( 'wordpress', function( editor ) {
|
|||||||
var Factory = tinymce.ui.Factory,
|
var Factory = tinymce.ui.Factory,
|
||||||
settings = editor.settings,
|
settings = editor.settings,
|
||||||
currentToolbar,
|
currentToolbar,
|
||||||
currentSelection;
|
currentSelection,
|
||||||
|
wpAdminbar = document.getElementById( 'wpadminbar' ),
|
||||||
|
mceIframe, mceToolbar, mceStatusbar, wpStatusbar;
|
||||||
|
|
||||||
function create( buttons ) {
|
editor.on( 'init', function() {
|
||||||
|
mceIframe = document.getElementById( editor.id + '_ifr' );
|
||||||
|
mceToolbar = tinymce.$( '.mce-toolbar-grp', editor.getContainer() )[0];
|
||||||
|
mceStatusbar = tinymce.$( '.mce-statusbar', editor.getContainer() )[0];
|
||||||
|
|
||||||
|
if ( editor.id === 'content' ) {
|
||||||
|
wpStatusbar = document.getElementById( 'post-status-info' );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
function create( buttons, bottom ) {
|
||||||
var toolbar,
|
var toolbar,
|
||||||
toolbarItems = [],
|
toolbarItems = [],
|
||||||
buttonGroup;
|
buttonGroup;
|
||||||
@ -573,107 +585,83 @@ tinymce.PluginManager.add( 'wordpress', function( editor ) {
|
|||||||
} ]
|
} ]
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
toolbar.bottom = bottom;
|
||||||
|
|
||||||
function hide() {
|
function hide() {
|
||||||
toolbar.hide();
|
toolbar.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
function reposition() {
|
function reposition() {
|
||||||
var top, left, minTop, className,
|
var scrollX = window.pageXOffset || document.documentElement.scrollLeft,
|
||||||
windowPos, adminbar, mceToolbar, boundary,
|
scrollY = window.pageYOffset || document.documentElement.scrollTop,
|
||||||
boundaryMiddle, boundaryVerticalMiddle, spaceTop,
|
windowWidth = window.innerWidth,
|
||||||
spaceBottom, windowWidth, toolbarWidth, toolbarHalf,
|
windowHeight = window.innerHeight,
|
||||||
iframe, iframePos, iframeWidth, iframeHeigth,
|
iframeRect = mceIframe.getBoundingClientRect(),
|
||||||
toolbarNodeHeight, verticalSpaceNeeded,
|
toolbar = this.getEl(),
|
||||||
toolbarNode = this.getEl(),
|
toolbarWidth = toolbar.offsetWidth,
|
||||||
|
toolbarHeight = toolbar.offsetHeight,
|
||||||
|
selection = currentSelection.getBoundingClientRect(),
|
||||||
|
selectionMiddle = ( selection.left + selection.right ) / 2,
|
||||||
buffer = 5,
|
buffer = 5,
|
||||||
margin = 8,
|
margin = 8,
|
||||||
adminbarHeight = 0;
|
spaceNeeded = toolbarHeight + margin + buffer,
|
||||||
|
wpAdminbarBottom = wpAdminbar ? wpAdminbar.getBoundingClientRect().bottom : 0,
|
||||||
|
mceToolbarBottom = mceToolbar ? mceToolbar.getBoundingClientRect().bottom : 0,
|
||||||
|
mceStatusbarTop = mceStatusbar ? windowHeight - mceStatusbar.getBoundingClientRect().top : 0,
|
||||||
|
wpStatusbarTop = wpStatusbar ? windowHeight - wpStatusbar.getBoundingClientRect().top : 0,
|
||||||
|
blockedTop = Math.max( 0, wpAdminbarBottom, mceToolbarBottom, iframeRect.top ),
|
||||||
|
blockedBottom = Math.max( 0, mceStatusbarTop, wpStatusbarTop, windowHeight - iframeRect.bottom ),
|
||||||
|
spaceTop = selection.top + iframeRect.top - blockedTop,
|
||||||
|
spaceBottom = windowHeight - iframeRect.top - selection.bottom - blockedBottom,
|
||||||
|
editorHeight = windowHeight - blockedTop - blockedBottom,
|
||||||
|
className = '',
|
||||||
|
top, left;
|
||||||
|
|
||||||
if ( ! currentSelection ) {
|
if ( this.bottom ) {
|
||||||
return;
|
if ( spaceBottom >= spaceNeeded ) {
|
||||||
}
|
|
||||||
|
|
||||||
windowPos = window.pageYOffset || document.documentElement.scrollTop;
|
|
||||||
adminbar = tinymce.$( '#wpadminbar' )[0];
|
|
||||||
mceToolbar = tinymce.$( '.mce-toolbar-grp', editor.getContainer() )[0];
|
|
||||||
boundary = currentSelection.getBoundingClientRect();
|
|
||||||
boundaryMiddle = ( boundary.left + boundary.right ) / 2;
|
|
||||||
boundaryVerticalMiddle = ( boundary.top + boundary.bottom ) / 2;
|
|
||||||
spaceTop = boundary.top;
|
|
||||||
spaceBottom = iframeHeigth - boundary.bottom;
|
|
||||||
windowWidth = window.innerWidth;
|
|
||||||
toolbarWidth = toolbarNode.offsetWidth;
|
|
||||||
toolbarHalf = toolbarWidth / 2;
|
|
||||||
iframe = document.getElementById( editor.id + '_ifr' );
|
|
||||||
iframePos = DOM.getPos( iframe );
|
|
||||||
iframeWidth = iframe.offsetWidth;
|
|
||||||
iframeHeigth = iframe.offsetHeight;
|
|
||||||
toolbarNodeHeight = toolbarNode.offsetHeight;
|
|
||||||
verticalSpaceNeeded = toolbarNodeHeight + margin + buffer;
|
|
||||||
|
|
||||||
if ( spaceTop >= verticalSpaceNeeded ) {
|
|
||||||
className = ' mce-arrow-down';
|
|
||||||
top = boundary.top + iframePos.y - toolbarNodeHeight - margin;
|
|
||||||
} else if ( spaceBottom >= verticalSpaceNeeded ) {
|
|
||||||
className = ' mce-arrow-up';
|
className = ' mce-arrow-up';
|
||||||
top = boundary.bottom + iframePos.y;
|
top = selection.bottom + iframeRect.top + scrollY;
|
||||||
} else {
|
} else if ( spaceTop >= spaceNeeded ) {
|
||||||
top = buffer;
|
|
||||||
|
|
||||||
if ( boundaryVerticalMiddle >= verticalSpaceNeeded ) {
|
|
||||||
className = ' mce-arrow-down';
|
className = ' mce-arrow-down';
|
||||||
|
top = selection.top + iframeRect.top + scrollY - toolbarHeight - margin;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if ( spaceTop >= spaceNeeded ) {
|
||||||
|
className = ' mce-arrow-down';
|
||||||
|
top = selection.top + iframeRect.top + scrollY - toolbarHeight - margin;
|
||||||
|
} else if ( spaceBottom >= spaceNeeded && editorHeight / 2 > selection.bottom + iframeRect.top - blockedTop ) {
|
||||||
className = ' mce-arrow-up';
|
className = ' mce-arrow-up';
|
||||||
|
top = selection.bottom + iframeRect.top + scrollY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the image toolbar is below the main toolbar.
|
if ( typeof top === 'undefined' ) {
|
||||||
if ( mceToolbar ) {
|
top = scrollY + blockedTop + buffer;
|
||||||
minTop = DOM.getPos( mceToolbar ).y + mceToolbar.clientHeight;
|
|
||||||
} else {
|
|
||||||
minTop = iframePos.y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure the image toolbar is below the adminbar (if visible) or below the top of the window.
|
left = selectionMiddle - toolbarWidth / 2 + iframeRect.left + scrollX;
|
||||||
if ( windowPos ) {
|
|
||||||
if ( adminbar && adminbar.getBoundingClientRect().top === 0 ) {
|
|
||||||
adminbarHeight = adminbar.clientHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( windowPos + adminbarHeight > minTop ) {
|
if ( selection.left < 0 || selection.right > iframeRect.width ) {
|
||||||
minTop = windowPos + adminbarHeight;
|
left = iframeRect.left + scrollX + ( iframeRect.width - toolbarWidth ) / 2;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( top && minTop && ( minTop + buffer > top ) ) {
|
|
||||||
top = minTop + buffer;
|
|
||||||
className = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
left = boundaryMiddle - toolbarHalf;
|
|
||||||
left += iframePos.x;
|
|
||||||
|
|
||||||
if ( boundary.left < 0 || boundary.right > iframeWidth ) {
|
|
||||||
left = iframePos.x + ( iframeWidth - toolbarWidth ) / 2;
|
|
||||||
} else if ( toolbarWidth >= windowWidth ) {
|
} else if ( toolbarWidth >= windowWidth ) {
|
||||||
className += ' mce-arrow-full';
|
className += ' mce-arrow-full';
|
||||||
left = 0;
|
left = 0;
|
||||||
} else if ( ( left < 0 && boundary.left + toolbarWidth > windowWidth ) ||
|
} else if ( ( left < 0 && selection.left + toolbarWidth > windowWidth ) || ( left + toolbarWidth > windowWidth && selection.right - toolbarWidth < 0 ) ) {
|
||||||
( left + toolbarWidth > windowWidth && boundary.right - toolbarWidth < 0 ) ) {
|
|
||||||
|
|
||||||
left = ( windowWidth - toolbarWidth ) / 2;
|
left = ( windowWidth - toolbarWidth ) / 2;
|
||||||
} else if ( left < iframePos.x ) {
|
} else if ( left < iframeRect.left + scrollX ) {
|
||||||
className += ' mce-arrow-left';
|
className += ' mce-arrow-left';
|
||||||
left = boundary.left + iframePos.x;
|
left = selection.left + iframeRect.left + scrollX;
|
||||||
} else if ( left + toolbarWidth > iframeWidth + iframePos.x ) {
|
} else if ( left + toolbarWidth > iframeRect.width + iframeRect.left + scrollX ) {
|
||||||
className += ' mce-arrow-right';
|
className += ' mce-arrow-right';
|
||||||
left = boundary.right - toolbarWidth + iframePos.x;
|
left = selection.right - toolbarWidth + iframeRect.left + scrollX;
|
||||||
}
|
}
|
||||||
|
|
||||||
toolbarNode.className = toolbarNode.className.replace( / ?mce-arrow-[\w]+/g, '' );
|
toolbar.className = toolbar.className.replace( / ?mce-arrow-[\w]+/g, '' ) + className;
|
||||||
toolbarNode.className += className;
|
|
||||||
|
|
||||||
DOM.setStyles( toolbarNode, { 'left': left, 'top': top } );
|
DOM.setStyles( toolbar, {
|
||||||
|
'left': left,
|
||||||
|
'top': top
|
||||||
|
} );
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user