WordPress.org

Make WordPress Core

Changeset 27411


Ignore:
Timestamp:
03/05/14 15:06:00 (4 years ago)
Author:
wonderboymusic
Message:

Add TinyMCE placeholders for audio and video shortcodes.

  • Add wp.media.mixin.
  • Add wp.media.audio and wp.media.video.
  • Add wp.media.model.PostAudio and wp.media.model.PostVideo
  • Add wp.media.controller.AudioDetails and wp.media.controller.VideoDetails.
  • Add wp.media.controller.ReplaceAudio and wp.media.controller.ReplaceVideo.
  • Add wp.media.view.MediaFrame.AudioDetails and wp.media.view.MediaFrame.VideoDetails.
  • Add wp.media.view.AudioDetails and wp.media.view.VideoDetails.
  • Update the wpgallery TinyMCE plugin.
  • Display audio and video players in the media modal when shortcode is clicked.
  • Provide a UI to edit shortcode attributes in the media modal.
  • Provide a UI to replace the src media file in an audio or video shortcode.

See #27016.

Location:
trunk/src/wp-includes
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/css/media-views.css

    r27289 r27411  
    14611461 
    14621462.embed-link-settings, 
    1463 .embed-image-settings { 
     1463.embed-media-settings { 
    14641464    position: absolute; 
    14651465    top: 60px; 
     
    14711471} 
    14721472 
    1473 .image-details .embed-image-settings { 
     1473.image-details .embed-media-settings { 
    14741474    top: 0; 
    14751475} 
     
    15241524} 
    15251525 
    1526 .media-embed .setting input, 
     1526.media-embed .setting input[type="text"], 
    15271527.media-embed .setting textarea { 
    15281528    display: block; 
     
    18731873    /* Image From Link */ 
    18741874    .embed-link-settings, 
    1875     .embed-image-settings { 
     1875    .embed-media-settings { 
    18761876        padding-bottom: 52px; 
    18771877    } 
  • trunk/src/wp-includes/js/media-editor.js

    r27343 r27411  
    275275    }; 
    276276 
     277    wp.media.mixin = { 
     278        /** 
     279         * A helper function to avoid truthy and falsey values being 
     280         *   passed as an input that expects booleans. If key is undefined in the map, 
     281         *   but has a default value, set it. 
     282         * 
     283         * @param {object} attrs Map of props from a shortcode or settings. 
     284         * @param {string} key The key within the passed map to check for a value. 
     285         * @returns {mixed|undefined} The original or coerced value of key within attrs 
     286         */ 
     287        coerce: function ( attrs, key ) { 
     288            if ( _.isUndefined( attrs[ key ] ) && ! _.isUndefined( this.defaults[ key ] ) ) { 
     289                attrs[ key ] = this.defaults[ key ]; 
     290            } else if ( 'true' === attrs[ key ] ) { 
     291                attrs[ key ] = true; 
     292            } else if ( 'false' === attrs[ key ] ) { 
     293                attrs[ key ] = false; 
     294            } 
     295            return attrs[ key ]; 
     296        } 
     297    }; 
     298 
    277299    wp.media.collection = function(attributes) { 
    278300        var collections = {}; 
    279301 
    280         return _.extend( attributes, { 
    281             /** 
    282              * A helper function to avoid truthy and falsey values being 
    283              *   passed as an input that expects booleans. If key is undefined in the map, 
    284              *   but has a default value, set it. 
    285              * 
    286              * @param {object} attrs Map of props from a shortcode or settings. 
    287              * @param {string} key The key within the passed map to check for a value. 
    288              * @returns {mixed|undefined} The original or coerced value of key within attrs 
    289              */ 
    290             coerce: function ( attrs, key ) { 
    291                 if ( _.isUndefined( attrs[ key ] ) && ! _.isUndefined( this.defaults[ key ] ) ) { 
    292                     attrs[ key ] = this.defaults[ key ]; 
    293                 } else if ( 'true' === attrs[ key ] ) { 
    294                     attrs[ key ] = true; 
    295                 } else if ( 'false' === attrs[ key ] ) { 
    296                     attrs[ key ] = false; 
    297                 } 
    298                 return attrs[ key ]; 
    299             }, 
     302        return _.extend( attributes, wp.media.mixin, { 
    300303            /** 
    301304             * Retrieve attachments based on the properties of the passed shortcode 
     
    537540    }); 
    538541 
    539     wp.media['video-playlist'] = new wp.media.collection( { 
     542    wp.media['video-playlist'] = new wp.media.collection({ 
    540543        tag: 'video-playlist', 
    541544        type : 'video', 
     
    548551            images: true 
    549552        } 
    550     } ); 
     553    }); 
     554 
     555    wp.media.audio = _.extend({ 
     556        defaults : { 
     557            id : wp.media.view.settings.post.id, 
     558            src      : '', 
     559            loop     : false, 
     560            autoplay : false, 
     561            preload  : 'none' 
     562        }, 
     563 
     564        edit : function (data) { 
     565            var frame, shortcode = wp.shortcode.next( 'audio', data ).shortcode; 
     566            frame = wp.media({ 
     567                frame: 'audio', 
     568                state: 'audio-details', 
     569                metadata: _.defaults( 
     570                    shortcode.attrs.named, 
     571                    wp.media.audio.defaults 
     572                ) 
     573            }); 
     574 
     575            return frame; 
     576        }, 
     577 
     578        shortcode : function (shortcode) { 
     579            var self = this; 
     580 
     581            _.each( wp.media.audio.defaults, function( value, key ) { 
     582                shortcode[ key ] = self.coerce( shortcode, key ); 
     583 
     584                if ( value === shortcode[ key ] ) { 
     585                    delete shortcode[ key ]; 
     586                } 
     587            }); 
     588 
     589            return wp.shortcode.string({ 
     590                tag:     'audio', 
     591                attrs:   shortcode 
     592            }); 
     593        } 
     594    }, wp.media.mixin); 
     595 
     596    wp.media.video = _.extend({ 
     597        defaults : { 
     598            id : wp.media.view.settings.post.id, 
     599            src : '', 
     600            poster : '', 
     601            loop : false, 
     602            autoplay : false, 
     603            preload : 'metadata' 
     604        }, 
     605 
     606        edit : function (data) { 
     607            var frame, shortcode = wp.shortcode.next( 'video', data ).shortcode; 
     608            frame = wp.media({ 
     609                frame: 'video', 
     610                state: 'video-details', 
     611                metadata: _.defaults( 
     612                    shortcode.attrs.named, 
     613                    wp.media.video.defaults 
     614                ) 
     615            }); 
     616 
     617            return frame; 
     618        }, 
     619 
     620        shortcode : function (shortcode) { 
     621            var self = this; 
     622            _.each( wp.media.video.defaults, function( value, key ) { 
     623                shortcode[ key ] = self.coerce( shortcode, key ); 
     624 
     625                if ( value === shortcode[ key ] ) { 
     626                    delete shortcode[ key ]; 
     627                } 
     628            }); 
     629 
     630            return wp.shortcode.string({ 
     631                tag:     'video', 
     632                attrs:   shortcode 
     633            }); 
     634        } 
     635    }, wp.media.mixin); 
    551636 
    552637    /** 
  • trunk/src/wp-includes/js/media-models.js

    r27051 r27411  
    3333        } else if ( 'image' === attributes.frame && MediaFrame.ImageDetails ) { 
    3434            frame = new MediaFrame.ImageDetails( attributes ); 
     35        } else if ( 'audio' === attributes.frame && MediaFrame.AudioDetails ) { 
     36            frame = new MediaFrame.AudioDetails( attributes ); 
     37        } else if ( 'video' === attributes.frame && MediaFrame.VideoDetails ) { 
     38            frame = new MediaFrame.VideoDetails( attributes ); 
    3539        } 
    3640 
     
    445449            this.set( 'width', size.width ); 
    446450            this.set( 'height', size.height ); 
     451        } 
     452    }); 
     453 
     454    /** 
     455     * wp.media.model.PostAudio 
     456     * 
     457     * @constructor 
     458     * @augments Backbone.Model 
     459     **/ 
     460    PostAudio = media.model.PostAudio = Backbone.Model.extend({ 
     461        initialize: function() { 
     462            this.attachment = false; 
     463        }, 
     464 
     465        changeAttachment: function( attachment, props ) { 
     466            var self = this; 
     467 
     468            this.attachment = attachment; 
     469            this.extension = attachment.get('filename' ).split('.').pop(); 
     470 
     471            if ( _.contains( wp.media.view.settings.embedExts, this.extension ) ) { 
     472                this.set( this.extension, attachment.get( 'url' ) ); 
     473            } else { 
     474                this.set( this.extension, '' ); 
     475            } 
     476 
     477            _.each( _.without( wp.media.view.settings.embedExts, this.extension ), function (ext) { 
     478                self.set( ext, '' ); 
     479            } ); 
     480        } 
     481    }); 
     482 
     483    /** 
     484     * wp.media.model.PostVideo 
     485     * 
     486     * @constructor 
     487     * @augments Backbone.Model 
     488     **/ 
     489    PostVideo = media.model.PostVideo = Backbone.Model.extend({ 
     490        initialize: function() { 
     491            this.attachment = false; 
     492        }, 
     493 
     494        changeAttachment: function( attachment, props ) { 
     495            var self = this; 
     496 
     497            this.attachment = attachment; 
     498            this.extension = attachment.get('filename' ).split('.').pop(); 
     499 
     500            if ( _.contains( wp.media.view.settings.embedExts, this.extension ) ) { 
     501                this.set( this.extension, attachment.get( 'url' ) ); 
     502            } else { 
     503                this.set( this.extension, '' ); 
     504            } 
     505 
     506            _.each( _.without( wp.media.view.settings.embedExts, this.extension ), function (ext) { 
     507                self.set( ext, '' ); 
     508            } ); 
    447509        } 
    448510    }); 
  • trunk/src/wp-includes/js/media-views.js

    r27378 r27411  
    11/* global _wpMediaViewsL10n, confirm, getUserSetting, setUserSetting */ 
    2 (function($){ 
     2(function($, _){ 
    33    var media = wp.media, l10n; 
    44 
     
    761761 
    762762    /** 
     763     * wp.media.controller.AudioDetails 
     764     * 
     765     * @constructor 
     766     * @augments wp.media.controller.State 
     767     * @augments Backbone.Model 
     768     */ 
     769    media.controller.AudioDetails = media.controller.State.extend({ 
     770        defaults: _.defaults({ 
     771            id: 'audio-details', 
     772            toolbar: 'audio-details', 
     773            title: l10n.audioDetailsTitle, 
     774            content: 'audio-details', 
     775            menu: 'audio-details', 
     776            router: false, 
     777            attachment: false, 
     778            priority: 60, 
     779            editing: false 
     780        }, media.controller.Library.prototype.defaults ), 
     781 
     782        initialize: function( options ) { 
     783            this.audio = options.audio; 
     784            media.controller.State.prototype.initialize.apply( this, arguments ); 
     785        } 
     786    }); 
     787 
     788    /** 
     789     * wp.media.controller.VideoDetails 
     790     * 
     791     * @constructor 
     792     * @augments wp.media.controller.State 
     793     * @augments Backbone.Model 
     794     */ 
     795    media.controller.VideoDetails = media.controller.State.extend({ 
     796        defaults: _.defaults({ 
     797            id: 'video-details', 
     798            toolbar: 'video-details', 
     799            title: l10n.videoDetailsTitle, 
     800            content: 'video-details', 
     801            menu: 'video-details', 
     802            router: false, 
     803            attachment: false, 
     804            priority: 60, 
     805            editing: false 
     806        }, media.controller.Library.prototype.defaults ), 
     807 
     808        initialize: function( options ) { 
     809            this.video = options.video; 
     810            media.controller.State.prototype.initialize.apply( this, arguments ); 
     811        } 
     812    }); 
     813 
     814    /** 
    763815     * wp.media.controller.CollectionEdit 
    764816     * 
     
    10631115            var selection = this.get('selection'), 
    10641116                attachment = this.image.attachment; 
     1117 
     1118            selection.reset( attachment ? [ attachment ] : [] ); 
     1119        } 
     1120    }); 
     1121 
     1122    /** 
     1123     * wp.media.controller.ReplaceVideo 
     1124     * 
     1125     * Replace a selected single video 
     1126     * 
     1127     * @constructor 
     1128     * @augments wp.media.controller.Library 
     1129     * @augments wp.media.controller.State 
     1130     * @augments Backbone.Model 
     1131     */ 
     1132    media.controller.ReplaceVideo = media.controller.Library.extend({ 
     1133        defaults: _.defaults({ 
     1134            id:         'replace-video', 
     1135            filterable: 'uploaded', 
     1136            multiple:   false, 
     1137            toolbar:    'replace', 
     1138            title:      l10n.replaceVideoTitle, 
     1139            priority:   60, 
     1140            syncSelection: false 
     1141        }, media.controller.Library.prototype.defaults ), 
     1142 
     1143        initialize: function( options ) { 
     1144            var library, comparator; 
     1145 
     1146            this.video = options.video; 
     1147            // If we haven't been provided a `library`, create a `Selection`. 
     1148            if ( ! this.get('library') ) { 
     1149                this.set( 'library', media.query({ type: 'video' }) ); 
     1150            } 
     1151 
     1152            media.controller.Library.prototype.initialize.apply( this, arguments ); 
     1153 
     1154            library    = this.get('library'); 
     1155            comparator = library.comparator; 
     1156 
     1157            // Overload the library's comparator to push items that are not in 
     1158            // the mirrored query to the front of the aggregate collection. 
     1159            library.comparator = function( a, b ) { 
     1160                var aInQuery = !! this.mirroring.get( a.cid ), 
     1161                    bInQuery = !! this.mirroring.get( b.cid ); 
     1162 
     1163                if ( ! aInQuery && bInQuery ) { 
     1164                    return -1; 
     1165                } else if ( aInQuery && ! bInQuery ) { 
     1166                    return 1; 
     1167                } else { 
     1168                    return comparator.apply( this, arguments ); 
     1169                } 
     1170            }; 
     1171 
     1172            // Add all items in the selection to the library, so any featured 
     1173            // images that are not initially loaded still appear. 
     1174            library.observe( this.get('selection') ); 
     1175        }, 
     1176 
     1177        activate: function() { 
     1178            this.updateSelection(); 
     1179            media.controller.Library.prototype.activate.apply( this, arguments ); 
     1180        }, 
     1181 
     1182        updateSelection: function() { 
     1183            var selection = this.get('selection'), 
     1184                attachment = this.video.attachment; 
     1185 
     1186            selection.reset( attachment ? [ attachment ] : [] ); 
     1187        } 
     1188    }); 
     1189 
     1190    /** 
     1191     * wp.media.controller.ReplaceAudio 
     1192     * 
     1193     * Replace a selected single audio file 
     1194     * 
     1195     * @constructor 
     1196     * @augments wp.media.controller.Library 
     1197     * @augments wp.media.controller.State 
     1198     * @augments Backbone.Model 
     1199     */ 
     1200    media.controller.ReplaceAudio = media.controller.Library.extend({ 
     1201        defaults: _.defaults({ 
     1202            id:         'replace-audio', 
     1203            filterable: 'uploaded', 
     1204            multiple:   false, 
     1205            toolbar:    'replace', 
     1206            title:      l10n.replaceAudioTitle, 
     1207            priority:   60, 
     1208            syncSelection: false 
     1209        }, media.controller.Library.prototype.defaults ), 
     1210 
     1211        initialize: function( options ) { 
     1212            var library, comparator; 
     1213 
     1214            this.audio = options.audio; 
     1215            // If we haven't been provided a `library`, create a `Selection`. 
     1216            if ( ! this.get('library') ) { 
     1217                this.set( 'library', media.query({ type: 'audio' }) ); 
     1218            } 
     1219 
     1220            media.controller.Library.prototype.initialize.apply( this, arguments ); 
     1221 
     1222            library    = this.get('library'); 
     1223            comparator = library.comparator; 
     1224 
     1225            // Overload the library's comparator to push items that are not in 
     1226            // the mirrored query to the front of the aggregate collection. 
     1227            library.comparator = function( a, b ) { 
     1228                var aInQuery = !! this.mirroring.get( a.cid ), 
     1229                    bInQuery = !! this.mirroring.get( b.cid ); 
     1230 
     1231                if ( ! aInQuery && bInQuery ) { 
     1232                    return -1; 
     1233                } else if ( aInQuery && ! bInQuery ) { 
     1234                    return 1; 
     1235                } else { 
     1236                    return comparator.apply( this, arguments ); 
     1237                } 
     1238            }; 
     1239 
     1240            // Add all items in the selection to the library, so any featured 
     1241            // images that are not initially loaded still appear. 
     1242            library.observe( this.get('selection') ); 
     1243        }, 
     1244 
     1245        activate: function() { 
     1246            this.updateSelection(); 
     1247            media.controller.Library.prototype.activate.apply( this, arguments ); 
     1248        }, 
     1249 
     1250        updateSelection: function() { 
     1251            var selection = this.get('selection'), 
     1252                attachment = this.audio.attachment; 
    10651253 
    10661254            selection.reset( attachment ? [ attachment ] : [] ); 
     
    24622650    }); 
    24632651 
     2652    media.view.MediaFrame.AudioDetails = media.view.MediaFrame.Select.extend({ 
     2653        defaults: { 
     2654            id:      'audio', 
     2655            url:     '', 
     2656            menu:    'audio-details', 
     2657            content: 'audio-details', 
     2658            toolbar: 'audio-details', 
     2659            type:    'link', 
     2660            title:    l10n.audioDetailsTitle, 
     2661            priority: 120 
     2662        }, 
     2663 
     2664        initialize: function( options ) { 
     2665            this.audio = new media.model.PostAudio( options.metadata ); 
     2666            this.options.selection = new media.model.Selection( this.audio.attachment, { multiple: false } ); 
     2667            media.view.MediaFrame.Select.prototype.initialize.apply( this, arguments ); 
     2668        }, 
     2669 
     2670        bindHandlers: function() { 
     2671            media.view.MediaFrame.Select.prototype.bindHandlers.apply( this, arguments ); 
     2672            this.on( 'menu:create:audio-details', this.createMenu, this ); 
     2673            this.on( 'content:render:audio-details', this.renderAudioDetailsContent, this ); 
     2674            this.on( 'menu:render:audio-details', this.renderMenu, this ); 
     2675            this.on( 'toolbar:render:audio-details', this.renderAudioDetailsToolbar, this ); 
     2676            // override the select toolbar 
     2677            this.on( 'toolbar:render:replace', this.renderReplaceAudioToolbar, this ); 
     2678        }, 
     2679 
     2680        createStates: function() { 
     2681            this.states.add([ 
     2682                new media.controller.AudioDetails({ 
     2683                    audio: this.audio, 
     2684                    editable: false, 
     2685                    menu: 'audio-details' 
     2686                }), 
     2687                new media.controller.ReplaceAudio({ 
     2688                    id: 'replace-audio', 
     2689                    library:   media.query( { type: 'audio' } ), 
     2690                    audio: this.audio, 
     2691                    multiple:  false, 
     2692                    title:     l10n.audioReplaceTitle, 
     2693                    menu: 'audio-details', 
     2694                    toolbar: 'replace', 
     2695                    priority:  80, 
     2696                    displaySettings: true 
     2697                }) 
     2698            ]); 
     2699        }, 
     2700 
     2701        renderAudioDetailsContent: function() { 
     2702            var view = new media.view.AudioDetails({ 
     2703                controller: this, 
     2704                model: this.state().audio, 
     2705                attachment: this.state().audio.attachment 
     2706            }).render(); 
     2707 
     2708            this.content.set( view ); 
     2709        }, 
     2710 
     2711        renderMenu: function( view ) { 
     2712            var lastState = this.lastState(), 
     2713                previous = lastState && lastState.id, 
     2714                frame = this; 
     2715 
     2716            view.set({ 
     2717                cancel: { 
     2718                    text:     l10n.audioDetailsCancel, 
     2719                    priority: 20, 
     2720                    click:    function() { 
     2721                        if ( previous ) { 
     2722                            frame.setState( previous ); 
     2723                        } else { 
     2724                            frame.close(); 
     2725                        } 
     2726                    } 
     2727                }, 
     2728                separateCancel: new media.View({ 
     2729                    className: 'separator', 
     2730                    priority: 40 
     2731                }) 
     2732            }); 
     2733 
     2734        }, 
     2735 
     2736        renderAudioDetailsToolbar: function() { 
     2737            this.toolbar.set( new media.view.Toolbar({ 
     2738                controller: this, 
     2739                items: { 
     2740                    select: { 
     2741                        style:    'primary', 
     2742                        text:     l10n.update, 
     2743                        priority: 80, 
     2744 
     2745                        click: function() { 
     2746                            var controller = this.controller, 
     2747                                state = controller.state(); 
     2748 
     2749                            controller.close(); 
     2750 
     2751                            // not sure if we want to use wp.media.string.image which will create a shortcode or 
     2752                            // perhaps wp.html.string to at least to build the <img /> 
     2753                            state.trigger( 'update', controller.audio.toJSON() ); 
     2754 
     2755                            // Restore and reset the default state. 
     2756                            controller.setState( controller.options.state ); 
     2757                            controller.reset(); 
     2758                        } 
     2759                    } 
     2760                } 
     2761            }) ); 
     2762        }, 
     2763 
     2764        renderReplaceAudioToolbar: function() { 
     2765            this.toolbar.set( new media.view.Toolbar({ 
     2766                controller: this, 
     2767                items: { 
     2768                    replace: { 
     2769                        style:    'primary', 
     2770                        text:     l10n.replace, 
     2771                        priority: 80, 
     2772 
     2773                        click: function() { 
     2774                            var controller = this.controller, 
     2775                                state = controller.state(), 
     2776                                selection = state.get( 'selection' ), 
     2777                                attachment = selection.single(); 
     2778 
     2779                            controller.audio.changeAttachment( attachment, state.display( attachment ) ); 
     2780 
     2781                            // not sure if we want to use wp.media.string.image which will create a shortcode or 
     2782                            // perhaps wp.html.string to at least to build the <img /> 
     2783                            state.trigger( 'replace', controller.audio.toJSON() ); 
     2784 
     2785                            // Restore and reset the default state. 
     2786                            controller.setState( controller.options.state ); 
     2787                            controller.reset(); 
     2788                        } 
     2789                    } 
     2790                } 
     2791            }) ); 
     2792        } 
     2793    }); 
     2794 
     2795    media.view.MediaFrame.VideoDetails = media.view.MediaFrame.Select.extend({ 
     2796        defaults: { 
     2797            id:      'video', 
     2798            url:     '', 
     2799            menu:    'video-details', 
     2800            content: 'video-details', 
     2801            toolbar: 'video-details', 
     2802            type:    'link', 
     2803            title:    l10n.videoDetailsTitle, 
     2804            priority: 120 
     2805        }, 
     2806 
     2807        initialize: function( options ) { 
     2808            this.video = new media.model.PostVideo( options.metadata ); 
     2809            this.options.selection = new media.model.Selection( this.video.attachment, { multiple: false } ); 
     2810            media.view.MediaFrame.Select.prototype.initialize.apply( this, arguments ); 
     2811        }, 
     2812 
     2813        bindHandlers: function() { 
     2814            media.view.MediaFrame.Select.prototype.bindHandlers.apply( this, arguments ); 
     2815            this.on( 'menu:create:video-details', this.createMenu, this ); 
     2816            this.on( 'content:render:video-details', this.renderVideoDetailsContent, this ); 
     2817            this.on( 'menu:render:video-details', this.renderMenu, this ); 
     2818            this.on( 'toolbar:render:video-details', this.renderVideoDetailsToolbar, this ); 
     2819            // override the select toolbar 
     2820            this.on( 'toolbar:render:replace', this.renderReplaceVideoToolbar, this ); 
     2821        }, 
     2822 
     2823        createStates: function() { 
     2824            this.states.add([ 
     2825                new media.controller.VideoDetails({ 
     2826                    video: this.video, 
     2827                    editable: false, 
     2828                    menu: 'video-details' 
     2829                }), 
     2830                new media.controller.ReplaceVideo({ 
     2831                    id: 'replace-video', 
     2832                    library:   media.query( { type: 'video' } ), 
     2833                    video: this.video, 
     2834                    multiple:  false, 
     2835                    title:     l10n.videoReplaceTitle, 
     2836                    menu: 'video-details', 
     2837                    toolbar: 'replace', 
     2838                    priority:  80, 
     2839                    displaySettings: true 
     2840                }) 
     2841            ]); 
     2842        }, 
     2843 
     2844        renderVideoDetailsContent: function() { 
     2845            var view = new media.view.VideoDetails({ 
     2846                controller: this, 
     2847                model: this.state().video, 
     2848                attachment: this.state().video.attachment 
     2849            }).render(); 
     2850 
     2851            this.content.set( view ); 
     2852        }, 
     2853 
     2854        renderMenu: function( view ) { 
     2855            var lastState = this.lastState(), 
     2856                previous = lastState && lastState.id, 
     2857                frame = this; 
     2858 
     2859            view.set({ 
     2860                cancel: { 
     2861                    text:     l10n.videoDetailsCancel, 
     2862                    priority: 20, 
     2863                    click:    function() { 
     2864                        if ( previous ) { 
     2865                            frame.setState( previous ); 
     2866                        } else { 
     2867                            frame.close(); 
     2868                        } 
     2869                    } 
     2870                }, 
     2871                separateCancel: new media.View({ 
     2872                    className: 'separator', 
     2873                    priority: 40 
     2874                }) 
     2875            }); 
     2876 
     2877        }, 
     2878 
     2879        renderVideoDetailsToolbar: function() { 
     2880            this.toolbar.set( new media.view.Toolbar({ 
     2881                controller: this, 
     2882                items: { 
     2883                    select: { 
     2884                        style:    'primary', 
     2885                        text:     l10n.update, 
     2886                        priority: 80, 
     2887 
     2888                        click: function() { 
     2889                            var controller = this.controller, 
     2890                                state = controller.state(); 
     2891 
     2892                            controller.close(); 
     2893 
     2894                            // not sure if we want to use wp.media.string.image which will create a shortcode or 
     2895                            // perhaps wp.html.string to at least to build the <img /> 
     2896                            state.trigger( 'update', controller.video.toJSON() ); 
     2897 
     2898                            // Restore and reset the default state. 
     2899                            controller.setState( controller.options.state ); 
     2900                            controller.reset(); 
     2901                        } 
     2902                    } 
     2903                } 
     2904            }) ); 
     2905        }, 
     2906 
     2907        renderReplaceVideoToolbar: function() { 
     2908            this.toolbar.set( new media.view.Toolbar({ 
     2909                controller: this, 
     2910                items: { 
     2911                    replace: { 
     2912                        style:    'primary', 
     2913                        text:     l10n.replace, 
     2914                        priority: 80, 
     2915 
     2916                        click: function() { 
     2917                            var controller = this.controller, 
     2918                                state = controller.state(), 
     2919                                selection = state.get( 'selection' ), 
     2920                                attachment = selection.single(); 
     2921 
     2922                            controller.video.changeAttachment( attachment, state.display( attachment ) ); 
     2923 
     2924                            state.trigger( 'replace', controller.video.toJSON() ); 
     2925 
     2926                            // Restore and reset the default state. 
     2927                            controller.setState( controller.options.state ); 
     2928                            controller.reset(); 
     2929                        } 
     2930                    } 
     2931                } 
     2932            }) ); 
     2933        } 
     2934    }); 
    24642935 
    24652936    /** 
     
    56066077     */ 
    56076078    media.view.EmbedImage =  media.view.Settings.AttachmentDisplay.extend({ 
    5608         className: 'embed-image-settings', 
     6079        className: 'embed-media-settings', 
    56096080        template:  media.template('embed-image-settings'), 
    56106081 
     
    56676138        } 
    56686139    }); 
    5669 }(jQuery)); 
     6140 
     6141    media.view.AudioDetails = media.view.Settings.AttachmentDisplay.extend({ 
     6142        className: 'audio-details', 
     6143        template:  media.template('audio-details'), 
     6144 
     6145        initialize: function() { 
     6146            _.bindAll(this, 'player', 'close'); 
     6147 
     6148            this.listenTo( this.controller, 'close', this.close ); 
     6149 
     6150            // used in AttachmentDisplay.prototype.updateLinkTo 
     6151            this.options.attachment = this.model.attachment; 
     6152            media.view.Settings.AttachmentDisplay.prototype.initialize.apply( this, arguments ); 
     6153        }, 
     6154 
     6155        prepare: function() { 
     6156            var attachment = false; 
     6157 
     6158            if ( this.model.attachment ) { 
     6159                attachment = this.model.attachment.toJSON(); 
     6160            } 
     6161            return _.defaults({ 
     6162                model: this.model.toJSON(), 
     6163                attachment: attachment 
     6164            }, this.options ); 
     6165        }, 
     6166 
     6167        close : function() { 
     6168            this.mejs.pause(); 
     6169            this.remove(); 
     6170            delete this.mejs; 
     6171            delete this.mejsInstance; 
     6172        }, 
     6173 
     6174        player : function (mejs) { 
     6175            this.mejs = mejs; 
     6176        }, 
     6177 
     6178        render: function() { 
     6179            var self = this, settings = { 
     6180                success : this.player 
     6181            }; 
     6182 
     6183            if ( ! _.isUndefined( window._wpmejsSettings ) ) { 
     6184                settings.pluginPath = _wpmejsSettings.pluginPath; 
     6185            } 
     6186 
     6187            media.view.Settings.AttachmentDisplay.prototype.render.apply( this, arguments ); 
     6188            setTimeout( function() { self.resetFocus(); }, 10 ); 
     6189 
     6190            this.mejsInstance = new MediaElementPlayer( this.$('audio').get(0), settings ); 
     6191 
     6192            return this; 
     6193        }, 
     6194 
     6195        resetFocus: function() { 
     6196            this.$( '.embed-media-settings' ).scrollTop( 0 ); 
     6197        } 
     6198    }); 
     6199 
     6200    media.view.VideoDetails = media.view.Settings.AttachmentDisplay.extend({ 
     6201        className: 'video-details', 
     6202        template:  media.template('video-details'), 
     6203 
     6204        initialize: function() { 
     6205            _.bindAll(this, 'player', 'played'); 
     6206 
     6207            this.removable = false; 
     6208            this.listenTo( this.controller, 'close', this.close ); 
     6209 
     6210            // used in AttachmentDisplay.prototype.updateLinkTo 
     6211            this.options.attachment = this.model.attachment; 
     6212            media.view.Settings.AttachmentDisplay.prototype.initialize.apply( this, arguments ); 
     6213        }, 
     6214 
     6215        prepare: function() { 
     6216            var attachment = false; 
     6217 
     6218            if ( this.model.attachment ) { 
     6219                attachment = this.model.attachment.toJSON(); 
     6220            } 
     6221            return _.defaults({ 
     6222                model: this.model.toJSON(), 
     6223                attachment: attachment 
     6224            }, this.options ); 
     6225        }, 
     6226 
     6227        close : function() { 
     6228            if ( this.removable ) { 
     6229                this.mejs.pause(); 
     6230            } 
     6231            this.remove(); 
     6232            this.mejs = this.mejsInstance = null; 
     6233        }, 
     6234 
     6235        played : function () { 
     6236            this.removable = true; 
     6237        }, 
     6238 
     6239        player : function (mejs) { 
     6240            this.mejs = mejs; 
     6241            this.mejs.addEventListener( 'play', this.played ); 
     6242        }, 
     6243 
     6244        render: function() { 
     6245            var self = this, settings = { 
     6246                success : this.player 
     6247            }; 
     6248 
     6249            if ( ! _.isUndefined( window._wpmejsSettings ) ) { 
     6250                settings.pluginPath = _wpmejsSettings.pluginPath; 
     6251            } 
     6252 
     6253            media.view.Settings.AttachmentDisplay.prototype.render.apply( this, arguments ); 
     6254            setTimeout( function() { self.resetFocus(); }, 10 ); 
     6255 
     6256            if ( ! this.mejsInstance ) { 
     6257                this.mejsInstance = new MediaElementPlayer( this.$('video').get(0), settings ); 
     6258            } 
     6259 
     6260            return this; 
     6261        }, 
     6262 
     6263        resetFocus: function() { 
     6264            this.$( '.embed-media-settings' ).scrollTop( 0 ); 
     6265        } 
     6266    }); 
     6267}(jQuery, _)); 
  • trunk/src/wp-includes/js/mediaelement/wp-mediaelement.css

    r27239 r27411  
    1313.me-cannotplay { 
    1414    width: auto !important; 
     15} 
     16 
     17.audio-details .wp-audio-shortcode { 
     18    display: inline-block; 
     19    max-width: 400px; 
     20} 
     21 
     22.video-details .embed-video-settings, 
     23.audio-details .embed-audio-settings { 
     24    top: 10px; 
     25} 
     26 
     27.video-details .embed-video-settings .checkbox-setting, 
     28.audio-details .embed-audio-settings .checkbox-setting { 
     29    width: 100px; 
     30    clear: none; 
     31} 
     32 
     33.video-details .wp-video-holder { 
     34    width: 100%; 
     35    max-width: 640px; 
    1536} 
    1637 
  • trunk/src/wp-includes/js/tinymce/plugins/wpgallery/plugin.js

    r27408 r27411  
    6565        } 
    6666 
     67        data = window.decodeURIComponent( editor.dom.getAttrib( node, 'data-wp-media' ) ); 
     68 
    6769        // Make sure we've selected a gallery node. 
    6870        if ( editor.dom.hasClass( node, 'wp-gallery' ) && wp.media.gallery ) { 
    6971            gallery = wp.media.gallery; 
    70             data = window.decodeURIComponent( editor.dom.getAttrib( node, 'data-wp-media' ) ); 
    7172            frame = gallery.edit( data ); 
    7273 
     
    7778            }); 
    7879        } else if ( editor.dom.hasClass( node, 'wp-playlist' ) && wp.media.playlist ) { 
    79             data = window.decodeURIComponent( editor.dom.getAttrib( node, 'data-wp-media' ) ); 
    8080            frame = wp.media.playlist.edit( data ); 
    8181 
     
    8686            }); 
    8787        } else if ( editor.dom.hasClass( node, 'wp-video-playlist' ) && wp.media['video-playlist'] ) { 
    88             data = window.decodeURIComponent( editor.dom.getAttrib( node, 'data-wp-media' ) ); 
    8988            frame = wp.media['video-playlist'].edit( data ); 
    9089 
     
    9493                frame.detach(); 
    9594            }); 
     95        } else if ( editor.dom.hasClass( node, 'wp-video' ) ) { 
     96            frame = wp.media.video.edit( data ); 
     97            frame.state( 'video-details' ).on( 'update replace', function ( selection ) { 
     98                var shortcode = wp.media.video.shortcode( selection ); 
     99                editor.dom.setAttrib( node, 'data-wp-media', window.encodeURIComponent( shortcode ) ); 
     100            } ); 
     101            frame.open(); 
     102        } else if ( editor.dom.hasClass( node, 'wp-audio' ) ) { 
     103            frame = wp.media.audio.edit( data ); 
     104            frame.state( 'audio-details' ).on( 'update replace', function ( selection ) { 
     105                var shortcode = wp.media.audio.shortcode( selection ); 
     106                editor.dom.setAttrib( node, 'data-wp-media', window.encodeURIComponent( shortcode ) ); 
     107            } ); 
     108            frame.open(); 
    96109        } else { 
    97110            // temp 
    98             window.console && window.console.log( 'Edit AV shortcode ' + window.decodeURIComponent( editor.dom.getAttrib( node, 'data-wp-media' ) ) ); 
     111            window.console && window.console.log( 'Edit AV shortcode ' + data ); 
    99112        } 
    100113    } 
  • trunk/src/wp-includes/media-template.php

    r27408 r27411  
    556556        <?php // reusing .media-embed to pick up the styles for now ?> 
    557557        <div class="media-embed"> 
    558             <div class="embed-image-settings"> 
     558            <div class="embed-media-settings"> 
    559559                <div class="thumbnail"> 
    560560                    <img src="{{ data.model.url }}" draggable="false" /> 
     
    646646                    </div> 
    647647                <# } #> 
     648            </div> 
     649        </div> 
     650    </script> 
     651 
     652    <script type="text/html" id="tmpl-audio-details"> 
     653        <?php // reusing .media-embed to pick up the styles for now ?> 
     654        <# var rendered = false; #> 
     655        <div class="media-embed"> 
     656            <div class="embed-media-settings embed-audio-settings"> 
     657                <# if ( data.model.src ) { #> 
     658                    <audio class="wp-audio-shortcode" src="{{{ data.model.src }}}" 
     659                        preload="{{{ _.isUndefined( data.model.preload ) ? 'none' : data.model.preload }}}" 
     660                        <# if ( ! _.isUndefined( data.model.autoplay ) && data.model.autoplay ) { #>autoplay<# } #> 
     661                        <# if ( ! _.isUndefined( data.model.loop ) && data.model.loop ) { #>loop<# } #> 
     662                    /> 
     663                    <# rendered = true; #> 
     664                <label class="setting"> 
     665                    <span>SRC</span> 
     666                    <input type="text" disabled="disabled" data-setting="src" value="{{{ data.model.src }}}" /> 
     667                </label> 
     668                <# } #> 
     669                <?php 
     670                $default_types = wp_get_audio_extensions(); 
     671 
     672                foreach ( $default_types as $type ): ?> 
     673                <# if ( data.model.<?php echo $type ?> ) { #> 
     674                    <# if ( ! rendered ) { #> 
     675                    <audio class="wp-audio-shortcode" src="{{{ data.model.<?php echo $type ?> }}}" 
     676                        preload="{{{ _.isUndefined( data.model.preload ) ? 'none' : data.model.preload }}}" 
     677                        <# if ( ! _.isUndefined( data.model.autoplay ) && data.model.autoplay ) { #>autoplay<# } #> 
     678                        <# if ( ! _.isUndefined( data.model.loop ) && data.model.loop ) { #>loop<# } #> 
     679                    /> 
     680                    <# 
     681                        rendered = true; 
     682                    } #> 
     683                <label class="setting"> 
     684                    <span><?php echo strtoupper( $type ) ?></span> 
     685                    <input type="text" disabled="disabled" data-setting="<?php echo $type ?>" value="{{{ data.model.<?php echo $type ?> }}}" /> 
     686                </label> 
     687                <# } #> 
     688                <?php endforeach ?> 
     689 
     690                <div class="setting preload"> 
     691                    <span><?php _e( 'Preload' ); ?></span> 
     692                    <div class="button-group button-large" data-setting="preload"> 
     693                        <button class="button" value="auto"> 
     694                            <?php esc_attr_e( 'Auto' ); ?> 
     695                        </button> 
     696                        <button class="button" value="metadata"> 
     697                            <?php esc_attr_e( 'Metadata' ); ?> 
     698                        </button> 
     699                        <button class="button active" value="none"> 
     700                            <?php esc_attr_e( 'None' ); ?> 
     701                        </button> 
     702                    </div> 
     703                </div> 
     704 
     705                <label class="setting checkbox-setting"> 
     706                    <span><?php _e( 'Autoplay' ); ?></span> 
     707                    <input type="checkbox" data-setting="autoplay" /> 
     708                </label> 
     709 
     710                <label class="setting checkbox-setting"> 
     711                    <span><?php _e( 'Loop' ); ?></span> 
     712                    <input type="checkbox" data-setting="loop" /> 
     713                </label> 
     714                <div class="clear"></div> 
     715            </div> 
     716        </div> 
     717    </script> 
     718 
     719    <script type="text/html" id="tmpl-video-details"> 
     720        <?php // reusing .media-embed to pick up the styles for now ?> 
     721        <# var rendered = false; #> 
     722        <div class="media-embed"> 
     723            <div class="embed-media-settings embed-video-settings"> 
     724                <div class="wp-video-holder"> 
     725                <# 
     726                var w = ! data.model.width || data.model.width > 640 ? 640 : data.model.width, 
     727                    h = ! data.model.height ? 320 : data.model.height; 
     728 
     729                if ( w !== data.model.width ) { 
     730                    h = Math.ceil( ( h * w ) / data.model.width ); 
     731                } 
     732 
     733                if ( data.model.src ) { #> 
     734                    <video class="wp-video-shortcode" 
     735                        width="{{{ w }}}" 
     736                        height="{{{ h }}}" 
     737                        src="{{{ data.model.src }}}" 
     738                        <# if ( ! _.isUndefined( data.model.poster ) ) { #>poster="{{{ data.model.poster }}}"<# } #> 
     739                        preload="{{{ _.isUndefined( data.model.preload ) ? 'metadata' : data.model.preload }}}" 
     740                        <# if ( ! _.isUndefined( data.model.autoplay ) && data.model.autoplay ) { #>autoplay<# } #> 
     741                        <# if ( ! _.isUndefined( data.model.loop ) && data.model.loop ) { #>loop<# } #> 
     742                    /> 
     743                    <# rendered = true; #> 
     744                <label class="setting"> 
     745                    <span>SRC</span> 
     746                    <input type="text" disabled="disabled" data-setting="src" value="{{{ data.model.src }}}" /> 
     747                </label> 
     748                <# } #> 
     749                <?php 
     750                $default_types = wp_get_video_extensions(); 
     751 
     752                foreach ( $default_types as $type ): ?> 
     753                <# if ( data.model.<?php echo $type ?> ) { #> 
     754                    <# if ( ! rendered ) { #> 
     755                    <video class="wp-video-shortcode" 
     756                        width="{{{ w }}}" 
     757                        height="{{{ h }}}" 
     758                        src="{{{ data.model.<?php echo $type ?> }}}" 
     759                        <# if ( ! _.isUndefined( data.model.poster ) ) { #>poster="{{{ data.model.poster }}}"<# } #> 
     760                        preload="{{{ _.isUndefined( data.model.preload ) ? 'metadata' : data.model.preload }}}" 
     761                        <# if ( ! _.isUndefined( data.model.autoplay ) && data.model.autoplay ) { #>autoplay<# } #> 
     762                        <# if ( ! _.isUndefined( data.model.loop ) && data.model.loop ) { #>loop<# } #> 
     763                    /> 
     764                    <# 
     765                        rendered = true; 
     766                    } #> 
     767                <label class="setting"> 
     768                    <span><?php echo strtoupper( $type ) ?></span> 
     769                    <input type="text" disabled="disabled" data-setting="<?php echo $type ?>" value="{{{ data.model.<?php echo $type ?> }}}" /> 
     770                </label> 
     771                <# } #> 
     772                <?php endforeach ?> 
     773                </div> 
     774                <label class="setting"> 
     775                    <span><?php _e( 'Poster Image' ); ?></span> 
     776                    <input type="text" data-setting="poster" value="{{{ data.model.poster }}}" /> 
     777                </label> 
     778                <div class="setting preload"> 
     779                    <span><?php _e( 'Preload' ); ?></span> 
     780                    <div class="button-group button-large" data-setting="preload"> 
     781                        <button class="button" value="auto"> 
     782                            <?php esc_attr_e( 'Auto' ); ?> 
     783                        </button> 
     784                        <button class="button" value="metadata"> 
     785                            <?php esc_attr_e( 'Metadata' ); ?> 
     786                        </button> 
     787                        <button class="button active" value="none"> 
     788                            <?php esc_attr_e( 'None' ); ?> 
     789                        </button> 
     790                    </div> 
     791                </div> 
     792 
     793                <label class="setting checkbox-setting"> 
     794                    <span><?php _e( 'Autoplay' ); ?></span> 
     795                    <input type="checkbox" data-setting="autoplay" /> 
     796                </label> 
     797 
     798                <label class="setting checkbox-setting"> 
     799                    <span><?php _e( 'Loop' ); ?></span> 
     800                    <input type="checkbox" data-setting="loop" /> 
     801                </label> 
     802                <div class="clear"></div> 
    648803            </div> 
    649804        </div> 
  • trunk/src/wp-includes/media.php

    r27404 r27411  
    23822382        'imageDetailsCancel'    => __( 'Cancel Edit' ), 
    23832383 
     2384        // Edit Image 
     2385        'audioDetailsTitle'     => __( 'Audio Details' ), 
     2386        'audioReplaceTitle'     => __( 'Replace Audio' ), 
     2387        'audioDetailsCancel'    => __( 'Cancel Edit' ), 
     2388 
     2389        // Edit Image 
     2390        'videoDetailsTitle'     => __( 'Video Details' ), 
     2391        'videoReplaceTitle'     => __( 'Replace Video' ), 
     2392        'videoDetailsCancel'    => __( 'Cancel Edit' ), 
     2393 
    23842394        // Playlist 
    23852395        'playlistDragInfo'    => __( 'Drag and drop to reorder tracks.' ), 
  • trunk/src/wp-includes/script-loader.php

    r27403 r27411  
    390390    // To enqueue media-views or media-editor, call wp_enqueue_media(). 
    391391    // Both rely on numerous settings, styles, and templates to operate correctly. 
    392     $scripts->add( 'media-views',  "/wp-includes/js/media-views$suffix.js",  array( 'utils', 'media-models', 'wp-plupload', 'jquery-ui-sortable' ), false, 1 ); 
     392    $scripts->add( 'media-views',  "/wp-includes/js/media-views$suffix.js",  array( 'utils', 'media-models', 'wp-plupload', 'jquery-ui-sortable', 'wp-mediaelement' ), false, 1 ); 
    393393    $scripts->add( 'media-editor', "/wp-includes/js/media-editor$suffix.js", array( 'shortcode', 'media-views' ), false, 1 ); 
    394394    $scripts->add( 'mce-view', "/wp-includes/js/mce-view$suffix.js", array( 'shortcode', 'media-models' ), false, 1 ); 
     
    615615    $styles->add( 'wp-auth-check',  "/wp-includes/css/wp-auth-check$suffix.css", array( 'dashicons' ) ); 
    616616    $styles->add( 'editor-buttons', "/wp-includes/css/editor$suffix.css", array( 'dashicons' ) ); 
    617     $styles->add( 'media-views',    "/wp-includes/css/media-views$suffix.css", array( 'buttons', 'dashicons' ) ); 
     617    $styles->add( 'media-views',    "/wp-includes/css/media-views$suffix.css", array( 'buttons', 'dashicons', 'wp-mediaelement' ) ); 
    618618    $styles->add( 'wp-pointer',     "/wp-includes/css/wp-pointer$suffix.css", array( 'dashicons' ) ); 
    619619 
Note: See TracChangeset for help on using the changeset viewer.