Make WordPress Core

Ticket #28458: 28458.3.patch

File 28458.3.patch, 17.2 KB (added by iseulde, 11 years ago)
  • src/wp-includes/js/mce-view.js

     
    2424         * that the TinyMCE View is not tied to a particular DOM node.
    2525         */
    2626        wp.mce.View = function( options ) {
    27                 options || (options = {});
    28                 _.extend(this, _.pick(options, viewOptions));
    29                 this.initialize.apply(this, arguments);
     27                options = options || {};
     28                _.extend( this, _.pick( options, viewOptions ) );
     29                this.initialize.apply( this, arguments );
    3030        };
    3131
    3232        _.extend( wp.mce.View.prototype, {
     
    3636                        var html = this.getHtml();
    3737                        // Search all tinymce editor instances and update the placeholders
    3838                        _.each( tinymce.editors, function( editor ) {
    39                                 var doc, self = this;
     39                                var self = this;
    4040                                if ( editor.plugins.wpview ) {
    41                                         doc = editor.getDoc();
    42                                         $( doc ).find( '[data-wpview-text="' + this.encodedText + '"]' ).each(function (i, elem) {
    43                                                 var node = $( elem );
     41                                        $( editor.getDoc() ).find( '[data-wpview-text="' + this.encodedText + '"]' ).each( function ( i, element ) {
     42                                                var node = $( element );
    4443                                                // The <ins> is used to mark the end of the wrapper div. Needed when comparing
    4544                                                // the content as string for preventing extra undo levels.
    4645                                                node.html( html ).append( '<ins data-wpview-end="1"></ins>' );
    47                                                 $( self ).trigger( 'ready', elem );
     46                                                $( self ).trigger( 'ready', element );
    4847                                        });
    4948                                }
    5049                        }, this );
     
    7473                 *
    7574                 */
    7675                register: function( type, constructor ) {
     76                        var defaultConstructor = {
     77                                        type: type,
     78                                        toView: function( content ) {
     79                                                var match = wp.shortcode.next( this.type, content );
     80
     81                                                if ( ! match ) {
     82                                                        return;
     83                                                }
     84
     85                                                return {
     86                                                        index: match.index,
     87                                                        content: match.content,
     88                                                        options: {
     89                                                                shortcode: match.shortcode
     90                                                        }
     91                                                };
     92                                        }
     93                                };
     94
     95                        constructor = _.defaults( constructor, defaultConstructor );
     96                        constructor.View = wp.mce.View.extend( constructor.View );
     97
    7798                        views[ type ] = constructor;
    7899                },
    79100
     
    252273                }
    253274        };
    254275
    255         wp.mce.gallery = {
    256                 shortcode: 'gallery',
    257                 toView:  function( content ) {
    258                         var match = wp.shortcode.next( this.shortcode, content );
    259 
    260                         if ( ! match ) {
    261                                 return;
    262                         }
    263 
    264                         return {
    265                                 index:   match.index,
    266                                 content: match.content,
    267                                 options: {
    268                                         shortcode: match.shortcode
    269                                 }
    270                         };
    271                 },
    272                 View: wp.mce.View.extend({
    273                         className: 'editor-gallery',
    274                         template:  media.template('editor-gallery'),
     276        wp.mce.views.register( 'gallery', {
     277                View: {
     278                        template: media.template( 'editor-gallery' ),
    275279
    276280                        // The fallback post ID to use as a parent for galleries that don't
    277281                        // specify the `ids` or `include` parameters.
     
    321325                                return this.template( options );
    322326
    323327                        }
    324                 }),
     328                },
    325329
    326330                edit: function( node ) {
    327331                        var gallery = wp.media.gallery,
     
    338342                                frame.detach();
    339343                        });
    340344                }
    341 
    342         };
    343         wp.mce.views.register( 'gallery', wp.mce.gallery );
    344 
    345         /**
    346          * Tiny MCE Views for Audio / Video
    347          *
    348          */
     345        } );
    349346
    350347        /**
    351          * These are base methods that are shared by each shortcode's MCE controller
     348         * These are base methods that are shared by the audio and video shortcode's MCE controller.
    352349         *
    353350         * @mixin
    354351         */
    355         wp.mce.media = {
     352        wp.mce.av = {
    356353                loaded: false,
    357                 toView: wp.mce.gallery.toView,
     354
     355                View: _.extend( {}, wp.media.mixin, {
     356                        initialize: function( options ) {
     357                                this.players = [];
     358                                this.shortcode = options.shortcode;
     359                                _.bindAll( this, 'setPlayer', 'pausePlayers' );
     360                                $( this ).on( 'ready', this.setPlayer );
     361                                $( 'body' ).on( 'click', '.wp-switch-editor', this.pausePlayers );
     362                                $( document ).on( 'media:edit', this.pausePlayers );
     363                        },
     364       
     365                        /**
     366                         * Creates the player instance for the current node
     367                         *
     368                         * @global MediaElementPlayer
     369                         * @global _wpmejsSettings
     370                         *
     371                         * @param {Event} e
     372                         * @param {HTMLElement} node
     373                         */
     374                        setPlayer: function(e, node) {
     375                                // if the ready event fires on an empty node
     376                                if ( ! node ) {
     377                                        return;
     378                                }
     379       
     380                                var self = this,
     381                                        media,
     382                                        firefox = this.ua.is( 'ff' ),
     383                                        className = '.wp-' +  this.shortcode.tag + '-shortcode';
     384       
     385                                media = $( node ).find( className );
     386       
     387                                if ( ! this.isCompatible( media ) ) {
     388                                        media.closest( '.wpview-wrap' ).addClass( 'wont-play' );
     389                                        if ( ! media.parent().hasClass( 'wpview-wrap' ) ) {
     390                                                media.parent().replaceWith( media );
     391                                        }
     392                                        media.replaceWith( '<p>' + media.find( 'source' ).eq(0).prop( 'src' ) + '</p>' );
     393                                        return;
     394                                } else {
     395                                        media.closest( '.wpview-wrap' ).removeClass( 'wont-play' );
     396                                        if ( firefox ) {
     397                                                media.prop( 'preload', 'metadata' );
     398                                        } else {
     399                                                media.prop( 'preload', 'none' );
     400                                        }
     401                                }
     402       
     403                                media = wp.media.view.MediaDetails.prepareSrc( media.get(0) );
     404       
     405                                setTimeout( function() {
     406                                        wp.mce.av.loaded = true;
     407                                        self.players.push( new MediaElementPlayer( media, self.mejsSettings ) );
     408                                }, wp.mce.av.loaded ? 10 : 500 );
     409                        },
     410       
     411                        /**
     412                         * Pass data to the View's Underscore template and return the compiled output
     413                         *
     414                         * @returns {string}
     415                         */
     416                        getHtml: function() {
     417                                var attrs = this.shortcode.attrs.named;
     418                                attrs.content = this.shortcode.content;
     419       
     420                                return this.template({ model: _.defaults(
     421                                        attrs,
     422                                        wp.media[ this.shortcode.tag ].defaults )
     423                                });
     424                        },
     425       
     426                        unbind: function() {
     427                                this.unsetPlayers();
     428                        }
     429                } ),
    358430
    359431                /**
    360432                 * Called when a TinyMCE view is clicked for editing.
     
    397469        };
    398470
    399471        /**
    400          * Base View class for audio and video shortcodes
    401          *
    402          * @constructor
    403          * @augments wp.mce.View
    404          * @mixes wp.media.mixin
    405          */
    406         wp.mce.media.View = wp.mce.View.extend({
    407                 initialize: function( options ) {
    408                         this.players = [];
    409                         this.shortcode = options.shortcode;
    410                         _.bindAll( this, 'setPlayer', 'pausePlayers' );
    411                         $( this ).on( 'ready', this.setPlayer );
    412                         $( 'body' ).on( 'click', '.wp-switch-editor', this.pausePlayers );
    413                         $( document ).on( 'media:edit', this.pausePlayers );
    414                 },
    415 
    416                 /**
    417                  * Creates the player instance for the current node
    418                  *
    419                  * @global MediaElementPlayer
    420                  * @global _wpmejsSettings
    421                  *
    422                  * @param {Event} e
    423                  * @param {HTMLElement} node
    424                  */
    425                 setPlayer: function(e, node) {
    426                         // if the ready event fires on an empty node
    427                         if ( ! node ) {
    428                                 return;
    429                         }
    430 
    431                         var self = this,
    432                                 media,
    433                                 firefox = this.ua.is( 'ff' ),
    434                                 className = '.wp-' +  this.shortcode.tag + '-shortcode';
    435 
    436                         media = $( node ).find( className );
    437 
    438                         if ( ! this.isCompatible( media ) ) {
    439                                 media.closest( '.wpview-wrap' ).addClass( 'wont-play' );
    440                                 if ( ! media.parent().hasClass( 'wpview-wrap' ) ) {
    441                                         media.parent().replaceWith( media );
    442                                 }
    443                                 media.replaceWith( '<p>' + media.find( 'source' ).eq(0).prop( 'src' ) + '</p>' );
    444                                 return;
    445                         } else {
    446                                 media.closest( '.wpview-wrap' ).removeClass( 'wont-play' );
    447                                 if ( firefox ) {
    448                                         media.prop( 'preload', 'metadata' );
    449                                 } else {
    450                                         media.prop( 'preload', 'none' );
    451                                 }
    452                         }
    453 
    454                         media = wp.media.view.MediaDetails.prepareSrc( media.get(0) );
    455 
    456                         setTimeout( function() {
    457                                 wp.mce.media.loaded = true;
    458                                 self.players.push( new MediaElementPlayer( media, self.mejsSettings ) );
    459                         }, wp.mce.media.loaded ? 10 : 500 );
    460                 },
    461 
    462                 /**
    463                  * Pass data to the View's Underscore template and return the compiled output
    464                  *
    465                  * @returns {string}
    466                  */
    467                 getHtml: function() {
    468                         var attrs = this.shortcode.attrs.named;
    469                         attrs.content = this.shortcode.content;
    470 
    471                         return this.template({ model: _.defaults(
    472                                 attrs,
    473                                 wp.media[ this.shortcode.tag ].defaults )
    474                         });
    475                 },
    476 
    477                 unbind: function() {
    478                         this.unsetPlayers();
    479                 }
    480         });
    481         _.extend( wp.mce.media.View.prototype, wp.media.mixin );
    482 
    483         /**
    484472         * TinyMCE handler for the video shortcode
    485473         *
    486          * @mixes wp.mce.media
     474         * @mixes wp.mce.av
    487475         */
    488         wp.mce.video = _.extend( {}, wp.mce.media, {
    489                 shortcode: 'video',
     476        wp.mce.views.register( 'video', _.extend( {}, wp.mce.av, {
    490477                state: 'video-details',
    491                 View: wp.mce.media.View.extend({
    492                         className: 'editor-video',
    493                         template:  media.template('editor-video')
    494                 })
    495         } );
    496         wp.mce.views.register( 'video', wp.mce.video );
     478                View: _.extend( {}, wp.mce.av.View, {
     479                        template: media.template( 'editor-video' )
     480                } )
     481        } ) );
    497482
    498483        /**
    499484         * TinyMCE handler for the audio shortcode
    500485         *
    501          * @mixes wp.mce.media
     486         * @mixes wp.mce.av
    502487         */
    503         wp.mce.audio = _.extend( {}, wp.mce.media, {
    504                 shortcode: 'audio',
     488        wp.mce.views.register( 'audio', _.extend( {}, wp.mce.av, {
    505489                state: 'audio-details',
    506                 View: wp.mce.media.View.extend({
    507                         className: 'editor-audio',
    508                         template:  media.template('editor-audio')
    509                 })
    510         } );
    511         wp.mce.views.register( 'audio', wp.mce.audio );
     490                View: _.extend( {}, wp.mce.av.View, {
     491                        template: media.template( 'editor-audio' )
     492                } )
     493        } ) );
    512494
    513495        /**
    514          * Base View class for playlist shortcodes
     496         * TinyMCE handler for the playlist shortcode
    515497         *
    516          * @constructor
    517          * @augments wp.mce.View
    518          * @mixes wp.media.mixin
     498         * @mixes wp.mce.av
    519499         */
    520         wp.mce.media.PlaylistView = wp.mce.View.extend({
    521                 className: 'editor-playlist',
    522                 template:  media.template('editor-playlist'),
    523 
    524                 initialize: function( options ) {
    525                         this.players = [];
    526                         this.data = {};
    527                         this.attachments = [];
    528                         this.shortcode = options.shortcode;
    529 
    530                         $( 'body' ).on( 'click', '.wp-switch-editor', this.pausePlayers );
    531                         $( document ).on( 'media:edit', this.pausePlayers );
    532 
    533                         this.fetch();
    534                 },
    535 
    536                 /**
    537                  * Asynchronously fetch the shortcode's attachments
    538                  */
    539                 fetch: function() {
    540                         this.attachments = wp.media.playlist.attachments( this.shortcode );
    541                         this.dfd = this.attachments.more().done( _.bind( this.render, this ) );
    542                 },
    543 
    544                 /**
    545                  * Get the HTML for the view (which also set's the data), replace the
    546                  *   current HTML, and then invoke the WPPlaylistView instance to render
    547                  *   the playlist in the editor
    548                  *
    549                  * @global WPPlaylistView
    550                  * @global tinymce.editors
    551                  */
    552                 render: function() {
    553                         var html = this.getHtml(), self = this;
    554 
    555                         _.each( tinymce.editors, function( editor ) {
    556                                 var doc;
    557                                 if ( editor.plugins.wpview ) {
    558                                         doc = editor.getDoc();
    559                                         $( doc ).find( '[data-wpview-text="' + this.encodedText + '"]' ).each(function (i, elem) {
    560                                                 var node = $( elem );
    561 
    562                                                 // The <ins> is used to mark the end of the wrapper div. Needed when comparing
    563                                                 // the content as string for preventing extra undo levels.
    564                                                 node.html( html ).append( '<ins data-wpview-end="1"></ins>' );
    565 
    566                                                 if ( ! self.data.tracks ) {
    567                                                         return;
    568                                                 }
    569 
    570                                                 self.players.push( new WPPlaylistView({
    571                                                         el: $( elem ).find( '.wp-playlist' ).get(0),
    572                                                         metadata: self.data
    573                                                 }).player );
    574                                         });
     500        wp.mce.views.register( 'playlist', _.extend( {}, wp.mce.av, {
     501                state: ['playlist-edit', 'video-playlist-edit'],
     502                View: _.extend( {}, wp.media.mixin, {
     503                        template:  media.template( 'editor-playlist' ),
     504       
     505                        initialize: function( options ) {
     506                                this.players = [];
     507                                this.data = {};
     508                                this.attachments = [];
     509                                this.shortcode = options.shortcode;
     510       
     511                                $( 'body' ).on( 'click', '.wp-switch-editor', this.pausePlayers );
     512                                $( document ).on( 'media:edit', this.pausePlayers );
     513       
     514                                this.fetch();
     515                               
     516                                $( this ).on( 'ready', this.setPlaylist );
     517                        },
     518       
     519                        /**
     520                         * Asynchronously fetch the shortcode's attachments
     521                         */
     522                        fetch: function() {
     523                                this.attachments = wp.media.playlist.attachments( this.shortcode );
     524                                this.dfd = this.attachments.more().done( _.bind( this.render, this ) );
     525                        },
     526                       
     527                        setPlaylist: function( event, element ) {
     528                                if ( ! this.data.tracks ) {
     529                                        return;
    575530                                }
    576                         }, this );
    577                 },
    578 
    579                 /**
    580                  * Set the data that will be used to compile the Underscore template,
    581                  *  compile the template, and then return it.
    582                  *
    583                  * @returns {string}
    584                  */
    585                 getHtml: function() {
    586                         var data = this.shortcode.attrs.named,
    587                                 model = wp.media.playlist,
    588                                 options,
    589                                 attachments,
    590                                 tracks = [];
    591 
    592                         // Don't render errors while still fetching attachments
    593                         if ( this.dfd && 'pending' === this.dfd.state() && ! this.attachments.length ) {
    594                                 return;
    595                         }
    596 
    597                         _.each( model.defaults, function( value, key ) {
    598                                 data[ key ] = model.coerce( data, key );
    599                         });
    600 
    601                         options = {
    602                                 type: data.type,
    603                                 style: data.style,
    604                                 tracklist: data.tracklist,
    605                                 tracknumbers: data.tracknumbers,
    606                                 images: data.images,
    607                                 artists: data.artists
    608                         };
    609 
    610                         if ( ! this.attachments.length ) {
    611                                 return this.template( options );
    612                         }
    613 
    614                         attachments = this.attachments.toJSON();
    615 
    616                         _.each( attachments, function( attachment ) {
    617                                 var size = {}, resize = {}, track = {
    618                                         src : attachment.url,
    619                                         type : attachment.mime,
    620                                         title : attachment.title,
    621                                         caption : attachment.caption,
    622                                         description : attachment.description,
    623                                         meta : attachment.meta
     531       
     532                                this.players.push( new WPPlaylistView( {
     533                                        el: $( element ).find( '.wp-playlist' ).get( 0 ),
     534                                        metadata: this.data
     535                                } ).player );
     536                        },
     537       
     538                        /**
     539                         * Set the data that will be used to compile the Underscore template,
     540                         *  compile the template, and then return it.
     541                         *
     542                         * @returns {string}
     543                         */
     544                        getHtml: function() {
     545                                var data = this.shortcode.attrs.named,
     546                                        model = wp.media.playlist,
     547                                        options,
     548                                        attachments,
     549                                        tracks = [];
     550       
     551                                // Don't render errors while still fetching attachments
     552                                if ( this.dfd && 'pending' === this.dfd.state() && ! this.attachments.length ) {
     553                                        return;
     554                                }
     555       
     556                                _.each( model.defaults, function( value, key ) {
     557                                        data[ key ] = model.coerce( data, key );
     558                                });
     559       
     560                                options = {
     561                                        type: data.type,
     562                                        style: data.style,
     563                                        tracklist: data.tracklist,
     564                                        tracknumbers: data.tracknumbers,
     565                                        images: data.images,
     566                                        artists: data.artists
    624567                                };
    625 
    626                                 if ( 'video' === data.type ) {
    627                                         size.width = attachment.width;
    628                                         size.height = attachment.height;
    629                                         if ( media.view.settings.contentWidth ) {
    630                                                 resize.width = media.view.settings.contentWidth - 22;
    631                                                 resize.height = Math.ceil( ( size.height * resize.width ) / size.width );
    632                                                 if ( ! options.width ) {
    633                                                         options.width = resize.width;
    634                                                         options.height = resize.height;
     568       
     569                                if ( ! this.attachments.length ) {
     570                                        return this.template( options );
     571                                }
     572       
     573                                attachments = this.attachments.toJSON();
     574       
     575                                _.each( attachments, function( attachment ) {
     576                                        var size = {}, resize = {}, track = {
     577                                                src : attachment.url,
     578                                                type : attachment.mime,
     579                                                title : attachment.title,
     580                                                caption : attachment.caption,
     581                                                description : attachment.description,
     582                                                meta : attachment.meta
     583                                        };
     584       
     585                                        if ( 'video' === data.type ) {
     586                                                size.width = attachment.width;
     587                                                size.height = attachment.height;
     588                                                if ( media.view.settings.contentWidth ) {
     589                                                        resize.width = media.view.settings.contentWidth - 22;
     590                                                        resize.height = Math.ceil( ( size.height * resize.width ) / size.width );
     591                                                        if ( ! options.width ) {
     592                                                                options.width = resize.width;
     593                                                                options.height = resize.height;
     594                                                        }
     595                                                } else {
     596                                                        if ( ! options.width ) {
     597                                                                options.width = attachment.width;
     598                                                                options.height = attachment.height;
     599                                                        }
    635600                                                }
     601                                                track.dimensions = {
     602                                                        original : size,
     603                                                        resized : _.isEmpty( resize ) ? size : resize
     604                                                };
    636605                                        } else {
    637                                                 if ( ! options.width ) {
    638                                                         options.width = attachment.width;
    639                                                         options.height = attachment.height;
    640                                                 }
     606                                                options.width = 400;
    641607                                        }
    642                                         track.dimensions = {
    643                                                 original : size,
    644                                                 resized : _.isEmpty( resize ) ? size : resize
    645                                         };
    646                                 } else {
    647                                         options.width = 400;
    648                                 }
    649 
    650                                 track.image = attachment.image;
    651                                 track.thumb = attachment.thumb;
    652 
    653                                 tracks.push( track );
    654                         } );
    655 
    656                         options.tracks = tracks;
    657                         this.data = options;
    658 
    659                         return this.template( options );
    660                 },
    661 
    662                 unbind: function() {
    663                         this.unsetPlayers();
    664                 }
    665         });
    666         _.extend( wp.mce.media.PlaylistView.prototype, wp.media.mixin );
    667 
    668         /**
    669          * TinyMCE handler for the playlist shortcode
    670          *
    671          * @mixes wp.mce.media
    672          */
    673         wp.mce.playlist = _.extend( {}, wp.mce.media, {
    674                 shortcode: 'playlist',
    675                 state: ['playlist-edit', 'video-playlist-edit'],
    676                 View: wp.mce.media.PlaylistView
    677         } );
    678         wp.mce.views.register( 'playlist', wp.mce.playlist );
     608       
     609                                        track.image = attachment.image;
     610                                        track.thumb = attachment.thumb;
     611       
     612                                        tracks.push( track );
     613                                } );
     614       
     615                                options.tracks = tracks;
     616                                this.data = options;
     617       
     618                                return this.template( options );
     619                        },
     620       
     621                        unbind: function() {
     622                                this.unsetPlayers();
     623                        }
     624                } )
     625        } ) );
    679626
    680627        /**
    681628         * TinyMCE handler for the embed shortcode
    682629         */
    683         wp.mce.embed = {
    684                 shortcode: 'embed',
    685                 toView: wp.mce.gallery.toView,
    686                 View: wp.mce.View.extend( {
    687                         className: 'editor-embed',
     630        wp.mce.views.register( 'embed', {
     631                View: _.extend( {}, wp.media.mixin, {
    688632                        template: media.template( 'editor-embed' ),
    689633                        initialize: function( options ) {
    690634                                this.players = [];
     
    737681                        }
    738682                } ),
    739683                edit: function() {}
    740         };
    741 
    742         _.extend( wp.mce.embed.View.prototype, wp.media.mixin );
    743 
    744         wp.mce.views.register( 'embed', wp.mce.embed );
     684        } );
    745685
    746686}(jQuery));