Make WordPress Core

Changeset 40476


Ignore:
Timestamp:
04/19/2017 02:37:29 AM (8 years ago)
Author:
azaozz
Message:

Editor: Provide API for the editor to be dynamically instantiated via JS. First run.

See: #35760

Location:
trunk/src
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/ajax-actions.php

    r40307 r40476  
    14981498    $args['pagenum'] = ! empty( $_POST['page'] ) ? absint( $_POST['page'] ) : 1;
    14991499
    1500     require(ABSPATH . WPINC . '/class-wp-editor.php');
     1500    if ( ! class_exists( '_WP_Editors', false ) ) {
     1501        require( ABSPATH . WPINC . '/class-wp-editor.php' );
     1502    }
     1503
    15011504    $results = _WP_Editors::wp_link_query( $args );
    15021505
  • trunk/src/wp-admin/js/editor.js

    r39912 r40476  
    1 
    2 ( function( $ ) {
     1window.wp = window.wp || {};
     2
     3( function( $, wp ) {
     4    wp.editor = wp.editor || {};
     5
    36    /**
    47     * @summary Utility functions for the editor.
     
    485488        }
    486489
    487         window.wp = window.wp || {};
    488         window.wp.editor = window.wp.editor || {};
    489         window.wp.editor.autop = wpautop;
    490         window.wp.editor.removep = pre_wpautop;
     490        wp.editor.autop = wpautop;
     491        wp.editor.removep = pre_wpautop;
    491492
    492493        exports = {
     
    506507     */
    507508    window.switchEditors = new SwitchEditors();
    508 }( window.jQuery ));
     509
     510    /**
     511     * Initialize TinyMCE and/or Quicktags. For use with wp_enqueue_editor() (PHP).
     512     *
     513     * Intended for use with an existing textarea that will become the Text editor tab.
     514     * The editor width will be the width of the textarea container, height will be adjustable.
     515     *
     516     * Settings for both TinyMCE and Quicktags can be passed on initialization, and are "filtered"
     517     * with custom jQuery events on the document element, wp-before-tinymce-init and wp-before-quicktags-init.
     518     *
     519     * @since 4.8
     520     *
     521     * @param {string} id The HTML id of the textarea that is used for the editor.
     522     *                    Has to be jQuery compliant. No brackets, special chars, etc.
     523     * @param {object} settings Example:
     524     * settings = {
     525     *    // See https://www.tinymce.com/docs/configure/integration-and-setup/.
     526     *    // Alternatively set to `true` to use the defaults.
     527     *    tinymce: {
     528     *        setup: function( editor ) {
     529     *            console.log( 'Editor initialized', editor );
     530     *        }
     531     *    }
     532     *
     533     *    // Alternatively set to `true` to use the defaults.
     534     *    quicktags: {
     535     *        buttons: 'strong,em,link'
     536     *    }
     537     * }
     538     */
     539    wp.editor.initialize = function( id, settings ) {
     540        var init;
     541        var defaults;
     542
     543        if ( ! $ || ! id || ! wp.editor.getDefaultSettings ) {
     544            return;
     545        }
     546
     547        defaults = wp.editor.getDefaultSettings();
     548
     549        // Initialize TinyMCE by default
     550        if ( ! settings ) {
     551            settings = {
     552                tinymce: true
     553            };
     554        }
     555
     556        // Add wrap and the Visual|Text tabs.
     557        if ( settings.tinymce && settings.quicktags ) {
     558            var $textarea = $( '#' + id );
     559            var $wrap = $( '<div>' ).attr( {
     560                    'class': 'wp-core-ui wp-editor-wrap tmce-active',
     561                    id: 'wp-' + id + '-wrap'
     562                } );
     563            var $editorContainer = $( '<div class="wp-editor-container">' );
     564            var $button = $( '<button>' ).attr( {
     565                    type: 'button',
     566                    'data-wp-editor-id': id
     567                } );
     568
     569            $wrap.append(
     570                $( '<div class="wp-editor-tools">' )
     571                    .append( $( '<div class="wp-editor-tabs">' )
     572                        .append( $button.clone().attr({
     573                            id: id + '-tmce',
     574                            'class': 'wp-switch-editor switch-tmce'
     575                        }).text( window.tinymce.translate( 'Visual' ) ) )
     576                        .append( $button.attr({
     577                            id: id + '-html',
     578                            'class': 'wp-switch-editor switch-html'
     579                        }).text( window.tinymce.translate( 'Text' ) ) )
     580                    ).append( $editorContainer )
     581            );
     582
     583            $textarea.after( $wrap );
     584            $editorContainer.append( $textarea );
     585        }
     586
     587        if ( window.tinymce && settings.tinymce ) {
     588            if ( typeof settings.tinymce !== 'object' ) {
     589                settings.tinymce = {};
     590            }
     591
     592            init = $.extend( {}, defaults.tinymce, settings.tinymce );
     593            init.selector = '#' + id;
     594
     595            $( document ).trigger( 'wp-before-tinymce-init', init );
     596            window.tinymce.init( init );
     597
     598            if ( ! window.wpActiveEditor ) {
     599                window.wpActiveEditor = id;
     600            }
     601        }
     602
     603        if ( window.quicktags && settings.quicktags ) {
     604            if ( typeof settings.quicktags !== 'object' ) {
     605                settings.quicktags = {};
     606            }
     607
     608            init = $.extend( {}, defaults.quicktags, settings.quicktags );
     609            init.id = id;
     610
     611            $( document ).trigger( 'wp-before-quicktags-init', init );
     612            window.quicktags( init );
     613
     614            if ( ! window.wpActiveEditor ) {
     615                window.wpActiveEditor = init.id;
     616            }
     617        }
     618    };
     619
     620    /**
     621     * Get the editor content.
     622     *
     623     * Intended for use with editors that were initialized with wp.editor.initialize().
     624     *
     625     * @since 4.8
     626     *
     627     * @param {string} id The HTML id of the editor textarea.
     628     * @return The editor content.
     629     */
     630    wp.editor.getContent = function( id ) {
     631        var editor;
     632
     633        if ( ! $ || ! id ) {
     634            return;
     635        }
     636
     637        if ( window.tinymce ) {
     638            editor = window.tinymce.get( id );
     639
     640            if ( editor && ! editor.isHidden() ) {
     641                editor.save();
     642            }
     643        }
     644
     645        return $( '#' + id ).val();
     646    };
     647
     648}( window.jQuery, window.wp ));
  • trunk/src/wp-includes/class-wp-editor.php

    r40019 r40476  
    2828    private static $old_dfw_compat = false;
    2929    private static $translation;
     30    private static $tinymce_scripts_printed = false;
     31    private static $link_dialog_printed = false;
    3032
    3133    private function __construct() {}
     
    351353
    352354            if ( empty( self::$first_init ) ) {
    353                 self::$baseurl = includes_url( 'js/tinymce' );
    354 
    355                 $mce_locale = get_user_locale();
    356                 self::$mce_locale = $mce_locale = empty( $mce_locale ) ? 'en' : strtolower( substr( $mce_locale, 0, 2 ) ); // ISO 639-1
    357 
    358                 /** This filter is documented in wp-admin/includes/media.php */
    359                 $no_captions = (bool) apply_filters( 'disable_captions', '' );
     355                $baseurl = self::get_baseurl();
     356                $mce_locale = self::get_mce_locale();
    360357                $ext_plugins = '';
    361                 $shortcut_labels = array();
    362 
    363                 foreach ( self::get_translation() as $name => $value ) {
    364                     if ( is_array( $value ) ) {
    365                         $shortcut_labels[$name] = $value[1];
    366                     }
    367                 }
    368358
    369359                if ( $set['teeny'] ) {
     
    377367                     * @param string $editor_id Unique editor identifier, e.g. 'content'.
    378368                     */
    379                     self::$plugins = $plugins = apply_filters( 'teeny_mce_plugins', array( 'colorpicker', 'lists', 'fullscreen', 'image', 'wordpress', 'wpeditimage', 'wplink' ), $editor_id );
     369                    $plugins = apply_filters( 'teeny_mce_plugins', array( 'colorpicker', 'lists', 'fullscreen', 'image', 'wordpress', 'wpeditimage', 'wplink' ), $editor_id );
    380370                } else {
    381371
     
    522512                self::$ext_plugins = $ext_plugins;
    523513
    524                 self::$first_init = array(
    525                     'theme' => 'modern',
    526                     'skin' => 'lightgray',
    527                     'language' => self::$mce_locale,
    528                     'formats' => '{' .
    529                         'alignleft: [' .
    530                             '{selector: "p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li", styles: {textAlign:"left"}},' .
    531                             '{selector: "img,table,dl.wp-caption", classes: "alignleft"}' .
    532                         '],' .
    533                         'aligncenter: [' .
    534                             '{selector: "p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li", styles: {textAlign:"center"}},' .
    535                             '{selector: "img,table,dl.wp-caption", classes: "aligncenter"}' .
    536                         '],' .
    537                         'alignright: [' .
    538                             '{selector: "p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li", styles: {textAlign:"right"}},' .
    539                             '{selector: "img,table,dl.wp-caption", classes: "alignright"}' .
    540                         '],' .
    541                         'strikethrough: {inline: "del"}' .
    542                     '}',
    543                     'relative_urls' => false,
    544                     'remove_script_host' => false,
    545                     'convert_urls' => false,
    546                     'browser_spellcheck' => true,
    547                     'fix_list_elements' => true,
    548                     'entities' => '38,amp,60,lt,62,gt',
    549                     'entity_encoding' => 'raw',
    550                     'keep_styles' => false,
    551                     'cache_suffix' => 'wp-mce-' . $tinymce_version,
    552 
    553                     // Limit the preview styles in the menu/toolbar
    554                     'preview_styles' => 'font-family font-size font-weight font-style text-decoration text-transform',
    555 
    556                     'end_container_on_empty_block' => true,
    557                     'wpeditimage_disable_captions' => $no_captions,
    558                     'wpeditimage_html5_captions' => current_theme_supports( 'html5', 'caption' ),
    559                     'plugins' => implode( ',', $plugins ),
    560                     'wp_lang_attr' => get_bloginfo( 'language' ),
    561                     'wp_shortcut_labels' => wp_json_encode( $shortcut_labels ),
    562                 );
     514                $settings = self::default_settings();
     515                $settings['plugins'] = implode( ',', $plugins );
    563516
    564517                if ( ! empty( $mce_external_plugins ) ) {
    565                     self::$first_init['external_plugins'] = wp_json_encode( $mce_external_plugins );
     518                    $settings['external_plugins'] = wp_json_encode( $mce_external_plugins );
    566519                }
    567520
    568                 $suffix = SCRIPT_DEBUG ? '' : '.min';
    569                 $version = 'ver=' . get_bloginfo( 'version' );
    570                 $dashicons = includes_url( "css/dashicons$suffix.css?$version" );
    571 
    572                 // WordPress default stylesheet and dashicons
    573                 $mce_css = array(
    574                     $dashicons,
    575                     self::$baseurl . '/skins/wordpress/wp-content.css?' . $version
    576                 );
    577 
     521                /** This filter is documented in wp-admin/includes/media.php */
     522                if ( apply_filters( 'disable_captions', '' ) ) {
     523                    $settings['wpeditimage_disable_captions'] = true;
     524                }
     525
     526                $mce_css = $settings['content_css'];
    578527                $editor_styles = get_editor_stylesheets();
     528
    579529                if ( ! empty( $editor_styles ) ) {
    580                     foreach ( $editor_styles as $style ) {
    581                         $mce_css[] = $style;
    582                     }
     530                    $mce_css .= ',' . implode( ',', $editor_styles );
    583531                }
    584532
     
    590538                 * @param string $stylesheets Comma-delimited list of stylesheets.
    591539                 */
    592                 $mce_css = trim( apply_filters( 'mce_css', implode( ',', $mce_css ) ), ' ,' );
    593 
    594                 if ( ! empty($mce_css) )
    595                     self::$first_init['content_css'] = $mce_css;
     540                $mce_css = trim( apply_filters( 'mce_css', $mce_css ), ' ,' );
     541
     542                if ( ! empty( $mce_css ) ) {
     543                    $settings['content_css'] = $mce_css;
     544                } else {
     545                    unset( $settings['content_css'] );
     546                }
     547
     548                self::$first_init = $settings;
    596549            }
    597550
     
    691644            $body_class .= ' locale-' . sanitize_html_class( strtolower( str_replace( '_', '-', get_user_locale() ) ) );
    692645
    693             if ( !empty($set['tinymce']['body_class']) ) {
     646            if ( ! empty( $set['tinymce']['body_class'] ) ) {
    694647                $body_class .= ' ' . $set['tinymce']['body_class'];
    695                 unset($set['tinymce']['body_class']);
     648                unset( $set['tinymce']['body_class'] );
    696649            }
    697650
    698651            $mceInit = array (
    699652                'selector' => "#$editor_id",
    700                 'resize' => 'vertical',
    701                 'menubar' => false,
    702653                'wpautop' => (bool) $set['wpautop'],
    703654                'indent' => ! $set['wpautop'],
    704                 'toolbar1' => implode($mce_buttons, ','),
    705                 'toolbar2' => implode($mce_buttons_2, ','),
    706                 'toolbar3' => implode($mce_buttons_3, ','),
    707                 'toolbar4' => implode($mce_buttons_4, ','),
     655                'toolbar1' => implode( ',', $mce_buttons ),
     656                'toolbar2' => implode( ',', $mce_buttons_2 ),
     657                'toolbar3' => implode( ',', $mce_buttons_3 ),
     658                'toolbar4' => implode( ',', $mce_buttons_4 ),
    708659                'tabfocus_elements' => $set['tabfocus_elements'],
    709660                'body_class' => $body_class
     
    763714     * @return string
    764715     */
    765     private static function _parse_init($init) {
     716    private static function _parse_init( $init ) {
    766717        $options = '';
    767718
    768         foreach ( $init as $k => $v ) {
    769             if ( is_bool($v) ) {
    770                 $val = $v ? 'true' : 'false';
    771                 $options .= $k . ':' . $val . ',';
     719        foreach ( $init as $key => $value ) {
     720            if ( is_bool( $value ) ) {
     721                $val = $value ? 'true' : 'false';
     722                $options .= $key . ':' . $val . ',';
    772723                continue;
    773             } elseif ( !empty($v) && is_string($v) && ( ('{' == $v{0} && '}' == $v{strlen($v) - 1}) || ('[' == $v{0} && ']' == $v{strlen($v) - 1}) || preg_match('/^\(?function ?\(/', $v) ) ) {
    774                 $options .= $k . ':' . $v . ',';
     724            } elseif ( ! empty( $value ) && is_string( $value ) && (
     725                ( '{' == $value{0} && '}' == $value{strlen( $value ) - 1} ) ||
     726                ( '[' == $value{0} && ']' == $value{strlen( $value ) - 1} ) ||
     727                preg_match( '/^\(?function ?\(/', $value ) ) ) {
     728
     729                $options .= $key . ':' . $value . ',';
    775730                continue;
    776731            }
    777             $options .= $k . ':"' . $v . '",';
     732            $options .= $key . ':"' . $value . '",';
    778733        }
    779734
     
    785740     * @static
    786741     */
    787     public static function enqueue_scripts() {
    788         if ( self::$has_tinymce )
    789             wp_enqueue_script('editor');
    790 
    791         if ( self::$has_quicktags ) {
     742    public static function enqueue_scripts( $default_scripts = false ) {
     743        if ( $default_scripts || self::$has_tinymce ) {
     744            wp_enqueue_script( 'editor' );
     745        }
     746
     747        if ( $default_scripts || self::$has_quicktags ) {
    792748            wp_enqueue_script( 'quicktags' );
    793749            wp_enqueue_style( 'buttons' );
    794750        }
    795751
    796         if ( in_array('wplink', self::$plugins, true) || in_array('link', self::$qt_buttons, true) ) {
    797             wp_enqueue_script('wplink');
     752        if ( $default_scripts || in_array( 'wplink', self::$plugins, true ) || in_array( 'link', self::$qt_buttons, true ) ) {
     753            wp_enqueue_script( 'wplink' );
    798754            wp_enqueue_script( 'jquery-ui-autocomplete' );
    799755        }
    800756
    801757        if ( self::$old_dfw_compat ) {
    802             wp_enqueue_script('wp-fullscreen-stub');
     758            wp_enqueue_script( 'wp-fullscreen-stub' );
    803759        }
    804760
     
    807763            wp_enqueue_script( 'media-upload' );
    808764            wp_enqueue_script( 'wp-embed' );
     765        } elseif ( $default_scripts ) {
     766            wp_enqueue_script( 'media-upload' );
    809767        }
    810768
     
    818776         */
    819777        do_action( 'wp_enqueue_editor', array(
    820             'tinymce'   => self::$has_tinymce,
    821             'quicktags' => self::$has_quicktags,
     778            'tinymce'   => ( $default_scripts || self::$has_tinymce ),
     779            'quicktags' => ( $default_scripts || self::$has_quicktags ),
    822780        ) );
     781    }
     782
     783    /**
     784     * Enqueue all editor scripts.
     785     * For use when the editor is going to be initialized after page load.
     786     *
     787     * @since 4.8.0
     788     */
     789    public static function enqueue_default_editor() {
     790        // We are past the point where scripts can be enqueued properly.
     791        if ( did_action( 'wp_enqueue_editor' ) ) {
     792            return;
     793        }
     794
     795        self::enqueue_scripts( true );
     796
     797        // Also add wp-includes/css/editor.css
     798        wp_enqueue_style( 'editor-buttons' );
     799
     800        if ( is_admin() ) {
     801            add_action( 'admin_print_footer_scripts', array( __CLASS__, 'print_default_editor_scripts' ), 45 );
     802        } else {
     803            add_action( 'wp_print_footer_scripts', array( __CLASS__, 'print_default_editor_scripts' ), 45 );
     804        }
     805    }
     806
     807    /**
     808     * Print (output) all editor scripts and default settings.
     809     * For use when the editor is going to be initialized after page load.
     810     *
     811     * @since 4.8.0
     812     *
     813     */
     814    public static function print_default_editor_scripts() {
     815        $settings = self::default_settings();
     816
     817        $settings['toolbar1'] = 'bold,italic,bullist,numlist,link';
     818        $settings['wpautop'] = false;
     819        $settings['indent'] = true;
     820        $settings['elementpath'] = false;
     821
     822        // In production all plugins are loaded (they are in wp-editor.js.gz)
     823        // but only these will be initialized by default.
     824        $settings['plugins'] = implode( ',', array(
     825            'charmap',
     826            'colorpicker',
     827            'hr',
     828            'lists',
     829    //      'media',
     830            'paste',
     831            'tabfocus',
     832            'textcolor',
     833            'fullscreen',
     834            'wordpress',
     835            'wpautoresize',
     836            'wpeditimage',
     837            'wpemoji',
     838            'wpgallery',
     839            'wplink',
     840    //      'wpdialogs',
     841            'wptextpattern',
     842    //      'wpview',
     843        ) );
     844
     845        $settings = self::_parse_init( $settings );
     846
     847        $suffix = SCRIPT_DEBUG ? '' : '.min';
     848        $baseurl = self::get_baseurl();
     849
     850        ?>
     851        <script type="text/javascript">
     852        window.wp = window.wp || {};
     853        window.wp.editor = window.wp.editor || {};
     854        window.wp.editor.getDefaultSettings = function() {
     855            return {
     856                tinymce: <?php echo $settings; ?>,
     857                quicktags: {
     858                    buttons: 'strong,em,link,ul,ol,li,code'
     859                }
     860            };
     861        };
     862
     863        var tinyMCEPreInit = {
     864            baseURL: "<?php echo $baseurl; ?>",
     865            suffix: "<?php echo $suffix; ?>",
     866            mceInit: {},
     867            qtInit: {},
     868            load_ext: function(url,lang){var sl=tinymce.ScriptLoader;sl.markDone(url+'/langs/'+lang+'.js');sl.markDone(url+'/langs/'+lang+'_dlg.js');}
     869        };
     870        </script>
     871        <?php
     872
     873        self::print_tinymce_scripts();
     874
     875        /**
     876         * Fires when the editor scripts are loaded for later initialization,
     877         * after all scripts and settings are printed.
     878         *
     879         * @since 4.8.0
     880         */
     881        do_action( 'print_default_editor_scripts' );
     882
     883        self::wp_link_dialog();
     884    }
     885
     886    public static function get_mce_locale() {
     887        if ( empty( self::$mce_locale ) ) {
     888            $mce_locale = get_user_locale();
     889            self::$mce_locale = empty( $mce_locale ) ? 'en' : strtolower( substr( $mce_locale, 0, 2 ) ); // ISO 639-1
     890        }
     891
     892        return self::$mce_locale;
     893    }
     894
     895    public static function get_baseurl() {
     896        if ( empty( self::$baseurl ) ) {
     897            self::$baseurl = includes_url( 'js/tinymce' );
     898        }
     899
     900        return self::$baseurl;
     901    }
     902
     903    /**
     904     * Returns the default TinyMCE settings.
     905     * Doesn't include plugins, buttons, editor selector.
     906     *
     907     * @return array
     908     */
     909    private static function default_settings() {
     910        global $tinymce_version;
     911
     912        $shortcut_labels = array();
     913
     914        foreach ( self::get_translation() as $name => $value ) {
     915            if ( is_array( $value ) ) {
     916                $shortcut_labels[$name] = $value[1];
     917            }
     918        }
     919
     920        $settings = array(
     921            'theme' => 'modern',
     922            'skin' => 'lightgray',
     923            'language' => self::get_mce_locale(),
     924            'formats' => '{' .
     925                'alignleft: [' .
     926                    '{selector: "p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li", styles: {textAlign:"left"}},' .
     927                    '{selector: "img,table,dl.wp-caption", classes: "alignleft"}' .
     928                '],' .
     929                'aligncenter: [' .
     930                    '{selector: "p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li", styles: {textAlign:"center"}},' .
     931                    '{selector: "img,table,dl.wp-caption", classes: "aligncenter"}' .
     932                '],' .
     933                'alignright: [' .
     934                    '{selector: "p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li", styles: {textAlign:"right"}},' .
     935                    '{selector: "img,table,dl.wp-caption", classes: "alignright"}' .
     936                '],' .
     937                'strikethrough: {inline: "del"}' .
     938            '}',
     939            'relative_urls' => false,
     940            'remove_script_host' => false,
     941            'convert_urls' => false,
     942            'browser_spellcheck' => true,
     943            'fix_list_elements' => true,
     944            'entities' => '38,amp,60,lt,62,gt',
     945            'entity_encoding' => 'raw',
     946            'keep_styles' => false,
     947            'cache_suffix' => 'wp-mce-' . $tinymce_version,
     948            'resize' => 'vertical',
     949            'menubar' => false,
     950
     951            // Limit the preview styles in the menu/toolbar
     952            'preview_styles' => 'font-family font-size font-weight font-style text-decoration text-transform',
     953
     954            'end_container_on_empty_block' => true,
     955            'wpeditimage_html5_captions' => true,
     956            'wp_lang_attr' => get_bloginfo( 'language' ),
     957            'wp_shortcut_labels' => wp_json_encode( $shortcut_labels ),
     958        );
     959
     960        $suffix = SCRIPT_DEBUG ? '' : '.min';
     961        $version = 'ver=' . get_bloginfo( 'version' );
     962
     963        // Default stylesheets
     964        $settings['content_css'] = includes_url( "css/dashicons$suffix.css?$version" ) . ',' .
     965            includes_url( "js/tinymce/skins/wordpress/wp-content.css?$version" );
     966
     967        return $settings;
    823968    }
    824969
     
    10291174            /* translators: word count */
    10301175            'Words: {0}' => sprintf( __( 'Words: %s' ), '{0}' ),
    1031             'Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.' => __( 'Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.' ) . "\n\n" . __( 'If you&#8217;re looking to paste rich content from Microsoft Word, try turning this option off. The editor will clean up text pasted from Word automatically.' ),
    1032             'Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help' => __( 'Rich Text Area. Press Alt-Shift-H for help.' ),
     1176            'Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.' =>
     1177                __( 'Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.' ) . "\n\n" .
     1178                __( 'If you&#8217;re looking to paste rich content from Microsoft Word, try turning this option off. The editor will clean up text pasted from Word automatically.' ),
     1179            'Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help' =>
     1180                __( 'Rich Text Area. Press Alt-Shift-H for help.' ),
    10331181            'Rich Text Area. Press Control-Option-H for help.' => __( 'Rich Text Area. Press Control-Option-H for help.' ),
    1034             'You have unsaved changes are you sure you want to navigate away?' => __( 'The changes you made will be lost if you navigate away from this page.' ),
    1035             'Your browser doesn\'t support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts instead.' => __( 'Your browser does not support direct access to the clipboard. Please use keyboard shortcuts or your browser&#8217;s edit menu instead.' ),
     1182            'You have unsaved changes are you sure you want to navigate away?' =>
     1183                __( 'The changes you made will be lost if you navigate away from this page.' ),
     1184            'Your browser doesn\'t support direct access to the clipboard. Please use the Ctrl+X/C/V keyboard shortcuts instead.' =>
     1185                __( 'Your browser does not support direct access to the clipboard. Please use keyboard shortcuts or your browser&#8217;s edit menu instead.' ),
    10361186
    10371187            // TinyMCE menus
     
    10561206            'Apply'  => __( 'Apply' ), // Tooltip for the 'apply' button in the inline link dialog
    10571207            'Link options'  => __( 'Link options' ), // Tooltip for the 'link options' button in the inline link dialog
     1208            'Visual' => __( 'Visual' ), // Editor switch tab label
     1209            'Text' => __( 'Text' ), // Editor switch tab label
    10581210
    10591211            // Shortcuts help modal
     
    10991251
    11001252    /**
    1101      * Translates the default TinyMCE strings and returns them as JSON encoded object ready to be loaded with tinymce.addI18n().
    1102      * Can be used directly (_WP_Editors::wp_mce_translation()) by passing the same locale as set in the TinyMCE init object.
     1253     * Translates the default TinyMCE strings and returns them as JSON encoded object ready to be loaded with tinymce.addI18n(),
     1254     * or as JS snippet that should run after tinymce.js is loaded.
    11031255     *
    11041256     * @static
     
    11091261    public static function wp_mce_translation( $mce_locale = '', $json_only = false ) {
    11101262        if ( ! $mce_locale ) {
    1111             $mce_locale = self::$mce_locale;
     1263            $mce_locale = self::get_mce_locale();
    11121264        }
    11131265
    11141266        $mce_translation = self::get_translation();
    1115        
     1267
    11161268        foreach ( $mce_translation as $name => $value ) {
    11171269            if ( is_array( $value ) ) {
     
    11511303        }
    11521304
    1153         $baseurl = self::$baseurl ? self::$baseurl : includes_url( 'js/tinymce' );
     1305        $baseurl = self::get_baseurl();
    11541306
    11551307        return "tinymce.addI18n( '$mce_locale', " . wp_json_encode( $mce_translation ) . ");\n" .
     
    11581310
    11591311    /**
     1312     * Print (output) the main TinyMCE scripts.
     1313     *
     1314     * @since 4.8
    11601315     *
    11611316     * @static
     
    11641319     * @global bool   $compress_scripts
    11651320     */
    1166     public static function editor_js() {
     1321    public static function print_tinymce_scripts() {
    11671322        global $tinymce_version, $concatenate_scripts, $compress_scripts;
    11681323
    1169         /**
    1170          * Filters "tiny_mce_version" is deprecated
    1171          *
    1172          * The tiny_mce_version filter is not needed since external plugins are loaded directly by TinyMCE.
    1173          * These plugins can be refreshed by appending query string to the URL passed to "mce_external_plugins" filter.
    1174          * If the plugin has a popup dialog, a query string can be added to the button action that opens it (in the plugin's code).
    1175          */
     1324        if ( self::$tinymce_scripts_printed ) {
     1325            return;
     1326        }
     1327
     1328        self::$tinymce_scripts_printed = true;
     1329
     1330        if ( ! isset( $concatenate_scripts ) ) {
     1331            script_concat_settings();
     1332        }
     1333
    11761334        $version = 'ver=' . $tinymce_version;
    1177         $tmce_on = !empty(self::$mce_settings);
    1178 
    1179         if ( ! isset($concatenate_scripts) )
    1180             script_concat_settings();
     1335        $baseurl = self::get_baseurl();
    11811336
    11821337        $compressed = $compress_scripts && $concatenate_scripts && isset($_SERVER['HTTP_ACCEPT_ENCODING'])
    11831338            && false !== stripos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip');
    11841339
     1340        // Load tinymce.js when running from /src, else load wp-tinymce.js.gz (production) or tinymce.min.js (SCRIPT_DEBUG)
     1341        $mce_suffix = false !== strpos( get_bloginfo( 'version' ), '-src' ) ? '' : '.min';
     1342
     1343        if ( $compressed ) {
     1344            echo "<script type='text/javascript' src='{$baseurl}/wp-tinymce.php?c=1&amp;$version'></script>\n";
     1345        } else {
     1346            echo "<script type='text/javascript' src='{$baseurl}/tinymce{$mce_suffix}.js?$version'></script>\n";
     1347            echo "<script type='text/javascript' src='{$baseurl}/plugins/compat3x/plugin{$suffix}.js?$version'></script>\n";
     1348        }
     1349
     1350        echo "<script type='text/javascript'>\n" . self::wp_mce_translation() . "</script>\n";
     1351    }
     1352
     1353    /**
     1354     * Print (output) the TinyMCE configuration and initialization scripts.
     1355     *
     1356     * @static
     1357     */
     1358    public static function editor_js() {
     1359        $tmce_on = ! empty( self::$mce_settings );
    11851360        $mceInit = $qtInit = '';
     1361
    11861362        if ( $tmce_on ) {
    11871363            foreach ( self::$mce_settings as $editor_id => $init ) {
     
    11891365                $mceInit .= "'$editor_id':{$options},";
    11901366            }
    1191             $mceInit = '{' . trim($mceInit, ',') . '}';
     1367            $mceInit = '{' . trim( $mceInit, ',' ) . '}';
    11921368        } else {
    11931369            $mceInit = '{}';
    11941370        }
    11951371
    1196         if ( !empty(self::$qt_settings) ) {
     1372        if ( ! empty( self::$qt_settings ) ) {
    11971373            foreach ( self::$qt_settings as $editor_id => $init ) {
    11981374                $options = self::_parse_init( $init );
    11991375                $qtInit .= "'$editor_id':{$options},";
    12001376            }
    1201             $qtInit = '{' . trim($qtInit, ',') . '}';
     1377            $qtInit = '{' . trim( $qtInit, ',' ) . '}';
    12021378        } else {
    12031379            $qtInit = '{}';
     
    12111387
    12121388        $suffix = SCRIPT_DEBUG ? '' : '.min';
     1389        $baseurl = self::get_baseurl();
    12131390
    12141391        /**
     
    12241401        <script type="text/javascript">
    12251402        tinyMCEPreInit = {
    1226             baseURL: "<?php echo self::$baseurl; ?>",
     1403            baseURL: "<?php echo $baseurl; ?>",
    12271404            suffix: "<?php echo $suffix; ?>",
    12281405            <?php
     
    12411418        <?php
    12421419
    1243         $baseurl = self::$baseurl;
    1244         // Load tinymce.js when running from /src, else load wp-tinymce.js.gz (production) or tinymce.min.js (SCRIPT_DEBUG)
    1245         $mce_suffix = false !== strpos( get_bloginfo( 'version' ), '-src' ) ? '' : '.min';
    1246 
    12471420        if ( $tmce_on ) {
    1248             if ( $compressed ) {
    1249                 echo "<script type='text/javascript' src='{$baseurl}/wp-tinymce.php?c=1&amp;$version'></script>\n";
    1250             } else {
    1251                 echo "<script type='text/javascript' src='{$baseurl}/tinymce{$mce_suffix}.js?$version'></script>\n";
    1252                 echo "<script type='text/javascript' src='{$baseurl}/plugins/compat3x/plugin{$suffix}.js?$version'></script>\n";
    1253             }
    1254 
    1255             echo "<script type='text/javascript'>\n" . self::wp_mce_translation() . "</script>\n";
     1421            self::print_tinymce_scripts();
    12561422
    12571423            if ( self::$ext_plugins ) {
     
    14351601     */
    14361602    public static function wp_link_dialog() {
     1603        // Run once
     1604        if ( self::$link_dialog_printed ) {
     1605            return;
     1606        }
     1607
     1608        self::$link_dialog_printed = true;
     1609
    14371610        // display: none is required here, see #WP27605
    14381611        ?>
  • trunk/src/wp-includes/css/editor.css

    r39367 r40476  
    609609
    610610/* Menubar */
    611 .mce-menubar {
     611div.mce-menubar {
    612612    border-color: #e5e5e5;
    613613    background: #fff;
    614614    border-width: 0px 0px 1px;
    615 }
    616 
    617 .mce-menubar .mce-menubtn {
    618     margin: 2px;
    619615}
    620616
     
    10921088.wp-editor-container {
    10931089    clear: both;
     1090    border: 1px solid #e5e5e5;
    10941091}
    10951092
  • trunk/src/wp-includes/general-template.php

    r40254 r40476  
    30583058
    30593059/**
     3060 * Outputs the editor scripts, stylesheets, and default settings.
     3061 *
     3062 * The editor can be initialized when needed after page load.
     3063 * See wp.editor.initialize() in wp-admin/js/editor.js for initialization options.
     3064 *
     3065 * @uses _WP_Editors
     3066 * @since 4.8.0
     3067 */
     3068function wp_enqueue_editor() {
     3069    if ( ! class_exists( '_WP_Editors', false ) ) {
     3070        require( ABSPATH . WPINC . '/class-wp-editor.php' );
     3071    }
     3072
     3073    _WP_Editors::enqueue_default_editor();
     3074}
     3075
     3076/**
    30603077 * Retrieves the contents of the search WordPress query variable.
    30613078 *
Note: See TracChangeset for help on using the changeset viewer.