WordPress.org

Make WordPress Core

Changeset 32816


Ignore:
Timestamp:
06/17/2015 04:41:59 AM (6 years ago)
Author:
iseulde
Message:

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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/js/tinymce/plugins/wordpress/plugin.js

    r32295 r32816  
    448448            settings = editor.settings,
    449449            currentToolbar,
    450             currentSelection;
    451 
    452         function create( buttons ) {
     450            currentSelection,
     451            wpAdminbar = document.getElementById( 'wpadminbar' ),
     452            mceIframe, mceToolbar, mceStatusbar, wpStatusbar;
     453
     454        editor.on( 'init', function() {
     455            mceIframe = document.getElementById( editor.id + '_ifr' );
     456            mceToolbar = tinymce.$( '.mce-toolbar-grp', editor.getContainer() )[0];
     457            mceStatusbar = tinymce.$( '.mce-statusbar', editor.getContainer() )[0];
     458
     459            if ( editor.id === 'content' ) {
     460                wpStatusbar = document.getElementById( 'post-status-info' );
     461            }
     462        } );
     463
     464        function create( buttons, bottom ) {
    453465            var toolbar,
    454466                toolbarItems = [],
     
    574586            } );
    575587
     588            toolbar.bottom = bottom;
     589
    576590            function hide() {
    577591                toolbar.hide();
     
    579593
    580594            function reposition() {
    581                 var top, left, minTop, className,
    582                     windowPos, adminbar, mceToolbar, boundary,
    583                     boundaryMiddle, boundaryVerticalMiddle, spaceTop,
    584                     spaceBottom, windowWidth, toolbarWidth, toolbarHalf,
    585                     iframe, iframePos, iframeWidth, iframeHeigth,
    586                     toolbarNodeHeight, verticalSpaceNeeded,
    587                     toolbarNode = this.getEl(),
     595                var scrollX = window.pageXOffset || document.documentElement.scrollLeft,
     596                    scrollY = window.pageYOffset || document.documentElement.scrollTop,
     597                    windowWidth = window.innerWidth,
     598                    windowHeight = window.innerHeight,
     599                    iframeRect = mceIframe.getBoundingClientRect(),
     600                    toolbar = this.getEl(),
     601                    toolbarWidth = toolbar.offsetWidth,
     602                    toolbarHeight = toolbar.offsetHeight,
     603                    selection = currentSelection.getBoundingClientRect(),
     604                    selectionMiddle = ( selection.left + selection.right ) / 2,
    588605                    buffer = 5,
    589606                    margin = 8,
    590                     adminbarHeight = 0;
    591 
    592                 if ( ! currentSelection ) {
    593                     return;
    594                 }
    595 
    596                 windowPos = window.pageYOffset || document.documentElement.scrollTop;
    597                 adminbar = tinymce.$( '#wpadminbar' )[0];
    598                 mceToolbar = tinymce.$( '.mce-toolbar-grp', editor.getContainer() )[0];
    599                 boundary = currentSelection.getBoundingClientRect();
    600                 boundaryMiddle = ( boundary.left + boundary.right ) / 2;
    601                 boundaryVerticalMiddle = ( boundary.top + boundary.bottom ) / 2;
    602                 spaceTop = boundary.top;
    603                 spaceBottom = iframeHeigth - boundary.bottom;
    604                 windowWidth = window.innerWidth;
    605                 toolbarWidth = toolbarNode.offsetWidth;
    606                 toolbarHalf = toolbarWidth / 2;
    607                 iframe = document.getElementById( editor.id + '_ifr' );
    608                 iframePos = DOM.getPos( iframe );
    609                 iframeWidth = iframe.offsetWidth;
    610                 iframeHeigth = iframe.offsetHeight;
    611                 toolbarNodeHeight = toolbarNode.offsetHeight;
    612                 verticalSpaceNeeded = toolbarNodeHeight + margin + buffer;
    613 
    614                 if ( spaceTop >= verticalSpaceNeeded ) {
    615                     className = ' mce-arrow-down';
    616                     top = boundary.top + iframePos.y - toolbarNodeHeight - margin;
    617                 } else if ( spaceBottom >= verticalSpaceNeeded ) {
    618                     className = ' mce-arrow-up';
    619                     top = boundary.bottom + iframePos.y;
     607                    spaceNeeded = toolbarHeight + margin + buffer,
     608                    wpAdminbarBottom = wpAdminbar ? wpAdminbar.getBoundingClientRect().bottom : 0,
     609                    mceToolbarBottom = mceToolbar ? mceToolbar.getBoundingClientRect().bottom : 0,
     610                    mceStatusbarTop = mceStatusbar ? windowHeight - mceStatusbar.getBoundingClientRect().top : 0,
     611                    wpStatusbarTop = wpStatusbar ? windowHeight - wpStatusbar.getBoundingClientRect().top : 0,
     612                    blockedTop = Math.max( 0, wpAdminbarBottom, mceToolbarBottom, iframeRect.top ),
     613                    blockedBottom = Math.max( 0, mceStatusbarTop, wpStatusbarTop, windowHeight - iframeRect.bottom ),
     614                    spaceTop = selection.top + iframeRect.top - blockedTop,
     615                    spaceBottom = windowHeight - iframeRect.top - selection.bottom - blockedBottom,
     616                    editorHeight = windowHeight - blockedTop - blockedBottom,
     617                    className = '',
     618                    top, left;
     619
     620                if ( this.bottom ) {
     621                    if ( spaceBottom >= spaceNeeded ) {
     622                        className = ' mce-arrow-up';
     623                        top = selection.bottom + iframeRect.top + scrollY;
     624                    } else if ( spaceTop >= spaceNeeded ) {
     625                        className = ' mce-arrow-down';
     626                        top = selection.top + iframeRect.top + scrollY - toolbarHeight - margin;
     627                    }
    620628                } else {
    621                     top = buffer;
    622 
    623                     if ( boundaryVerticalMiddle >= verticalSpaceNeeded ) {
     629                    if ( spaceTop >= spaceNeeded ) {
    624630                        className = ' mce-arrow-down';
    625                     } else {
     631                        top = selection.top + iframeRect.top + scrollY - toolbarHeight - margin;
     632                    } else if ( spaceBottom >= spaceNeeded && editorHeight / 2 > selection.bottom + iframeRect.top - blockedTop ) {
    626633                        className = ' mce-arrow-up';
    627                     }
    628                 }
    629 
    630                 // Make sure the image toolbar is below the main toolbar.
    631                 if ( mceToolbar ) {
    632                     minTop = DOM.getPos( mceToolbar ).y + mceToolbar.clientHeight;
    633                 } else {
    634                     minTop = iframePos.y;
    635                 }
    636 
    637                 // Make sure the image toolbar is below the adminbar (if visible) or below the top of the window.
    638                 if ( windowPos ) {
    639                     if ( adminbar && adminbar.getBoundingClientRect().top === 0 ) {
    640                         adminbarHeight = adminbar.clientHeight;
    641                     }
    642 
    643                     if ( windowPos + adminbarHeight > minTop ) {
    644                         minTop = windowPos + adminbarHeight;
    645                     }
    646                 }
    647 
    648                 if ( top && minTop && ( minTop + buffer > top ) ) {
    649                     top = minTop + buffer;
    650                     className = '';
    651                 }
    652 
    653                 left = boundaryMiddle - toolbarHalf;
    654                 left += iframePos.x;
    655 
    656                 if ( boundary.left < 0 || boundary.right > iframeWidth ) {
    657                     left = iframePos.x + ( iframeWidth - toolbarWidth ) / 2;
     634                        top = selection.bottom + iframeRect.top + scrollY;
     635                    }
     636                }
     637
     638                if ( typeof top === 'undefined' ) {
     639                    top = scrollY + blockedTop + buffer;
     640                }
     641
     642                left = selectionMiddle - toolbarWidth / 2 + iframeRect.left + scrollX;
     643
     644                if ( selection.left < 0 || selection.right > iframeRect.width ) {
     645                    left = iframeRect.left + scrollX + ( iframeRect.width - toolbarWidth ) / 2;
    658646                } else if ( toolbarWidth >= windowWidth ) {
    659647                    className += ' mce-arrow-full';
    660648                    left = 0;
    661                 } else if ( ( left < 0 && boundary.left + toolbarWidth > windowWidth ) ||
    662                     ( left + toolbarWidth > windowWidth && boundary.right - toolbarWidth < 0 ) ) {
    663 
     649                } else if ( ( left < 0 && selection.left + toolbarWidth > windowWidth ) || ( left + toolbarWidth > windowWidth && selection.right - toolbarWidth < 0 ) ) {
    664650                    left = ( windowWidth - toolbarWidth ) / 2;
    665                 } else if ( left < iframePos.x ) {
     651                } else if ( left < iframeRect.left + scrollX ) {
    666652                    className += ' mce-arrow-left';
    667                     left = boundary.left + iframePos.x;
    668                 } else if ( left + toolbarWidth > iframeWidth + iframePos.x ) {
     653                    left = selection.left + iframeRect.left + scrollX;
     654                } else if ( left + toolbarWidth > iframeRect.width + iframeRect.left + scrollX ) {
    669655                    className += ' mce-arrow-right';
    670                     left = boundary.right - toolbarWidth + iframePos.x;
    671                 }
    672 
    673                 toolbarNode.className = toolbarNode.className.replace( / ?mce-arrow-[\w]+/g, '' );
    674                 toolbarNode.className += className;
    675 
    676                 DOM.setStyles( toolbarNode, { 'left': left, 'top': top } );
     656                    left = selection.right - toolbarWidth + iframeRect.left + scrollX;
     657                }
     658
     659                toolbar.className = toolbar.className.replace( / ?mce-arrow-[\w]+/g, '' ) + className;
     660
     661                DOM.setStyles( toolbar, {
     662                    'left': left,
     663                    'top': top
     664                } );
    677665
    678666                return this;
Note: See TracChangeset for help on using the changeset viewer.