WordPress.org

Make WordPress Core

Changeset 31725


Ignore:
Timestamp:
03/11/2015 07:11:02 PM (5 years ago)
Author:
azaozz
Message:

TinyMCE:

  • Abstract the code for creating floating toolbars.
  • Introduce editor.wp namespace to hold exported methods from our plugins.
  • Create the wpView toolbar(s) with the new method. This makes them work the same as the image toolbar: shortcuts, esc key, etc.

Props iseulde. See #30619.

Location:
trunk/src
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/js/editor-expand.js

    r31361 r31725  
    178178                    range, view, offset;
    179179
    180                 if ( editor.plugins.wpview && ( view = editor.plugins.wpview.getView( node ) ) ) {
     180                if ( editor.wp && editor.wp.getView && ( view = editor.wp.getView( node ) ) ) {
    181181                    offset = view.getBoundingClientRect();
    182182                } else {
  • trunk/src/wp-includes/css/editor.css

    r31713 r31725  
    171171    margin-bottom: 8px;
    172172    position: absolute;
    173     visibility: hidden;
    174173    -moz-user-select: none;
    175174    -webkit-user-select: none;
     
    179178}
    180179
    181 div.mce-wp-image-toolbar > div.mce-stack-layout {
     180div.mce-inline-toolbar-grp > div.mce-stack-layout {
    182181    padding: 1px;
    183182}
     
    261260    width: 100%;
    262261    overflow-x: auto;
    263 }
    264 
    265 div.mce-inline-toolbar-grp-active {
    266     visibility: visible;
    267262}
    268263
  • trunk/src/wp-includes/js/mce-view.js

    r31689 r31725  
    406406                            '<p class="wpview-selection-before">\u00a0</p>' +
    407407                            '<div class="wpview-body" contenteditable="false">' +
    408                                 '<div class="toolbar mce-arrow-down">' +
    409                                     ( this.edit ? '<div class="dashicons dashicons-edit edit"></div>' : '' ) +
    410                                     '<div class="dashicons dashicons-no remove"></div>' +
    411                                 '</div>' +
    412408                                '<div class="wpview-content wpview-type-' + this.type + '"></div>' +
    413409                            '</div>' +
  • trunk/src/wp-includes/js/tinymce/plugins/wordpress/plugin.js

    r31703 r31725  
    433433        }
    434434    });
     435   
     436    /**
     437     * Experimental: create a floating toolbar.
     438     * This functionality will change in the next releases. Not recommennded for use by plugins.
     439     */     
     440    ( function() {
     441        var DOM = tinymce.DOM,
     442            each = tinymce.each,
     443            Factory = tinymce.ui.Factory,
     444            settings = editor.settings,
     445            currentToolbar,
     446            currentSelection;
     447
     448        function create( buttons ) {
     449            var toolbar,
     450                toolbarItems = [],
     451                buttonGroup;
     452
     453            each( buttons, function( item ) {
     454                var itemName;
     455
     456                function bindSelectorChanged() {
     457                    var selection = editor.selection;
     458
     459                    if ( itemName === 'bullist' ) {
     460                        selection.selectorChanged( 'ul > li', function( state, args ) {
     461                            var i = args.parents.length,
     462                                nodeName;
     463
     464                            while ( i-- ) {
     465                                nodeName = args.parents[ i ].nodeName;
     466
     467                                if ( nodeName === 'OL' || nodeName == 'UL' ) {
     468                                    break;
     469                                }
     470                            }
     471
     472                            item.active( state && nodeName === 'UL' );
     473                        } );
     474                    }
     475
     476                    if ( itemName === 'numlist' ) {
     477                        selection.selectorChanged( 'ol > li', function( state, args ) {
     478                            var i = args.parents.length,
     479                                nodeName;
     480
     481                            while ( i-- ) {
     482                                nodeName = args.parents[ i ].nodeName;
     483
     484                                if ( nodeName === 'OL' || nodeName === 'UL' ) {
     485                                    break;
     486                                }
     487                            }
     488
     489                            item.active( state && nodeName === 'OL' );
     490                        } );
     491                    }
     492
     493                    if ( item.settings.stateSelector ) {
     494                        selection.selectorChanged( item.settings.stateSelector, function( state ) {
     495                            item.active( state );
     496                        }, true );
     497                    }
     498
     499                    if ( item.settings.disabledStateSelector ) {
     500                        selection.selectorChanged( item.settings.disabledStateSelector, function( state ) {
     501                            item.disabled( state );
     502                        } );
     503                    }
     504                }
     505
     506                if ( item === '|' ) {
     507                    buttonGroup = null;
     508                } else {
     509                    if ( Factory.has( item ) ) {
     510                        item = {
     511                            type: item
     512                        };
     513
     514                        if ( settings.toolbar_items_size ) {
     515                            item.size = settings.toolbar_items_size;
     516                        }
     517
     518                        toolbarItems.push( item );
     519
     520                        buttonGroup = null;
     521                    } else {
     522                        if ( ! buttonGroup ) {
     523                            buttonGroup = {
     524                                type: 'buttongroup',
     525                                items: []
     526                            };
     527
     528                            toolbarItems.push( buttonGroup );
     529                        }
     530
     531                        if ( editor.buttons[ item ] ) {
     532                            itemName = item;
     533                            item = editor.buttons[ itemName ];
     534
     535                            if ( typeof item === 'function' ) {
     536                                item = item();
     537                            }
     538
     539                            item.type = item.type || 'button';
     540
     541                            if ( settings.toolbar_items_size ) {
     542                                item.size = settings.toolbar_items_size;
     543                            }
     544
     545                            item = Factory.create( item );
     546
     547                            buttonGroup.items.push( item );
     548
     549                            if ( editor.initialized ) {
     550                                bindSelectorChanged();
     551                            } else {
     552                                editor.on( 'init', bindSelectorChanged );
     553                            }
     554                        }
     555                    }
     556                }
     557            } );
     558
     559            toolbar = Factory.create( {
     560                type: 'panel',
     561                layout: 'stack',
     562                classes: 'toolbar-grp inline-toolbar-grp',
     563                ariaRoot: true,
     564                ariaRemember: true,
     565                items: [ {
     566                    type: 'toolbar',
     567                    layout: 'flow',
     568                    items: toolbarItems
     569                } ]
     570            } );
     571
     572            function hide() {
     573                toolbar.hide();
     574            }
     575
     576            function reposition() {
     577                var top, left, minTop, className,
     578                    windowPos, adminbar, mceToolbar, boundary,
     579                    boundaryMiddle, boundaryVerticalMiddle, spaceTop,
     580                    spaceBottom, windowWidth, toolbarWidth, toolbarHalf,
     581                    iframe, iframePos, iframeWidth, iframeHeigth,
     582                    toolbarNodeHeight, verticalSpaceNeeded,
     583                    toolbarNode = this.getEl(),
     584                    buffer = 5,
     585                    margin = 8,
     586                    adminbarHeight = 0;
     587
     588                windowPos = window.pageYOffset || document.documentElement.scrollTop;
     589                adminbar = tinymce.$( '#wpadminbar' )[0];
     590                mceToolbar = tinymce.$( '.mce-toolbar-grp', editor.getContainer() )[0];
     591                boundary = currentSelection.getBoundingClientRect();
     592                boundaryMiddle = ( boundary.left + boundary.right ) / 2;
     593                boundaryVerticalMiddle = ( boundary.top + boundary.bottom ) / 2;
     594                spaceTop = boundary.top;
     595                spaceBottom = iframeHeigth - boundary.bottom;
     596                windowWidth = window.innerWidth;
     597                toolbarWidth = toolbarNode.offsetWidth;
     598                toolbarHalf = toolbarWidth / 2;
     599                iframe = document.getElementById( editor.id + '_ifr' );
     600                iframePos = DOM.getPos( iframe );
     601                iframeWidth = iframe.offsetWidth;
     602                iframeHeigth = iframe.offsetHeight;
     603                toolbarNodeHeight = toolbarNode.offsetHeight;
     604                verticalSpaceNeeded = toolbarNodeHeight + margin + buffer;
     605
     606                if ( spaceTop >= verticalSpaceNeeded ) {
     607                    className = ' mce-arrow-down';
     608                    top = boundary.top + iframePos.y - toolbarNodeHeight - margin;
     609                } else if ( spaceBottom >= verticalSpaceNeeded ) {
     610                    className = ' mce-arrow-up';
     611                    top = boundary.bottom + iframePos.y;
     612                } else {
     613                    top = buffer;
     614
     615                    if ( boundaryVerticalMiddle >= verticalSpaceNeeded ) {
     616                        className = ' mce-arrow-down';
     617                    } else {
     618                        className = ' mce-arrow-up';
     619                    }
     620                }
     621
     622                // Make sure the image toolbar is below the main toolbar.
     623                if ( mceToolbar ) {
     624                    minTop = DOM.getPos( mceToolbar ).y + mceToolbar.clientHeight;
     625                } else {
     626                    minTop = iframePos.y;
     627                }
     628
     629                // Make sure the image toolbar is below the adminbar (if visible) or below the top of the window.
     630                if ( windowPos ) {
     631                    if ( adminbar && adminbar.getBoundingClientRect().top === 0 ) {
     632                        adminbarHeight = adminbar.clientHeight;
     633                    }
     634
     635                    if ( windowPos + adminbarHeight > minTop ) {
     636                        minTop = windowPos + adminbarHeight;
     637                    }
     638                }
     639
     640                if ( top && minTop && ( minTop + buffer > top ) ) {
     641                    top = minTop + buffer;
     642                    className = '';
     643                }
     644
     645                left = boundaryMiddle - toolbarHalf;
     646                left += iframePos.x;
     647
     648                if ( boundary.left < 0 || boundary.right > iframeWidth ) {
     649                    left = iframePos.x + ( iframeWidth - toolbarWidth ) / 2;
     650                } else if ( toolbarWidth >= windowWidth ) {
     651                    className += ' mce-arrow-full';
     652                    left = 0;
     653                } else if ( ( left < 0 && boundary.left + toolbarWidth > windowWidth ) ||
     654                    ( left + toolbarWidth > windowWidth && boundary.right - toolbarWidth < 0 ) ) {
     655
     656                    left = ( windowWidth - toolbarWidth ) / 2;
     657                } else if ( left < iframePos.x ) {
     658                    className += ' mce-arrow-left';
     659                    left = boundary.left + iframePos.x;
     660                } else if ( left + toolbarWidth > iframeWidth + iframePos.x ) {
     661                    className += ' mce-arrow-right';
     662                    left = boundary.right - toolbarWidth + iframePos.x;
     663                }
     664
     665                toolbarNode.className = toolbarNode.className.replace( / ?mce-arrow-[\w]+/g, '' );
     666                toolbarNode.className += className;
     667
     668                DOM.setStyles( toolbarNode, { 'left': left, 'top': top } );
     669
     670                return this;
     671            }
     672
     673            toolbar.on( 'show', function() {
     674                currentToolbar = this;
     675                this.reposition();
     676            } );
     677
     678            toolbar.on( 'hide', function() {
     679                currentToolbar = false;
     680            } );
     681
     682            toolbar.on( 'keydown', function( event ) {
     683                if ( event.keyCode === 27 ) {
     684                    this.hide();
     685                    editor.focus();
     686                }
     687            } );
     688
     689            toolbar.on( 'remove', function() {
     690                DOM.unbind( window, 'resize scroll', hide );
     691                editor.dom.unbind( editor.getWin(), 'resize scroll', hide );
     692                editor.off( 'blur hide', hide );
     693            } );
     694
     695            editor.once( 'init', function() {
     696                DOM.bind( window, 'resize scroll', hide );
     697                editor.dom.bind( editor.getWin(), 'resize scroll', hide );
     698                editor.on( 'blur hide', hide );
     699            } );
     700
     701            toolbar.reposition = reposition;
     702            toolbar.hide().renderTo( document.body );
     703
     704            return toolbar;
     705        }
     706
     707        editor.shortcuts.add( 'alt+119', '', function() {
     708            var node;
     709
     710            if ( currentToolbar ) {
     711                node = currentToolbar.find( 'toolbar' )[0];
     712                node && node.focus( true );
     713            }
     714        } );
     715
     716        editor.on( 'nodechange', function( event ) {
     717            var collapsed = editor.selection.isCollapsed();
     718
     719            var args = {
     720                element: event.element,
     721                parents: event.parents,
     722                collapsed: collapsed
     723            };
     724
     725            editor.fire( 'wptoolbar', args );
     726
     727            currentSelection = args.selection || args.element;
     728
     729            currentToolbar && currentToolbar.hide();
     730            args.toolbar && args.toolbar.show();
     731        } );
     732
     733        editor.wp = editor.wp || {};
     734        editor.wp._createToolbar = create;
     735    }());
    435736
    436737    function noop() {}
  • trunk/src/wp-includes/js/tinymce/plugins/wpeditimage/plugin.js

    r31691 r31725  
    22tinymce.PluginManager.add( 'wpeditimage', function( editor ) {
    33    var floatingToolbar, serializer,
    4         DOM = tinymce.DOM,
    5         settings = editor.settings,
    6         Factory = tinymce.ui.Factory,
    74        each = tinymce.each,
    8         iOS = tinymce.Env.iOS,
    9         toolbarIsHidden = true,
    10         editorWrapParent = tinymce.$( '#postdivrich' );
     5        iOS = tinymce.Env.iOS;
    116
    127    function isPlaceholder( node ) {
     
    6560    } );
    6661
    67     function toolbarConfig() {
    68         var toolbarItems = [],
    69             buttonGroup;
    70 
    71         each( [ 'wp_img_alignleft', 'wp_img_aligncenter', 'wp_img_alignright', 'wp_img_alignnone', 'wp_img_edit', 'wp_img_remove' ], function( item ) {
    72             var itemName;
    73 
    74             function bindSelectorChanged() {
    75                 var selection = editor.selection;
    76 
    77                 if ( item.settings.stateSelector ) {
    78                     selection.selectorChanged( item.settings.stateSelector, function( state ) {
    79                         item.active( state );
    80                     }, true );
    81                 }
    82 
    83                 if ( item.settings.disabledStateSelector ) {
    84                     selection.selectorChanged( item.settings.disabledStateSelector, function( state ) {
    85                         item.disabled( state );
    86                     } );
    87                 }
    88             }
    89 
    90             if ( item === '|' ) {
    91                 buttonGroup = null;
    92             } else {
    93                 if ( Factory.has( item ) ) {
    94                     item = {
    95                         type: item
    96                     };
    97 
    98                     if ( settings.toolbar_items_size ) {
    99                         item.size = settings.toolbar_items_size;
    100                     }
    101 
    102                     toolbarItems.push( item );
    103 
    104                     buttonGroup = null;
    105                 } else {
    106                     if ( ! buttonGroup ) {
    107                         buttonGroup = {
    108                             type: 'buttongroup',
    109                             items: []
    110                         };
    111 
    112                         toolbarItems.push( buttonGroup );
    113                     }
    114 
    115                     if ( editor.buttons[ item ] ) {
    116                         itemName = item;
    117                         item = editor.buttons[ itemName ];
    118 
    119                         if ( typeof item === 'function' ) {
    120                             item = item();
    121                         }
    122 
    123                         item.type = item.type || 'button';
    124 
    125                         if ( settings.toolbar_items_size ) {
    126                             item.size = settings.toolbar_items_size;
    127                         }
    128 
    129                         item = Factory.create( item );
    130                         buttonGroup.items.push( item );
    131 
    132                         if ( editor.initialized ) {
    133                             bindSelectorChanged();
    134                         } else {
    135                             editor.on( 'init', bindSelectorChanged );
    136                         }
    137                     }
    138                 }
    139             }
    140         } );
    141 
    142         return {
    143             type: 'panel',
    144             layout: 'stack',
    145             classes: 'toolbar-grp inline-toolbar-grp wp-image-toolbar',
    146             ariaRoot: true,
    147             ariaRemember: true,
    148             items: [
    149                 {
    150                     type: 'toolbar',
    151                     layout: 'flow',
    152                     items: toolbarItems
    153                 }
    154             ]
    155         };
    156     }
    157 
    158     floatingToolbar = Factory.create( toolbarConfig() ).renderTo( document.body ).hide();
    159 
    160     floatingToolbar.reposition = function() {
    161         var top, left, minTop, className,
    162             windowPos, adminbar, mceToolbar, boundary,
    163             boundaryMiddle, boundaryVerticalMiddle, spaceTop,
    164             spaceBottom, windowWidth, toolbarWidth, toolbarHalf,
    165             iframe, iframePos, iframeWidth, iframeHeigth,
    166             toolbarNodeHeight, verticalSpaceNeeded,
    167             toolbarNode = this.getEl(),
    168             buffer = 5,
    169             margin = 8,
    170             adminbarHeight = 0,
    171             imageNode = editor.selection.getNode();
    172 
    173         if ( ! imageNode || imageNode.nodeName !== 'IMG' ) {
    174             return this;
    175         }
    176 
    177         windowPos = window.pageYOffset || document.documentElement.scrollTop;
    178         adminbar = tinymce.$( '#wpadminbar' )[0];
    179         mceToolbar = tinymce.$( '.mce-toolbar-grp', editor.getContainer() )[0];
    180         boundary = imageNode.getBoundingClientRect();
    181         boundaryMiddle = ( boundary.left + boundary.right ) / 2;
    182         boundaryVerticalMiddle = ( boundary.top + boundary.bottom ) / 2;
    183         spaceTop = boundary.top;
    184         spaceBottom = iframeHeigth - boundary.bottom;
    185         windowWidth = window.innerWidth;
    186         toolbarWidth = toolbarNode.offsetWidth;
    187         toolbarHalf = toolbarWidth / 2;
    188         iframe = document.getElementById( editor.id + '_ifr' );
    189         iframePos = DOM.getPos( iframe );
    190         iframeWidth = iframe.offsetWidth;
    191         iframeHeigth = iframe.offsetHeight;
    192         toolbarNodeHeight = toolbarNode.offsetHeight;
    193         verticalSpaceNeeded = toolbarNodeHeight + margin + buffer;
    194 
    195         if ( iOS ) {
    196             top = boundary.top + iframePos.y + margin;
    197         } else {
    198             if ( spaceTop >= verticalSpaceNeeded ) {
    199                 className = ' mce-arrow-down';
    200                 top = boundary.top + iframePos.y - toolbarNodeHeight - margin;
    201             } else if ( spaceBottom >= verticalSpaceNeeded ) {
    202                 className = ' mce-arrow-up';
    203                 top = boundary.bottom + iframePos.y;
    204             } else {
    205                 top = buffer;
    206 
    207                 if ( boundaryVerticalMiddle >= verticalSpaceNeeded ) {
    208                     className = ' mce-arrow-down';
    209                 } else {
    210                     className = ' mce-arrow-up';
    211                 }
    212             }
    213         }
    214 
    215         // Make sure the image toolbar is below the main toolbar.
    216         if ( mceToolbar ) {
    217             minTop = DOM.getPos( mceToolbar ).y + mceToolbar.clientHeight;
    218         } else {
    219             minTop = iframePos.y;
    220         }
    221 
    222         // Make sure the image toolbar is below the adminbar (if visible) or below the top of the window.
    223         if ( windowPos ) {
    224             if ( adminbar && adminbar.getBoundingClientRect().top === 0 ) {
    225                 adminbarHeight = adminbar.clientHeight;
    226             }
    227 
    228             if ( windowPos + adminbarHeight > minTop ) {
    229                 minTop = windowPos + adminbarHeight;
    230             }
    231         }
    232 
    233         if ( top && minTop && ( minTop + buffer > top ) ) {
    234             top = minTop + buffer;
    235             className = '';
    236         }
    237 
    238         left = boundaryMiddle - toolbarHalf;
    239         left += iframePos.x;
    240 
    241         if ( boundary.left < 0 || boundary.right > iframeWidth ) {
    242             left = iframePos.x + ( iframeWidth - toolbarWidth ) / 2;
    243         } else if ( toolbarWidth >= windowWidth ) {
    244             className += ' mce-arrow-full';
    245             left = 0;
    246         } else if ( ( left < 0 && boundary.left + toolbarWidth > windowWidth ) ||
    247             ( left + toolbarWidth > windowWidth && boundary.right - toolbarWidth < 0 ) ) {
    248 
    249             left = ( windowWidth - toolbarWidth ) / 2;
    250         } else if ( left < iframePos.x ) {
    251             className += ' mce-arrow-left';
    252             left = boundary.left + iframePos.x;
    253         } else if ( left + toolbarWidth > iframeWidth + iframePos.x ) {
    254             className += ' mce-arrow-right';
    255             left = boundary.right - toolbarWidth + iframePos.x;
    256         }
    257 
    258         if ( ! iOS ) {
    259             toolbarNode.className = toolbarNode.className.replace( / ?mce-arrow-[\w]+/g, '' );
    260             toolbarNode.className += className;
    261         }
    262 
    263         DOM.setStyles( toolbarNode, { 'left': left, 'top': top } );
    264 
    265         return this;
    266     };
    267 
     62    editor.on( 'wptoolbar', function( event ) {
     63        if ( event.element.nodeName === 'IMG' && ! isPlaceholder( event.element ) ) {
     64            event.toolbar = floatingToolbar;
     65        }
     66    } );
     67
     68    // Safari on iOS fails to select image nodes in contentEditoble mode on touch/click.
     69    // Select them again.
    26870    if ( iOS ) {
    269         // Safari on iOS fails to select image nodes in contentEditoble mode on touch/click.
    270         // Select them again.
    27171        editor.on( 'click', function( event ) {
    27272            if ( event.target.nodeName === 'IMG' ) {
     
    27575                window.setTimeout( function() {
    27676                    editor.selection.select( node );
     77                    editor.nodeChanged();
    27778                }, 200 );
    27879            } else {
    27980                floatingToolbar.hide();
    28081            }
    281         });
    282     }
    283 
    284     editor.on( 'nodechange', function( event ) {
    285         var delay = iOS ? 350 : 100;
    286 
    287         if ( event.element.nodeName !== 'IMG' || isPlaceholder( event.element ) ) {
    288             floatingToolbar.hide();
    289             return;
    290         }
    291 
    292         setTimeout( function() {
    293             var element = editor.selection.getNode();
    294 
    295             if ( element.nodeName === 'IMG' && ! isPlaceholder( element ) ) {
    296                 if ( floatingToolbar._visible ) {
    297                     floatingToolbar.reposition();
    298                 } else {
    299                     floatingToolbar.show();
    300                 }
    301             } else {
    302                 floatingToolbar.hide();
    303             }
    304         }, delay );
    305     } );
    306 
    307     function hide() {
    308         if ( ! toolbarIsHidden ) {
    309             floatingToolbar.hide();
    310         }
    311     }
    312 
    313     floatingToolbar.on( 'show', function() {
    314         toolbarIsHidden = false;
    315 
    316         if ( this._visible ) {
    317             this.reposition();
    318             DOM.addClass( this.getEl(), 'mce-inline-toolbar-grp-active' );
    319         }
    320     } );
    321 
    322     floatingToolbar.on( 'hide', function() {
    323         toolbarIsHidden = true;
    324         DOM.removeClass( this.getEl(), 'mce-inline-toolbar-grp-active' );
    325     } );
    326 
    327     floatingToolbar.on( 'keydown', function( event ) {
    328         if ( event.keyCode === 27 ) {
    329             hide();
    330             editor.focus();
    331         }
    332     } );
    333 
    334     DOM.bind( window, 'resize scroll', function() {
    335         if ( ! toolbarIsHidden && editorWrapParent.hasClass( 'wp-editor-expand' ) ) {
    336             hide();
    337         }
    338     });
    339 
    340     editor.on( 'init', function() {
    341         editor.dom.bind( editor.getWin(), 'scroll', hide );
    342     });
    343 
    344     editor.on( 'blur hide', hide );
    345 
    346     // 119 = F8
    347     editor.shortcuts.add( 'Alt+119', '', function() {
    348         var node = floatingToolbar.find( 'toolbar' )[0];
    349 
    350         if ( node ) {
    351             node.focus( true );
    352         }
    353     });
     82        } );
     83    }
    35484
    35585    function parseShortcode( content ) {
     
    815545        dom.addClass( editor.getBody(), captionClass );
    816546
     547        if ( editor.wp._createToolbar ) {
     548            floatingToolbar = editor.wp._createToolbar( [
     549                'wp_img_alignleft',
     550                'wp_img_aligncenter',
     551                'wp_img_alignright',
     552                'wp_img_alignnone',
     553                'wp_img_edit',
     554                'wp_img_remove'
     555            ] );
     556        }
     557
    817558        // Add caption field to the default image dialog
    818559        editor.on( 'wpLoadImageForm', function( event ) {
     
    1227968    } );
    1228969
     970    // Add to editor.wp
     971    editor.wp = editor.wp || {};
     972    editor.wp.isPlaceholder = isPlaceholder;
     973
     974    // Back-compat.
    1229975    return {
    1230976        _do_shcode: parseShortcode,
  • trunk/src/wp-includes/js/tinymce/plugins/wpview/plugin.js

    r31559 r31725  
    1313        _noop = function() { return false; },
    1414        isios = /iPad|iPod|iPhone/.test( navigator.userAgent ),
    15         cursorInterval, lastKeyDownNode, setViewCursorTries, focus, execCommandView, execCommandBefore;
     15        cursorInterval,
     16        lastKeyDownNode,
     17        setViewCursorTries,
     18        focus,
     19        execCommandView,
     20        execCommandBefore,
     21        toolbar;
    1622
    1723    function getView( node ) {
     
    8793        }
    8894
    89         // Adjust the toolbar position and bail if node is already selected.
    90         if ( viewNode === selected ) {
    91             adjustToolbarPosition( viewNode );
    92             return;
    93         }
    94 
    95         // Make sure that the editor is focused.
    96         // It is possible that the editor is not focused when the mouse event fires
    97         // without focus, the selection will not work properly.
    98         editor.getBody().focus();
    99 
    100         deselect();
    101         selected = viewNode;
    102         dom.setAttrib( viewNode, 'data-mce-selected', 1 );
    103         adjustToolbarPosition( viewNode );
    104 
    105         clipboard = dom.create( 'div', {
    106             'class': 'wpview-clipboard',
    107             'contenteditable': 'true'
    108         }, wp.mce.views.getText( viewNode ) );
    109 
    110         editor.dom.select( '.wpview-body', viewNode )[0].appendChild( clipboard );
    111 
    112         // Both of the following are necessary to prevent manipulating the selection/focus
    113         dom.bind( clipboard, 'beforedeactivate focusin focusout', _stop );
    114         dom.bind( selected, 'beforedeactivate focusin focusout', _stop );
    115 
    116         // select the hidden div
    117         if ( isios ) {
    118             editor.selection.select( clipboard );
    119         } else {
    120             editor.selection.select( clipboard, true );
     95        if ( viewNode !== selected ) {
     96            // Make sure that the editor is focused.
     97            // It is possible that the editor is not focused when the mouse event fires
     98            // without focus, the selection will not work properly.
     99            editor.getBody().focus();
     100
     101            deselect();
     102            selected = viewNode;
     103            dom.setAttrib( viewNode, 'data-mce-selected', 1 );
     104
     105            clipboard = dom.create( 'div', {
     106                'class': 'wpview-clipboard',
     107                'contenteditable': 'true'
     108            }, wp.mce.views.getText( viewNode ) );
     109
     110            editor.dom.select( '.wpview-body', viewNode )[0].appendChild( clipboard );
     111
     112            // Both of the following are necessary to prevent manipulating the selection/focus
     113            dom.bind( clipboard, 'beforedeactivate focusin focusout', _stop );
     114            dom.bind( selected, 'beforedeactivate focusin focusout', _stop );
     115
     116            // select the hidden div
     117            if ( isios ) {
     118                editor.selection.select( clipboard );
     119            } else {
     120                editor.selection.select( clipboard, true );
     121            }
    121122        }
    122123
    123124        editor.nodeChanged();
    124125        editor.fire( 'wpview-selected', viewNode );
    125     }
    126 
    127     function adjustToolbarPosition( viewNode ) {
    128         var delta = 0,
    129             toolbar = editor.$( viewNode ).find( '.toolbar' ),
    130             editorToolbar = tinymce.$( editor.editorContainer ).find( '.mce-toolbar-grp' )[0],
    131             editorToolbarBottom = ( editorToolbar && editorToolbar.getBoundingClientRect().bottom ) || 0;
    132 
    133         if ( toolbar.length && editor.iframeElement ) {
    134             // 48 = 43 for the toolbar + 5 buffer
    135             delta = viewNode.getBoundingClientRect().top + editor.iframeElement.getBoundingClientRect().top - editorToolbarBottom - 48;
    136         }
    137 
    138         if ( delta < 0 ) {
    139             toolbar.removeClass( 'mce-arrow-down' ).css({ top: ( -43 + delta * -1 ) });
    140         } else if ( delta > 0 && ! toolbar.hasClass( 'mce-arrow-down' ) ) {
    141             toolbar.addClass( 'mce-arrow-down' ).css({ top: '' });
    142         }
    143126    }
    144127
     
    258241            MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
    259242
     243        toolbar = editor.wp._createToolbar( [
     244            'wp_view_edit',
     245            'wp_view_remove'
     246        ] );
     247
    260248        // When a view is selected, ensure content that is being pasted
    261249        // or inserted is added to a text node (instead of the view).
     
    298286                event.stopImmediatePropagation();
    299287                event.preventDefault();
    300 
    301                 if ( ( event.type === 'touchend' || event.type === 'mousedown' ) && ! event.metaKey && ! event.ctrlKey ) {
    302                     if ( editor.dom.hasClass( event.target, 'edit' ) ) {
    303 
    304                         // In IE need to transfer focus from the non-editable view back to the editor.
    305                         if ( Env.ie ) {
    306                             editor.focus();
    307                         }
    308 
    309                         wp.mce.views.edit( editor, view );
    310                         return false;
    311                     } else if ( editor.dom.hasClass( event.target, 'remove' ) ) {
    312                         removeView( view );
    313                         return false;
    314                     }
    315                 }
    316288
    317289                if ( event.type === 'touchend' && scrolled ) {
     
    686658    });
    687659
     660    editor.addButton( 'wp_view_edit', {
     661        tooltip: 'Edit ', // trailing space is needed, used for context
     662        icon: 'dashicon dashicons-edit',
     663        onclick: function() {
     664            selected && wp.mce.views.edit( editor, selected );
     665        }
     666    } );
     667
     668    editor.addButton( 'wp_view_remove', {
     669        tooltip: 'Remove',
     670        icon: 'dashicon dashicons-no',
     671        onclick: function() {
     672            selected && removeView( selected );
     673        }
     674    } );
     675
     676    editor.on( 'wptoolbar', function( event ) {
     677        if ( selected ) {
     678            event.element = selected;
     679            event.toolbar = toolbar;
     680        }
     681    } );
     682
     683    // Add to editor.wp
     684    editor.wp = editor.wp || {};
     685    editor.wp.getView = getView;
     686
     687    // Keep for back-compat.
    688688    return {
    689689        getView: getView
  • trunk/src/wp-includes/js/tinymce/skins/wordpress/wp-content.css

    r30694 r31725  
    320320}
    321321
    322 .wpview-wrap .toolbar {
    323     position: absolute;
    324     top: -43px;
    325     left: 45%;
    326     left: calc(50% - 32px);
    327     display: none;
    328     z-index: 100;
    329     background-color: #f5f5f5;
    330     border: 1px solid #aaa;
    331     padding: 1px;
    332     cursor: default;
    333     -webkit-border-radius: 2px;
    334     border-radius: 2px;
    335     -webkit-box-shadow: 0 1px 4px rgba( 0, 0, 0, 0.2 );
    336     box-shadow: 0 1px 4px rgba( 0, 0, 0, 0.2 );
    337     -webkit-box-sizing: border-box;
    338     -moz-box-sizing: border-box;
    339     box-sizing: border-box;
    340     margin-bottom: 8px;
    341 }
    342 
    343 .wpview-wrap[data-mce-selected] .toolbar {
    344     display: block;
    345 }
    346 
    347 .wpview-wrap .toolbar:before,
    348 .wpview-wrap .toolbar:after {
    349     position: absolute;
    350     left: 50%;
    351     display: block;
    352     width: 0;
    353     height: 0;
    354     border-style: solid;
    355     border-color: transparent;
    356     border-width: 9px;
    357     margin-left: -9px;
    358     content: '';
    359 }
    360 
    361 .wpview-wrap .toolbar:after {
    362     border-width: 8px;
    363     margin-left: -8px;
    364 }
    365 
    366 .wpview-wrap .toolbar.mce-arrow-down:before {
    367     bottom: -18px;
    368     border-top-color: #aaa;
    369 }
    370 
    371 .wpview-wrap .toolbar.mce-arrow-down:after {
    372     bottom: -16px;
    373     border-top-color: #f5f5f5;
    374 }
    375 
    376 .wpview-wrap .toolbar.mce-arrow-up:before {
    377     top: -18px;
    378     border-bottom-color: #aaa;
    379 }
    380 
    381 .wpview-wrap .toolbar.mce-arrow-up:after {
    382     top: -16px;
    383     border-bottom-color: #f5f5f5;
    384 }
    385 
    386 .wpview-wrap .toolbar div {
    387     margin: 2px;
    388     padding: 2px 3px;
    389     width: 20px;
    390     height: 20px;
    391     color: #777;
    392     cursor: pointer;
    393     font-size: 20px;
    394     border: 1px solid transparent;
    395     border-radius: 2px;
    396 }
    397 
    398 .wpview-wrap .toolbar div:hover {
    399     background-color: #fafafa;
    400     border-color: #999;
    401     color: #222;
    402     -webkit-box-shadow: inset 0 1px 0 #fff, 0 1px 0 rgba( 0, 0, 0, 0.08 );
    403     box-shadow: inset 0 1px 0 #fff, 0 1px 0 rgba( 0, 0, 0, 0.08 );
    404     outline: none;
    405 }
    406 
    407322.wpview-wrap .loading-placeholder {
    408323    border: 1px dashed #ccc;
     
    456371}
    457372
    458 .ie8 .wpview-wrap .toolbar div,
    459 .ie7 .wpview-wrap .toolbar div {
    460     display: inline;
    461     padding: 4px;
    462 }
    463 
    464 .ie8 .dashicons-edit,
    465 .ie7 .dashicons-edit {
    466     background-image: url(images/dashicon-edit.png);
    467 }
    468 
    469 .ie8 .dashicons-no,
    470 .ie7 .dashicons-no {
    471     background-image: url(images/dashicon-no.png);
    472 }
    473 
    474373.wpview-error {
    475374    border: 1px solid #dedede;
     
    498397}
    499398
    500 .wont-play {
    501     padding: 4px 0;
    502 }
    503 
    504 .wont-play p {
    505     font-size: 13px;
    506     line-height: 1.3;
    507     display: block;
    508     width: 70%;
    509     margin: 0 15%;
    510     text-align: center;
    511 }
    512 
    513399.wpview-type-gallery:after {
    514400    content: '';
     
    536422    margin: auto;
    537423}
    538 
    539424
    540425.gallery .gallery-item {
Note: See TracChangeset for help on using the changeset viewer.