/* global tinymce */ tinymce.PluginManager.add( 'wpeditimage', function( editor ) { var floatingToolbar, serializer, DOM = tinymce.DOM, settings = editor.settings, Factory = tinymce.ui.Factory, each = tinymce.each, iOS = tinymce.Env.iOS, toolbarIsHidden = true, editorWrapParent = tinymce.$( '#postdivrich' ); function isPlaceholder( node ) { return !! ( editor.dom.getAttrib( node, 'data-mce-placeholder' ) || editor.dom.getAttrib( node, 'data-mce-object' ) ); } editor.addButton( 'wp_img_remove', { tooltip: 'Remove', icon: 'dashicon dashicons-no', onclick: function() { removeImage( editor.selection.getNode() ); } } ); editor.addButton( 'wp_img_edit', { tooltip: 'Edit ', // trailing space is needed, used for context icon: 'dashicon dashicons-edit', onclick: function() { editImage( editor.selection.getNode() ); } } ); each( { alignleft: 'Align left', aligncenter: 'Align center', alignright: 'Align right', alignnone: 'No alignment' }, function( tooltip, name ) { var direction = name.slice( 5 ); editor.addButton( 'wp_img_' + name, { tooltip: tooltip, icon: 'dashicon dashicons-align-' + direction, cmd: 'alignnone' === name ? 'wpAlignNone' : 'Justify' + direction.slice( 0, 1 ).toUpperCase() + direction.slice( 1 ), onPostRender: function() { var self = this; editor.on( 'NodeChange', function( event ) { var node; // Don't bother. if ( event.element.nodeName !== 'IMG' ) { return; } node = editor.dom.getParent( event.element, '.wp-caption' ) || event.element; if ( 'alignnone' === name ) { self.active( ! /\balign(left|center|right)\b/.test( node.className ) ); } else { self.active( editor.dom.hasClass( node, name ) ); } } ); } } ); } ); function toolbarConfig() { var toolbarItems = [], buttonGroup; each( [ 'wp_img_alignleft', 'wp_img_aligncenter', 'wp_img_alignright', 'wp_img_alignnone', 'wp_img_edit', 'wp_img_remove' ], function( item ) { var itemName; function bindSelectorChanged() { var selection = editor.selection; 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 ); } } } } } ); return { type: 'panel', layout: 'stack', classes: 'toolbar-grp inline-toolbar-grp wp-image-toolbar', ariaRoot: true, ariaRemember: true, items: [ { type: 'toolbar', layout: 'flow', items: toolbarItems } ] }; } floatingToolbar = Factory.create( toolbarConfig() ).renderTo( document.body ).hide(); floatingToolbar.reposition = function() { var top, left, minTop, className, windowPos, adminbar, mceToolbar, boundary, boundaryMiddle, boundaryVerticalMiddle, spaceTop, spaceBottom, windowWidth, toolbarWidth, toolbarHalf, iframe, iframePos, iframeWidth, iframeHeigth, toolbarNodeHeight, verticalSpaceNeeded, toolbarNode = this.getEl(), buffer = 5, margin = 8, adminbarHeight = 0, imageNode = editor.selection.getNode(); if ( ! imageNode || imageNode.nodeName !== 'IMG' ) { return this; } windowPos = window.pageYOffset || document.documentElement.scrollTop; adminbar = tinymce.$( '#wpadminbar' )[0]; mceToolbar = tinymce.$( '.mce-toolbar-grp', editor.getContainer() )[0]; boundary = imageNode.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 ( iOS ) { top = boundary.top + iframePos.y + margin; } else { if ( spaceTop >= verticalSpaceNeeded ) { className = ' mce-arrow-down'; top = boundary.top + iframePos.y - toolbarNodeHeight - margin; } else if ( spaceBottom >= verticalSpaceNeeded ) { className = ' mce-arrow-up'; top = boundary.bottom + iframePos.y; } else { top = buffer; if ( boundaryVerticalMiddle >= verticalSpaceNeeded ) { className = ' mce-arrow-down'; } else { className = ' mce-arrow-up'; } } } // Make sure the image toolbar is below the main toolbar. if ( mceToolbar ) { 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. if ( windowPos ) { if ( adminbar && adminbar.getBoundingClientRect().top === 0 ) { adminbarHeight = adminbar.clientHeight; } if ( windowPos + adminbarHeight > minTop ) { minTop = windowPos + adminbarHeight; } } 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 ) { className += ' mce-arrow-full'; left = 0; } else if ( ( left < 0 && boundary.left + toolbarWidth > windowWidth ) || ( left + toolbarWidth > windowWidth && boundary.right - toolbarWidth < 0 ) ) { left = ( windowWidth - toolbarWidth ) / 2; } else if ( left < iframePos.x ) { className += ' mce-arrow-left'; left = boundary.left + iframePos.x; } else if ( left + toolbarWidth > iframeWidth + iframePos.x ) { className += ' mce-arrow-right'; left = boundary.right - toolbarWidth + iframePos.x; } if ( ! iOS ) { toolbarNode.className = toolbarNode.className.replace( / ?mce-arrow-[\w]+/g, '' ); toolbarNode.className += className; } DOM.setStyles( toolbarNode, { 'left': left, 'top': top } ); return this; }; if ( iOS ) { // Safari on iOS fails to select image nodes in contentEditoble mode on touch/click. // Select them again. editor.on( 'click', function( event ) { if ( event.target.nodeName === 'IMG' ) { var node = event.target; window.setTimeout( function() { editor.selection.select( node ); }, 200 ); } else { floatingToolbar.hide(); } }); } editor.on( 'nodechange', function( event ) { var delay = iOS ? 350 : 100; if ( event.element.nodeName !== 'IMG' || isPlaceholder( event.element ) ) { floatingToolbar.hide(); return; } setTimeout( function() { var element = editor.selection.getNode(); if ( element.nodeName === 'IMG' && ! isPlaceholder( element ) ) { if ( floatingToolbar._visible ) { floatingToolbar.reposition(); } else { floatingToolbar.show(); } } else { floatingToolbar.hide(); } }, delay ); } ); function hide() { if ( ! toolbarIsHidden ) { floatingToolbar.hide(); } } floatingToolbar.on( 'show', function() { toolbarIsHidden = false; if ( this._visible ) { this.reposition(); DOM.addClass( this.getEl(), 'mce-inline-toolbar-grp-active' ); } } ); floatingToolbar.on( 'hide', function() { toolbarIsHidden = true; DOM.removeClass( this.getEl(), 'mce-inline-toolbar-grp-active' ); } ); floatingToolbar.on( 'keydown', function( event ) { if ( event.keyCode === 27 ) { hide(); editor.focus(); } } ); DOM.bind( window, 'resize scroll', function() { if ( ! toolbarIsHidden && editorWrapParent.hasClass( 'wp-editor-expand' ) ) { hide(); } }); editor.on( 'init', function() { editor.dom.bind( editor.getWin(), 'scroll', hide ); }); editor.on( 'blur hide', hide ); // 119 = F8 editor.shortcuts.add( 'Alt+119', '', function() { var node = floatingToolbar.find( 'toolbar' )[0]; if ( node ) { node.focus( true ); } }); function parseShortcode( content ) { return content.replace( /(?:
)?\[(?:wp_)?caption([^\]]+)\]([\s\S]+?)\[\/(?:wp_)?caption\](?:<\/p>)?/g, function( a, b, c ) {
var id, align, classes, caption, img, width,
trim = tinymce.trim;
id = b.match( /id=['"]([^'"]*)['"] ?/ );
if ( id ) {
b = b.replace( id[0], '' );
}
align = b.match( /align=['"]([^'"]*)['"] ?/ );
if ( align ) {
b = b.replace( align[0], '' );
}
classes = b.match( /class=['"]([^'"]*)['"] ?/ );
if ( classes ) {
b = b.replace( classes[0], '' );
}
width = b.match( /width=['"]([0-9]*)['"] ?/ );
if ( width ) {
b = b.replace( width[0], '' );
}
c = trim( c );
img = c.match( /((?:]+>)?]+>(?:<\/a>)?)([\s\S]*)/i );
if ( img && img[2] ) {
caption = trim( img[2] );
img = trim( img[1] );
} else {
// old captions shortcode style
caption = trim( b ).replace( /caption=['"]/, '' ).replace( /['"]$/, '' );
img = c;
}
id = ( id && id[1] ) ? id[1].replace( /[<>&]+/g, '' ) : '';
align = ( align && align[1] ) ? align[1] : 'alignnone';
classes = ( classes && classes[1] ) ? ' ' + classes[1].replace( /[<>&]+/g, '' ) : '';
if ( ! width && img ) {
width = img.match( /width=['"]([0-9]*)['"]/ );
}
if ( width && width[1] ) {
width = width[1];
}
if ( ! width || ! caption ) {
return c;
}
width = parseInt( width, 10 );
if ( ! editor.getParam( 'wpeditimage_html5_captions' ) ) {
width += 10;
}
return '