+ while ( i-- ) {
+ nodeName = args.parents[ i ].nodeName;
+
+ if ( nodeName === 'OL' || nodeName === 'UL' ) {
+ break;
+ }
+ }
+
+ item.active( state && nodeName === 'OL' );
+ } );
+ }
+
+ if ( item.settings.stateSelector ) {
+ selection.selectorChanged( item.settings.stateSelector, function( state ) {
+ item.active( state );
+ }, true );
+ }
+
+ if ( item.settings.disabledStateSelector ) {
+ selection.selectorChanged( item.settings.disabledStateSelector, function( state ) {
+ item.disabled( state );
+ } );
+ }
+ }
+
+ if ( item === '|' ) {
+ buttonGroup = null;
+ } else {
+ if ( Factory.has( item ) ) {
+ item = {
+ type: item
+ };
+
+ if ( settings.toolbar_items_size ) {
+ item.size = settings.toolbar_items_size;
+ }
+
+ toolbarItems.push( item );
+
+ buttonGroup = null;
+ } else {
+ if ( ! buttonGroup ) {
+ buttonGroup = {
+ type: 'buttongroup',
+ items: []
+ };
+
+ toolbarItems.push( buttonGroup );
+ }
+
+ if ( editor.buttons[ item ] ) {
+ itemName = item;
+ item = editor.buttons[ itemName ];
+
+ if ( typeof item === 'function' ) {
+ item = item();
+ }
+
+ item.type = item.type || 'button';
+
+ if ( settings.toolbar_items_size ) {
+ item.size = settings.toolbar_items_size;
+ }
+
+ item = Factory.create( item );
+
+ buttonGroup.items.push( item );
+
+ if ( editor.initialized ) {
+ bindSelectorChanged();
+ } else {
+ editor.on( 'init', bindSelectorChanged );
+ }
+ }
+ }
+ }
+ } );
+
+ toolbar = Factory.create( {
+ type: 'panel',
+ layout: 'stack',
+ classes: 'toolbar-grp inline-toolbar-grp',
+ ariaRoot: true,
+ ariaRemember: true,
+ items: [ {
+ type: 'toolbar',
+ layout: 'flow',
+ items: toolbarItems
+ } ]
+ } );
+
+ toolbar.bottom = bottom;
+
+ function reposition() {
+ if ( ! currentSelection ) {
+ return this;
+ }
+
+ var scrollX = window.pageXOffset || document.documentElement.scrollLeft,
+ scrollY = window.pageYOffset || document.documentElement.scrollTop,
+ windowWidth = window.innerWidth,
+ windowHeight = window.innerHeight,
+ iframeRect = mceIframe ? mceIframe.getBoundingClientRect() : {
+ top: 0,
+ right: windowWidth,
+ bottom: windowHeight,
+ left: 0,
+ width: windowWidth,
+ height: windowHeight
+ },
+ toolbar = this.getEl(),
+ toolbarWidth = toolbar.offsetWidth,
+ toolbarHeight = toolbar.offsetHeight,
+ selection = currentSelection.getBoundingClientRect(),
+ selectionMiddle = ( selection.left + selection.right ) / 2,
+ buffer = 5,
+ margin = 8,
+ 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 = '',
+ iosOffsetTop = 0,
+ iosOffsetBottom = 0,
+ top, left;
+
+ if ( spaceTop >= editorHeight || spaceBottom >= editorHeight ) {
+ this.scrolling = true;
+ this.hide();
+ this.scrolling = false;
+ return this;
+ }
+
+ // Add offset in iOS to move the menu over the image, out of the way of the default iOS menu.
+ if ( tinymce.Env.iOS && currentSelection.nodeName === 'IMG' ) {
+ iosOffsetTop = 54;
+ iosOffsetBottom = 46;
+ }
+
+ if ( this.bottom ) {
+ if ( spaceBottom >= spaceNeeded ) {
+ className = ' mce-arrow-up';
+ top = selection.bottom + iframeRect.top + scrollY - iosOffsetBottom;
+ } else if ( spaceTop >= spaceNeeded ) {
+ className = ' mce-arrow-down';
+ top = selection.top + iframeRect.top + scrollY - toolbarHeight - margin + iosOffsetTop;
+ }
+ } else {
+ if ( spaceTop >= spaceNeeded ) {
+ className = ' mce-arrow-down';
+ top = selection.top + iframeRect.top + scrollY - toolbarHeight - margin + iosOffsetTop;
+ } else if ( spaceBottom >= spaceNeeded && editorHeight / 2 > selection.bottom + iframeRect.top - blockedTop ) {
+ className = ' mce-arrow-up';
+ top = selection.bottom + iframeRect.top + scrollY - iosOffsetBottom;
+ }
+ }
+
+ if ( typeof top === 'undefined' ) {
+ top = scrollY + blockedTop + buffer + iosOffsetBottom;
+ }
+
+ left = selectionMiddle - toolbarWidth / 2 + iframeRect.left + scrollX;
+
+ if ( selection.left < 0 || selection.right > iframeRect.width ) {
+ left = iframeRect.left + scrollX + ( iframeRect.width - toolbarWidth ) / 2;
+ } else if ( toolbarWidth >= windowWidth ) {
+ className += ' mce-arrow-full';
+ left = 0;
+ } else if ( ( left < 0 && selection.left + toolbarWidth > windowWidth ) || ( left + toolbarWidth > windowWidth && selection.right - toolbarWidth < 0 ) ) {
+ left = ( windowWidth - toolbarWidth ) / 2;
+ } else if ( left < iframeRect.left + scrollX ) {
+ className += ' mce-arrow-left';
+ left = selection.left + iframeRect.left + scrollX;
+ } else if ( left + toolbarWidth > iframeRect.width + iframeRect.left + scrollX ) {
+ className += ' mce-arrow-right';
+ left = selection.right - toolbarWidth + iframeRect.left + scrollX;
+ }
+
+ // No up/down arrows on the menu over images in iOS.
+ if ( tinymce.Env.iOS && currentSelection.nodeName === 'IMG' ) {
+ className = className.replace( / ?mce-arrow-(up|down)/g, '' );
+ }
+
+ toolbar.className = toolbar.className.replace( / ?mce-arrow-[\w]+/g, '' ) + className;
+
+ DOM.setStyles( toolbar, {
+ 'left': left,
+ 'top': top
+ } );
+
+ return this;
+ }
+
+ toolbar.on( 'show', function() {
+ this.reposition();
+ } );
+
+ toolbar.on( 'keydown', function( event ) {
+ if ( event.keyCode === 27 ) {
+ this.hide();
+ editor.focus();
+ }
+ } );
+
+ editor.on( 'remove', function() {
+ toolbar.remove();
+ } );
+
+ toolbar.reposition = reposition;
+ toolbar.hide().renderTo( document.body );
+
+ return toolbar;