Make WordPress Core

Changeset 22004


Ignore:
Timestamp:
09/26/2012 01:00:08 AM (12 years ago)
Author:
koopersmith
Message:

Add JavaScript methods for handling shortcodes.

Adds wp.shortcode, a set of methods used for parsing shortcodes out of content. Also adds a default set of shortcode properties to wp.mce.view.

fixes #21996, see #21812, #21813, #21815.

Location:
trunk/wp-includes
Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/js/mce-view.js

    r21962 r22004  
     1// Ensure the global `wp` object exists.
    12if ( typeof wp === 'undefined' )
    23    var wp = {};
     
    67        instances = {};
    78
    8     wp.mce = {};
    9 
     9    // Create the `wp.mce` object if necessary.
     10    wp.mce = wp.mce || {};
     11
     12    // wp.mce.view
     13    // -----------
     14    //
     15    // A set of utilities that simplifies adding custom UI within a TinyMCE editor.
     16    // At its core, it serves as a series of converters, transforming text to a
     17    // custom UI, and back again.
    1018    wp.mce.view = {
     19        // ### defaults
    1120        // The default properties used for the objects in `wp.mce.view.add()`.
    1221        defaults: {
     
    1423            text: function( instance ) {
    1524                return instance.options.original;
     25            },
     26
     27            toView: function( content ) {
     28                if ( ! this.pattern )
     29                    return;
     30
     31                this.pattern.lastIndex = 0;
     32                var match = this.pattern.exec( content );
     33
     34                if ( ! match )
     35                    return;
     36
     37                return {
     38                    index:   match.index,
     39                    content: match[0],
     40                    options: {
     41                        original: match[0],
     42                        results:  _.toArray( arguments )
     43                    }
     44                };
    1645            }
    1746        },
    1847
     48        shortcode: {
     49            view: Backbone.View,
     50            text: function( instance ) {
     51                return instance.options.shortcode.text();
     52            },
     53
     54            toView: function( content ) {
     55                var match = wp.shortcode.next( this.tag, content );
     56
     57                if ( ! match )
     58                    return;
     59
     60                return {
     61                    index:   match.index,
     62                    content: match.content,
     63                    options: {
     64                        shortcode: match.shortcode
     65                    }
     66                };
     67            }
     68        },
     69
     70        // ### add( id, options )
    1971        // Registers a new TinyMCE view.
    2072        //
     
    2375        // `options` accepts the following properties:
    2476        //
    25         // `pattern` is the regular expression used to scan the content and
     77        // * `pattern` is the regular expression used to scan the content and
    2678        // detect matching views.
    2779        //
    28         // `view` is a `Backbone.View` constructor. If a plain object is
     80        // * `view` is a `Backbone.View` constructor. If a plain object is
    2981        // provided, it will automatically extend the parent constructor
    3082        // (usually `Backbone.View`). Views are instantiated when the `pattern`
     
    3385        // capture groups, and the `viewType`, which is the constructor's `id`.
    3486        //
    35         // `extend` an existing view by passing in its `id`. The current
     87        // * `extend` an existing view by passing in its `id`. The current
    3688        // view will inherit all properties from the parent view, and if
    3789        // `view` is set to a plain object, it will extend the parent `view`
    3890        // constructor.
    3991        //
    40         // `text` is a method that accepts an instance of the `view`
     92        // * `text` is a method that accepts an instance of the `view`
    4193        // constructor and transforms it into a text representation.
    4294        add: function( id, options ) {
    43             var parent;
    44 
    4595            // Fetch the parent view or the default options.
    46             parent = options.extend ? wp.mce.view.get( options.extend ) : wp.mce.view.defaults;
     96            var parent = options.extend ? wp.mce.view.get( options.extend ) : wp.mce.view.defaults;
    4797
    4898            // Extend the `options` object with the parent's properties.
     
    59109        },
    60110
     111        // ### get( id )
    61112        // Returns a TinyMCE view options object.
    62113        get: function( id ) {
     
    64115        },
    65116
     117        // ### remove( id )
    66118        // Unregisters a TinyMCE view.
    67119        remove: function( id ) {
     
    69121        },
    70122
     123        // ### toViews( content )
    71124        // Scans a `content` string for each view's pattern, replacing any
    72125        // matches with wrapper elements, and creates a new view instance for
     
    75128        // To render the views, call `wp.mce.view.render( scope )`.
    76129        toViews: function( content ) {
     130            var pieces = [ { content: content } ],
     131                current;
     132
    77133            _.each( views, function( view, viewType ) {
    78                 if ( ! view.pattern )
    79                     return;
    80 
    81                 // Scan for matches.
    82                 content = content.replace( view.pattern, function( match ) {
    83                     var instance, id, tag;
    84 
    85                     // Create a new view instance.
    86                     instance = new view.view({
    87                         original: match,
    88                         results:  _.toArray( arguments ),
    89                         viewType: viewType
    90                     });
    91 
    92                     // Use the view's `id` if it already exists. Otherwise,
    93                     // create a new `id`.
    94                     id = instance.el.id = instance.el.id || _.uniqueId('__wpmce-');
    95                     instances[ id ] = instance;
    96 
    97                     // If the view is a span, wrap it in a span.
    98                     tag = 'span' === instance.tagName ? 'span' : 'div';
    99 
    100                     return '<' + tag + ' class="wp-view-wrap" data-wp-view="' + id + '" contenteditable="false"></' + tag + '>';
     134                current = pieces.slice();
     135                pieces  = [];
     136
     137                _.each( current, function( piece ) {
     138                    var remaining = piece.content,
     139                        result;
     140
     141                    // Ignore processed pieces, but retain their location.
     142                    if ( piece.processed ) {
     143                        pieces.push( piece );
     144                        return;
     145                    }
     146
     147                    // Iterate through the string progressively matching views
     148                    // and slicing the string as we go.
     149                    while ( remaining && (result = view.toView( remaining )) ) {
     150                        // Any text before the match becomes an unprocessed piece.
     151                        if ( result.index )
     152                            pieces.push({ content: remaining.substring( 0, result.index ) });
     153
     154                        // Add the processed piece for the match.
     155                        pieces.push({
     156                            content:   wp.mce.view.toView( viewType, result.options ),
     157                            processed: true
     158                        });
     159
     160                        // Update the remaining content.
     161                        remaining = remaining.slice( result.index + result.content.length );
     162                    }
     163
     164                    // There are no additional matches. If any content remains,
     165                    // add it as an unprocessed piece.
     166                    if ( remaining )
     167                        pieces.push({ content: remaining });
    101168                });
    102169            });
    103170
    104             return content;
    105         },
    106 
     171            return _.pluck( pieces, 'content' ).join('');
     172        },
     173
     174        toView: function( viewType, options ) {
     175            var view = wp.mce.view.get( viewType ),
     176                instance, id, tag;
     177
     178            if ( ! view )
     179                return '';
     180
     181            // Create a new view instance.
     182            instance = new view.view( _.extend( options || {}, {
     183                viewType: viewType
     184            }) );
     185
     186            // Use the view's `id` if it already exists. Otherwise,
     187            // create a new `id`.
     188            id = instance.el.id = instance.el.id || _.uniqueId('__wpmce-');
     189            instances[ id ] = instance;
     190
     191            // If the view is a span, wrap it in a span.
     192            tag = 'span' === instance.tagName ? 'span' : 'div';
     193
     194            return '<' + tag + ' class="wp-view-wrap" data-wp-view="' + id + '" contenteditable="false"></' + tag + '>';
     195        },
     196
     197        // ### render( scope )
    107198        // Renders any view instances inside a DOM node `scope`.
    108199        //
     
    131222        },
    132223
     224        // ### toText( content )
    133225        // Scans an HTML `content` string and replaces any view instances with
    134226        // their respective text representations.
  • trunk/wp-includes/js/tinymce/themes/advanced/skins/wp_theme/content.css

    r21961 r22004  
    143143
    144144/* WordPress TinyMCE Previews */
    145 div.wp-preview-wrap {
    146     display: inline;
     145div.wp-view-wrap,
     146div.wp-view {
     147    display: inline-block;
    147148}
  • trunk/wp-includes/script-loader.php

    r21961 r22004  
    323323    ) );
    324324
    325     $scripts->add( 'mce-view', "/wp-includes/js/mce-view$suffix.js", array( 'backbone', 'jquery' ), false, 1 );
     325    $scripts->add( 'shortcode', "/wp-includes/js/shortcode$suffix.js", array( 'underscore' ), false, 1 );
     326    $scripts->add( 'mce-view', "/wp-includes/js/mce-view$suffix.js", array( 'shortcode', 'backbone', 'jquery' ), false, 1 );
    326327
    327328    if ( is_admin() ) {
Note: See TracChangeset for help on using the changeset viewer.