/* global getUserSetting, setUserSetting */ ( function( tinymce ) { // 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 wpAdvButton, style, DOM = tinymce.DOM, each = tinymce.each, __ = editor.editorManager.i18n.translate, $ = window.jQuery, wp = window.wp, hasWpautop = ( wp && wp.editor && wp.editor.autop && editor.getParam( 'wpautop', true ) ); if ( $ ) { $( 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( event ) { var title; if ( event.content ) { if ( event.content.indexOf( '/g, function( match, moretext ) { return ''; }); } if ( event.content.indexOf( '' ) !== -1 ) { title = __( 'Page break' ); event.content = event.content.replace( //g, '' ); } if ( event.load && event.format !== 'raw' && hasWpautop ) { event.content = wp.editor.autop( event.content ); } // Remove spaces from empty paragraphs. // Avoid backtracking, can freeze the editor. See #35890. // (This is also quite faster than using only one regex.) event.content = event.content.replace( /

([^<>]+)<\/p>/gi, function( tag, text ) { if ( /^( |\s|\u00a0|\ufeff)+$/i.test( text ) ) { return '


'; } return tag; }); } }); // 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() { var access = tinymce.Env.mac ? __( 'Ctrl + Alt + letter:' ) : __( 'Shift + Alt + letter:' ), meta = tinymce.Env.mac ? __( 'Cmd + letter:' ) : __( 'Ctrl + letter:' ), table1 = [], table2 = [], header, html, dialog, $wrap; each( [ { c: 'Copy', x: 'Cut' }, { v: 'Paste', a: 'Select all' }, { z: 'Undo', y: 'Redo' }, { b: 'Bold', i: 'Italic' }, { u: 'Underline', k: 'Insert/edit link' } ], function( row ) { table1.push( tr( row ) ); } ); each( [ { 1: 'Heading 1', 2: 'Heading 2' }, { 3: 'Heading 3', 4: 'Heading 4' }, { 5: 'Heading 5', 6: 'Heading 6' }, { l: 'Align left', c: 'Align center' }, { r: 'Align right', j: 'Justify' }, { d: 'Strikethrough', q: 'Blockquote' }, { u: 'Bullet list', o: 'Numbered list' }, { a: 'Insert/edit link', s: 'Remove link' }, { m: 'Insert/edit image', t: 'Insert Read More tag' }, { h: 'Keyboard Shortcuts', x: 'Code' }, { p: 'Insert Page Break tag', w: 'Distraction-free writing mode' } ], function( row ) { table2.push( tr( row ) ); } ); function tr( row ) { var out = ''; each( row, function( text, key ) { if ( ! text ) { out += ''; } else { out += '' + key + '' + __( text ) + ''; } }); return out + ''; } header = [ __( 'Letter' ), __( 'Action' ), __( 'Letter' ), __( 'Action' ) ]; header = '' + header.join( '' ) + ''; html = '
'; // Main section, default and additional shortcuts html = html + '

' + __( 'Default shortcuts,' ) + ' ' + meta + '

' + '' + header + table1.join('') + '
' + '

' + __( 'Additional shortcuts,' ) + ' ' + access + '

' + '' + header + table2.join('') + '
'; if ( editor.plugins.wptextpattern && ( ! tinymce.Env.ie || tinymce.Env.ie > 8 ) ) { // Text pattern section html = html + '

' + __( 'When starting a new paragraph with one of these formatting shortcuts followed by a space, the formatting will be applied automatically. Press Backspace or Escape to undo.' ) + '

' + '' + tr({ '*': 'Bullet list', '1.': 'Numbered list' }) + tr({ '-': 'Bullet list', '1)': 'Numbered list' }) + '
'; html = html + '

' + __( 'The following formatting shortcuts are replaced when pressing Enter. Press Escape or the Undo button to undo.' ) + '

' + '' + tr({ '>': 'Blockquote' }) + tr({ '##': 'Heading 2' }) + tr({ '###': 'Heading 3' }) + tr({ '####': 'Heading 4' }) + tr({ '#####': 'Heading 5' }) + tr({ '######': 'Heading 6' }) + tr({ '---': 'Horizontal line' }) + tr({ '***': 'Horizontal line' }) + '
'; html = html + '

' + __( 'The next group of formatting shortcuts are applied as you type or when you insert them around plain text in the same paragraph. Press Escape or the Undo button to undo.' ) + '

' + '' + tr({ '*': 'Italic', '**': 'Bold' }) + tr({ '_': 'Italic', '__': 'Bold' }) + tr({ '`': 'Code', empty: '' }) + '
'; } // Focus management section html = html + '

' + __( 'Focus shortcuts:' ) + '

' + '' + tr({ 'Alt + F8': 'Inline toolbar (when an image, link or preview is selected)' }) + tr({ 'Alt + F9': 'Editor menu (when enabled)' }) + tr({ 'Alt + F10': 'Editor toolbar' }) + tr({ 'Alt + F11': 'Elements path' }) + '
' + '

' + __( 'To move focus to other buttons use Tab or the arrow keys. To return focus to the editor press Escape or use one of the buttons.' ) + '

'; html += '
'; dialog = editor.windowManager.open( { title: 'Keyboard Shortcuts', items: { type: 'container', classes: 'wp-help', html: html }, buttons: { text: 'Close', onclick: 'close' } } ); if ( dialog.$el ) { dialog.$el.find( 'div[role="application"]' ).attr( 'role', 'document' ); $wrap = dialog.$el.find( '.mce-wp-help' ); if ( $wrap[0] ) { $wrap.attr( 'tabindex', '0' ); $wrap[0].focus(); $wrap.on( 'keydown', function( event ) { // Prevent use of: page up, page down, end, home, left arrow, up arrow, right arrow, down arrow // in the dialog keydown handler. if ( event.keyCode >= 33 && event.keyCode <= 40 ) { event.stopPropagation(); } }); } } } ); editor.addCommand( 'WP_Medialib', function() { if ( wp && 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 ( wp && 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 ( env.iOS ) { dom.addClass( doc.documentElement, 'ios' ); } if ( editor.getParam( 'directionality' ) === 'rtl' ) { bodyClass.push('rtl'); dom.setAttrib( doc.documentElement, 'dir', 'rtl' ); } dom.setAttrib( doc.documentElement, 'lang', editor.getParam( 'wp_lang_attr' ) ); 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 editor.on( 'BeforeSetContent', function( event ) { if ( event.content ) { event.content = event.content.replace( /

\s*<(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre)( [^>]*)?>/gi, '<$1$2>' ) .replace( /<\/(p|div|ul|ol|dl|table|blockquote|h[1-6]|fieldset|pre)>\s*<\/p>/gi, '' ); } }); if ( $ ) { $( document ).triggerHandler( 'tinymce-editor-init', [editor] ); } if ( window.tinyMCEPreInit && window.tinyMCEPreInit.dragDropUpload ) { dom.bind( doc, 'dragstart dragend dragover drop', function( event ) { if ( $ ) { // Trigger the jQuery handlers. $( document ).trigger( new $.Event( event ) ); } }); } if ( editor.getParam( 'wp_paste_filters', true ) ) { editor.on( 'PastePreProcess', function( event ) { // Remove trailing
added by WebKit browsers to the clipboard event.content = event.content.replace( /
/gi, '' ); // In WebKit this is handled by removeWebKitStyles() if ( ! tinymce.Env.webkit ) { // 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 ); } }); }); } }); editor.on( 'SaveContent', function( event ) { // If editor is hidden, we just want the textarea's value to be saved if ( ! editor.inline && editor.isHidden() ) { event.content = event.element.value; return; } // Keep empty paragraphs :( event.content = event.content.replace( /

(?:
|\u00a0|\uFEFF| )*<\/p>/g, '

 

' ); if ( hasWpautop ) { event.content = wp.editor.removep( event.content ); } }); editor.on( 'preInit', function() { var validElementsSetting = '@[id|accesskey|class|dir|lang|style|tabindex|' + 'title|contenteditable|draggable|dropzone|hidden|spellcheck|translate],' + // Global attributes. 'i,' + // Don't replace with and with and don't remove them when empty. 'b,' + 'script[src|async|defer|type|charset|crossorigin|integrity]'; // Add support for