diff -r 346c88efed21 -r 5e2f62d02dcd wp/wp-includes/js/tinymce/plugins/wordpress/plugin.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/wp/wp-includes/js/tinymce/plugins/wordpress/plugin.js Tue Jun 09 03:35:32 2015 +0200
@@ -0,0 +1,754 @@
+/* global tinymce, getUserSetting, setUserSetting */
+
+// Set the minimum value for the modals z-index higher than #wpadminbar (100000)
+tinymce.ui.FloatPanel.zIndex = 100100;
+
+tinymce.PluginManager.add( 'wordpress', function( editor ) {
+ var DOM = tinymce.DOM,
+ each = tinymce.each,
+ __ = editor.editorManager.i18n.translate,
+ wpAdvButton, style,
+ last = 0;
+
+ if ( typeof window.jQuery !== 'undefined' ) {
+ window.jQuery( document ).triggerHandler( 'tinymce-editor-setup', [ editor ] );
+ }
+
+ function toggleToolbars( state ) {
+ var iframe, initial, toolbars,
+ pixels = 0;
+
+ initial = ( state === 'hide' );
+
+ if ( editor.theme.panel ) {
+ toolbars = editor.theme.panel.find('.toolbar:not(.menubar)');
+ }
+
+ if ( ! toolbars || toolbars.length < 2 || ( state === 'hide' && ! toolbars[1].visible() ) ) {
+ return;
+ }
+
+ if ( ! state && toolbars[1].visible() ) {
+ state = 'hide';
+ }
+
+ each( toolbars, function( toolbar, i ) {
+ if ( i > 0 ) {
+ if ( state === 'hide' ) {
+ toolbar.hide();
+ pixels += 30;
+ } else {
+ toolbar.show();
+ pixels -= 30;
+ }
+ }
+ });
+
+ if ( pixels && ! initial ) {
+ // Resize iframe, not needed in iOS
+ if ( ! tinymce.Env.iOS ) {
+ iframe = editor.getContentAreaContainer().firstChild;
+ DOM.setStyle( iframe, 'height', iframe.clientHeight + pixels );
+ }
+
+ if ( state === 'hide' ) {
+ setUserSetting('hidetb', '0');
+ wpAdvButton && wpAdvButton.active( false );
+ } else {
+ setUserSetting('hidetb', '1');
+ wpAdvButton && wpAdvButton.active( true );
+ }
+ }
+
+ editor.fire( 'wp-toolbar-toggle' );
+ }
+
+ // Add the kitchen sink button :)
+ editor.addButton( 'wp_adv', {
+ tooltip: 'Toolbar Toggle',
+ cmd: 'WP_Adv',
+ onPostRender: function() {
+ wpAdvButton = this;
+ wpAdvButton.active( getUserSetting( 'hidetb' ) === '1' ? true : false );
+ }
+ });
+
+ // Hide the toolbars after loading
+ editor.on( 'PostRender', function() {
+ if ( editor.getParam( 'wordpress_adv_hidden', true ) && getUserSetting( 'hidetb', '0' ) === '0' ) {
+ toggleToolbars( 'hide' );
+ }
+ });
+
+ editor.addCommand( 'WP_Adv', function() {
+ toggleToolbars();
+ });
+
+ editor.on( 'focus', function() {
+ window.wpActiveEditor = editor.id;
+ });
+
+ // Replace Read More/Next Page tags with images
+ editor.on( 'BeforeSetContent', function( e ) {
+ var title;
+
+ if ( e.content ) {
+ if ( e.content.indexOf( '/g, function( match, moretext ) {
+ return '';
+ });
+ }
+
+ if ( e.content.indexOf( '' ) !== -1 ) {
+ title = __( 'Page break' );
+
+ e.content = e.content.replace( //g,
+ '
' );
+ }
+ }
+ });
+
+ // Replace images with tags
+ editor.on( 'PostProcess', function( e ) {
+ if ( e.get ) {
+ e.content = e.content.replace(/
]+>/g, function( image ) {
+ var match, moretext = '';
+
+ if ( image.indexOf( 'data-wp-more="more"' ) !== -1 ) {
+ if ( match = image.match( /data-wp-more-text="([^"]+)"/ ) ) {
+ moretext = match[1];
+ }
+
+ image = '';
+ } else if ( image.indexOf( 'data-wp-more="nextpage"' ) !== -1 ) {
+ image = '';
+ }
+
+ return image;
+ });
+ }
+ });
+
+ // Display the tag name instead of img in element path
+ editor.on( 'ResolveName', function( event ) {
+ var attr;
+
+ if ( event.target.nodeName === 'IMG' && ( attr = editor.dom.getAttrib( event.target, 'data-wp-more' ) ) ) {
+ event.name = attr;
+ }
+ });
+
+ // Register commands
+ editor.addCommand( 'WP_More', function( tag ) {
+ var parent, html, title,
+ classname = 'wp-more-tag',
+ dom = editor.dom,
+ node = editor.selection.getNode();
+
+ tag = tag || 'more';
+ classname += ' mce-wp-' + tag;
+ title = tag === 'more' ? 'Read more...' : 'Next page';
+ title = __( title );
+ html = '
';
+
+ // Most common case
+ if ( node.nodeName === 'BODY' || ( node.nodeName === 'P' && node.parentNode.nodeName === 'BODY' ) ) {
+ editor.insertContent( html );
+ return;
+ }
+
+ // Get the top level parent node
+ parent = dom.getParent( node, function( found ) {
+ if ( found.parentNode && found.parentNode.nodeName === 'BODY' ) {
+ return true;
+ }
+
+ return false;
+ }, editor.getBody() );
+
+ if ( parent ) {
+ if ( parent.nodeName === 'P' ) {
+ parent.appendChild( dom.create( 'p', null, html ).firstChild );
+ } else {
+ dom.insertAfter( dom.create( 'p', null, html ), parent );
+ }
+
+ editor.nodeChanged();
+ }
+ });
+
+ editor.addCommand( 'WP_Code', function() {
+ editor.formatter.toggle('code');
+ });
+
+ editor.addCommand( 'WP_Page', function() {
+ editor.execCommand( 'WP_More', 'nextpage' );
+ });
+
+ editor.addCommand( 'WP_Help', function() {
+ editor.windowManager.open({
+ url: tinymce.baseURL + '/wp-mce-help.php',
+ title: 'Keyboard Shortcuts',
+ width: 450,
+ height: 420,
+ classes: 'wp-help',
+ buttons: { text: 'Close', onclick: 'close' }
+ });
+ });
+
+ editor.addCommand( 'WP_Medialib', function() {
+ if ( typeof wp !== 'undefined' && wp.media && wp.media.editor ) {
+ wp.media.editor.open( editor.id );
+ }
+ });
+
+ // Register buttons
+ editor.addButton( 'wp_more', {
+ tooltip: 'Insert Read More tag',
+ onclick: function() {
+ editor.execCommand( 'WP_More', 'more' );
+ }
+ });
+
+ editor.addButton( 'wp_page', {
+ tooltip: 'Page break',
+ onclick: function() {
+ editor.execCommand( 'WP_More', 'nextpage' );
+ }
+ });
+
+ editor.addButton( 'wp_help', {
+ tooltip: 'Keyboard Shortcuts',
+ cmd: 'WP_Help'
+ });
+
+ editor.addButton( 'wp_code', {
+ tooltip: 'Code',
+ cmd: 'WP_Code',
+ stateSelector: 'code'
+ });
+
+ // Menubar
+ // Insert->Add Media
+ if ( typeof wp !== 'undefined' && wp.media && wp.media.editor ) {
+ editor.addMenuItem( 'add_media', {
+ text: 'Add Media',
+ icon: 'wp-media-library',
+ context: 'insert',
+ cmd: 'WP_Medialib'
+ });
+ }
+
+ // Insert "Read More..."
+ editor.addMenuItem( 'wp_more', {
+ text: 'Insert Read More tag',
+ icon: 'wp_more',
+ context: 'insert',
+ onclick: function() {
+ editor.execCommand( 'WP_More', 'more' );
+ }
+ });
+
+ // Insert "Next Page"
+ editor.addMenuItem( 'wp_page', {
+ text: 'Page break',
+ icon: 'wp_page',
+ context: 'insert',
+ onclick: function() {
+ editor.execCommand( 'WP_More', 'nextpage' );
+ }
+ });
+
+ editor.on( 'BeforeExecCommand', function(e) {
+ if ( tinymce.Env.webkit && ( e.command === 'InsertUnorderedList' || e.command === 'InsertOrderedList' ) ) {
+ if ( ! style ) {
+ style = editor.dom.create( 'style', {'type': 'text/css'},
+ '#tinymce,#tinymce span,#tinymce li,#tinymce li>span,#tinymce p,#tinymce p>span{font:medium sans-serif;color:#000;line-height:normal;}');
+ }
+
+ editor.getDoc().head.appendChild( style );
+ }
+ });
+
+ editor.on( 'ExecCommand', function( e ) {
+ if ( tinymce.Env.webkit && style &&
+ ( 'InsertUnorderedList' === e.command || 'InsertOrderedList' === e.command ) ) {
+
+ editor.dom.remove( style );
+ }
+ });
+
+ editor.on( 'init', function() {
+ var env = tinymce.Env,
+ bodyClass = ['mceContentBody'], // back-compat for themes that use this in editor-style.css...
+ doc = editor.getDoc(),
+ dom = editor.dom;
+
+ if ( tinymce.Env.iOS ) {
+ dom.addClass( doc.documentElement, 'ios' );
+ }
+
+ if ( editor.getParam( 'directionality' ) === 'rtl' ) {
+ bodyClass.push('rtl');
+ dom.setAttrib( doc.documentElement, 'dir', 'rtl' );
+ }
+
+ if ( env.ie ) {
+ if ( parseInt( env.ie, 10 ) === 9 ) {
+ bodyClass.push('ie9');
+ } else if ( parseInt( env.ie, 10 ) === 8 ) {
+ bodyClass.push('ie8');
+ } else if ( env.ie < 8 ) {
+ bodyClass.push('ie7');
+ }
+ } else if ( env.webkit ) {
+ bodyClass.push('webkit');
+ }
+
+ bodyClass.push('wp-editor');
+
+ each( bodyClass, function( cls ) {
+ if ( cls ) {
+ dom.addClass( doc.body, cls );
+ }
+ });
+
+ // Remove invalid parent paragraphs when inserting HTML
+ // TODO: still needed?
+ editor.on( 'BeforeSetContent', function( e ) {
+ if ( e.content ) {
+ e.content = e.content.replace(/
\s*<(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre|address)( [^>]*)?>/gi, '<$1$2>'); + e.content = e.content.replace(/<\/(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre|address)>\s*<\/p>/gi, '$1>'); + } + }); + + if ( typeof window.jQuery !== 'undefined' ) { + window.jQuery( document ).triggerHandler( 'tinymce-editor-init', [editor] ); + } + + if ( window.tinyMCEPreInit && window.tinyMCEPreInit.dragDropUpload ) { + dom.bind( doc, 'dragstart dragend dragover drop', function( event ) { + if ( typeof window.jQuery !== 'undefined' ) { + // Trigger the jQuery handlers. + window.jQuery( document ).trigger( new window.jQuery.Event( event ) ); + } + }); + } + + if ( editor.getParam( 'wp_paste_filters', true ) ) { + if ( ! tinymce.Env.webkit ) { + // In WebKit handled by removeWebKitStyles() + editor.on( 'PastePreProcess', function( event ) { + // Remove all inline styles + event.content = event.content.replace( /(<[^>]+) style="[^"]*"([^>]*>)/gi, '$1$2' ); + + // Put back the internal styles + event.content = event.content.replace(/(<[^>]+) data-mce-style=([^>]+>)/gi, '$1 style=$2' ); + }); + } + + editor.on( 'PastePostProcess', function( event ) { + // Remove empty paragraphs + each( dom.select( 'p', event.node ), function( node ) { + if ( dom.isEmpty( node ) ) { + dom.remove( node ); + } + }); + }); + } + }); + + // Word count + if ( typeof window.jQuery !== 'undefined' ) { + editor.on( 'keyup', function( e ) { + var key = e.keyCode || e.charCode; + + if ( key === last ) { + return; + } + + if ( 13 === key || 8 === last || 46 === last ) { + window.jQuery( document ).triggerHandler( 'wpcountwords', [ editor.getContent({ format : 'raw' }) ] ); + } + + last = key; + }); + } + + editor.on( 'SaveContent', function( e ) { + // If editor is hidden, we just want the textarea's value to be saved + if ( ! editor.inline && editor.isHidden() ) { + e.content = e.element.value; + return; + } + + // Keep empty paragraphs :( + e.content = e.content.replace( /
(?:
|\u00a0|\uFEFF| )*<\/p>/g, '
' ); + + if ( editor.getParam( 'wpautop', true ) && typeof window.switchEditors !== 'undefined' ) { + e.content = window.switchEditors.pre_wpautop( e.content ); + } + }); + + // Remove spaces from empty paragraphs. + editor.on( 'BeforeSetContent', function( event ) { + var paragraph = tinymce.Env.webkit ? '
(?: |\u00a0|\uFEFF|\s)+<\/p>/gi, paragraph ); + } + }); + + editor.on( 'preInit', function() { + // Don't replace with and with and don't remove them when empty + editor.schema.addValidElements( '@[id|accesskey|class|dir|lang|style|tabindex|title|contenteditable|draggable|dropzone|hidden|spellcheck|translate],i,b' ); + + if ( tinymce.Env.iOS ) { + editor.settings.height = 300; + } + + each( { + c: 'JustifyCenter', + r: 'JustifyRight', + l: 'JustifyLeft', + j: 'JustifyFull', + q: 'mceBlockQuote', + u: 'InsertUnorderedList', + o: 'InsertOrderedList', + s: 'unlink', + m: 'WP_Medialib', + z: 'WP_Adv', + t: 'WP_More', + d: 'Strikethrough', + h: 'WP_Help', + p: 'WP_Page', + x: 'WP_Code' + }, function( command, key ) { + editor.shortcuts.add( 'access+' + key, '', command ); + } ); + + editor.addShortcut( 'meta+s', '', function() { + if ( typeof wp !== 'undefined' && wp.autosave ) { + wp.autosave.server.triggerSave(); + } + } ); + } ); + + /** + * Experimental: create a floating toolbar. + * This functionality will change in the next releases. Not recommended for use by plugins. + */ + ( function() { + var Factory = tinymce.ui.Factory, + settings = editor.settings, + currentToolbar, + currentSelection; + + function create( buttons ) { + var toolbar, + toolbarItems = [], + buttonGroup; + + each( buttons, function( item ) { + var itemName; + + function bindSelectorChanged() { + var selection = editor.selection; + + if ( itemName === 'bullist' ) { + selection.selectorChanged( 'ul > li', function( state, args ) { + var i = args.parents.length, + nodeName; + + while ( i-- ) { + nodeName = args.parents[ i ].nodeName; + + if ( nodeName === 'OL' || nodeName == 'UL' ) { + break; + } + } + + item.active( state && nodeName === 'UL' ); + } ); + } + + if ( itemName === 'numlist' ) { + selection.selectorChanged( 'ol > li', function( state, args ) { + var i = args.parents.length, + nodeName; + + 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 + } ] + } ); + + function hide() { + toolbar.hide(); + } + + function reposition() { + 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; + + if ( ! currentSelection ) { + return; + } + + 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'; + 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; + } + + toolbarNode.className = toolbarNode.className.replace( / ?mce-arrow-[\w]+/g, '' ); + toolbarNode.className += className; + + DOM.setStyles( toolbarNode, { 'left': left, 'top': top } ); + + return this; + } + + toolbar.on( 'show', function() { + currentToolbar = this; + this.reposition(); + } ); + + toolbar.on( 'hide', function() { + currentToolbar = false; + } ); + + toolbar.on( 'keydown', function( event ) { + if ( event.keyCode === 27 ) { + this.hide(); + editor.focus(); + } + } ); + + toolbar.on( 'remove', function() { + DOM.unbind( window, 'resize scroll', hide ); + editor.dom.unbind( editor.getWin(), 'resize scroll', hide ); + editor.off( 'blur hide', hide ); + } ); + + editor.once( 'init', function() { + DOM.bind( window, 'resize scroll', hide ); + editor.dom.bind( editor.getWin(), 'resize scroll', hide ); + editor.on( 'blur hide', hide ); + } ); + + toolbar.reposition = reposition; + toolbar.hide().renderTo( document.body ); + + return toolbar; + } + + editor.shortcuts.add( 'alt+119', '', function() { + var node; + + if ( currentToolbar ) { + node = currentToolbar.find( 'toolbar' )[0]; + node && node.focus( true ); + } + } ); + + editor.on( 'nodechange', function( event ) { + var collapsed = editor.selection.isCollapsed(); + + var args = { + element: event.element, + parents: event.parents, + collapsed: collapsed + }; + + editor.fire( 'wptoolbar', args ); + + currentSelection = args.selection || args.element; + + currentToolbar && currentToolbar.hide(); + args.toolbar && args.toolbar.show(); + } ); + + editor.wp = editor.wp || {}; + editor.wp._createToolbar = create; + }()); + + function noop() {} + + // Expose some functions (back-compat) + return { + _showButtons: noop, + _hideButtons: noop, + _setEmbed: noop, + _getEmbed: noop + }; +});