~canonical-sysadmins/wordpress/4.7.4

« back to all changes in this revision

Viewing changes to wp-includes/js/media-audiovideo.js

  • Committer: Jacek Nykis
  • Date: 2015-01-05 16:17:05 UTC
  • Revision ID: jacek.nykis@canonical.com-20150105161705-w544l1h5mcg7u4w9
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* global _wpMediaViewsL10n, _wpmejsSettings, MediaElementPlayer */
 
2
 
 
3
(function($, _, Backbone) {
 
4
        var media = wp.media,
 
5
                baseSettings = {},
 
6
                l10n = typeof _wpMediaViewsL10n === 'undefined' ? {} : _wpMediaViewsL10n;
 
7
 
 
8
        if ( ! _.isUndefined( window._wpmejsSettings ) ) {
 
9
                baseSettings = _wpmejsSettings;
 
10
        }
 
11
 
 
12
        /**
 
13
         * @mixin
 
14
         */
 
15
        wp.media.mixin = {
 
16
                mejsSettings: baseSettings,
 
17
 
 
18
                removeAllPlayers: function() {
 
19
                        var p;
 
20
 
 
21
                        if ( window.mejs && window.mejs.players ) {
 
22
                                for ( p in window.mejs.players ) {
 
23
                                        window.mejs.players[p].pause();
 
24
                                        this.removePlayer( window.mejs.players[p] );
 
25
                                }
 
26
                        }
 
27
                },
 
28
 
 
29
                /**
 
30
                 * Override the MediaElement method for removing a player.
 
31
                 *      MediaElement tries to pull the audio/video tag out of
 
32
                 *      its container and re-add it to the DOM.
 
33
                 */
 
34
                removePlayer: function(t) {
 
35
                        var featureIndex, feature;
 
36
 
 
37
                        if ( ! t.options ) {
 
38
                                return;
 
39
                        }
 
40
 
 
41
                        // invoke features cleanup
 
42
                        for ( featureIndex in t.options.features ) {
 
43
                                feature = t.options.features[featureIndex];
 
44
                                if ( t['clean' + feature] ) {
 
45
                                        try {
 
46
                                                t['clean' + feature](t);
 
47
                                        } catch (e) {}
 
48
                                }
 
49
                        }
 
50
 
 
51
                        if ( ! t.isDynamic ) {
 
52
                                t.$node.remove();
 
53
                        }
 
54
 
 
55
                        if ( 'native' !== t.media.pluginType ) {
 
56
                                t.media.remove();
 
57
                        }
 
58
 
 
59
                        delete window.mejs.players[t.id];
 
60
 
 
61
                        t.container.remove();
 
62
                        t.globalUnbind();
 
63
                        delete t.node.player;
 
64
                },
 
65
 
 
66
                /**
 
67
                 * Allows any class that has set 'player' to a MediaElementPlayer
 
68
                 *  instance to remove the player when listening to events.
 
69
                 *
 
70
                 *  Examples: modal closes, shortcode properties are removed, etc.
 
71
                 */
 
72
                unsetPlayers : function() {
 
73
                        if ( this.players && this.players.length ) {
 
74
                                _.each( this.players, function (player) {
 
75
                                        player.pause();
 
76
                                        wp.media.mixin.removePlayer( player );
 
77
                                } );
 
78
                                this.players = [];
 
79
                        }
 
80
                }
 
81
        };
 
82
 
 
83
        /**
 
84
         * Autowire "collection"-type shortcodes
 
85
         */
 
86
        wp.media.playlist = new wp.media.collection({
 
87
                tag: 'playlist',
 
88
                editTitle : l10n.editPlaylistTitle,
 
89
                defaults : {
 
90
                        id: wp.media.view.settings.post.id,
 
91
                        style: 'light',
 
92
                        tracklist: true,
 
93
                        tracknumbers: true,
 
94
                        images: true,
 
95
                        artists: true,
 
96
                        type: 'audio'
 
97
                }
 
98
        });
 
99
 
 
100
        /**
 
101
         * Shortcode modeling for audio
 
102
         *  `edit()` prepares the shortcode for the media modal
 
103
         *  `shortcode()` builds the new shortcode after update
 
104
         *
 
105
         * @namespace
 
106
         */
 
107
        wp.media.audio = {
 
108
                coerce : wp.media.coerce,
 
109
 
 
110
                defaults : {
 
111
                        id : wp.media.view.settings.post.id,
 
112
                        src : '',
 
113
                        loop : false,
 
114
                        autoplay : false,
 
115
                        preload : 'none',
 
116
                        width : 400
 
117
                },
 
118
 
 
119
                edit : function( data ) {
 
120
                        var frame, shortcode = wp.shortcode.next( 'audio', data ).shortcode;
 
121
                        frame = wp.media({
 
122
                                frame: 'audio',
 
123
                                state: 'audio-details',
 
124
                                metadata: _.defaults( shortcode.attrs.named, this.defaults )
 
125
                        });
 
126
 
 
127
                        return frame;
 
128
                },
 
129
 
 
130
                shortcode : function( model ) {
 
131
                        var self = this, content;
 
132
 
 
133
                        _.each( this.defaults, function( value, key ) {
 
134
                                model[ key ] = self.coerce( model, key );
 
135
 
 
136
                                if ( value === model[ key ] ) {
 
137
                                        delete model[ key ];
 
138
                                }
 
139
                        });
 
140
 
 
141
                        content = model.content;
 
142
                        delete model.content;
 
143
 
 
144
                        return new wp.shortcode({
 
145
                                tag: 'audio',
 
146
                                attrs: model,
 
147
                                content: content
 
148
                        });
 
149
                }
 
150
        };
 
151
 
 
152
        /**
 
153
         * Shortcode modeling for video
 
154
         *  `edit()` prepares the shortcode for the media modal
 
155
         *  `shortcode()` builds the new shortcode after update
 
156
         *
 
157
         * @namespace
 
158
         */
 
159
        wp.media.video = {
 
160
                coerce : wp.media.coerce,
 
161
 
 
162
                defaults : {
 
163
                        id : wp.media.view.settings.post.id,
 
164
                        src : '',
 
165
                        poster : '',
 
166
                        loop : false,
 
167
                        autoplay : false,
 
168
                        preload : 'metadata',
 
169
                        content : '',
 
170
                        width : 640,
 
171
                        height : 360
 
172
                },
 
173
 
 
174
                edit : function( data ) {
 
175
                        var frame,
 
176
                                shortcode = wp.shortcode.next( 'video', data ).shortcode,
 
177
                                attrs;
 
178
 
 
179
                        attrs = shortcode.attrs.named;
 
180
                        attrs.content = shortcode.content;
 
181
 
 
182
                        frame = wp.media({
 
183
                                frame: 'video',
 
184
                                state: 'video-details',
 
185
                                metadata: _.defaults( attrs, this.defaults )
 
186
                        });
 
187
 
 
188
                        return frame;
 
189
                },
 
190
 
 
191
                shortcode : function( model ) {
 
192
                        var self = this, content;
 
193
 
 
194
                        _.each( this.defaults, function( value, key ) {
 
195
                                model[ key ] = self.coerce( model, key );
 
196
 
 
197
                                if ( value === model[ key ] ) {
 
198
                                        delete model[ key ];
 
199
                                }
 
200
                        });
 
201
 
 
202
                        content = model.content;
 
203
                        delete model.content;
 
204
 
 
205
                        return new wp.shortcode({
 
206
                                tag: 'video',
 
207
                                attrs: model,
 
208
                                content: content
 
209
                        });
 
210
                }
 
211
        };
 
212
 
 
213
        /**
 
214
         * Shared model class for audio and video. Updates the model after
 
215
         *   "Add Audio|Video Source" and "Replace Audio|Video" states return
 
216
         *
 
217
         * @constructor
 
218
         * @augments Backbone.Model
 
219
         */
 
220
        media.model.PostMedia = Backbone.Model.extend({
 
221
                initialize: function() {
 
222
                        this.attachment = false;
 
223
                },
 
224
 
 
225
                setSource: function( attachment ) {
 
226
                        this.attachment = attachment;
 
227
                        this.extension = attachment.get( 'filename' ).split('.').pop();
 
228
 
 
229
                        if ( this.get( 'src' ) && this.extension === this.get( 'src' ).split('.').pop() ) {
 
230
                                this.unset( 'src' );
 
231
                        }
 
232
 
 
233
                        if ( _.contains( wp.media.view.settings.embedExts, this.extension ) ) {
 
234
                                this.set( this.extension, this.attachment.get( 'url' ) );
 
235
                        } else {
 
236
                                this.unset( this.extension );
 
237
                        }
 
238
                },
 
239
 
 
240
                changeAttachment: function( attachment ) {
 
241
                        var self = this;
 
242
 
 
243
                        this.setSource( attachment );
 
244
 
 
245
                        this.unset( 'src' );
 
246
                        _.each( _.without( wp.media.view.settings.embedExts, this.extension ), function( ext ) {
 
247
                                self.unset( ext );
 
248
                        } );
 
249
                }
 
250
        });
 
251
 
 
252
        /**
 
253
         * The controller for the Audio Details state
 
254
         *
 
255
         * @constructor
 
256
         * @augments wp.media.controller.State
 
257
         * @augments Backbone.Model
 
258
         */
 
259
        media.controller.AudioDetails = media.controller.State.extend({
 
260
                defaults: {
 
261
                        id: 'audio-details',
 
262
                        toolbar: 'audio-details',
 
263
                        title: l10n.audioDetailsTitle,
 
264
                        content: 'audio-details',
 
265
                        menu: 'audio-details',
 
266
                        router: false,
 
267
                        priority: 60
 
268
                },
 
269
 
 
270
                initialize: function( options ) {
 
271
                        this.media = options.media;
 
272
                        media.controller.State.prototype.initialize.apply( this, arguments );
 
273
                }
 
274
        });
 
275
 
 
276
        /**
 
277
         * The controller for the Video Details state
 
278
         *
 
279
         * @constructor
 
280
         * @augments wp.media.controller.State
 
281
         * @augments Backbone.Model
 
282
         */
 
283
        media.controller.VideoDetails = media.controller.State.extend({
 
284
                defaults: {
 
285
                        id: 'video-details',
 
286
                        toolbar: 'video-details',
 
287
                        title: l10n.videoDetailsTitle,
 
288
                        content: 'video-details',
 
289
                        menu: 'video-details',
 
290
                        router: false,
 
291
                        priority: 60
 
292
                },
 
293
 
 
294
                initialize: function( options ) {
 
295
                        this.media = options.media;
 
296
                        media.controller.State.prototype.initialize.apply( this, arguments );
 
297
                }
 
298
        });
 
299
 
 
300
        /**
 
301
         * wp.media.view.MediaFrame.MediaDetails
 
302
         *
 
303
         * @constructor
 
304
         * @augments wp.media.view.MediaFrame.Select
 
305
         * @augments wp.media.view.MediaFrame
 
306
         * @augments wp.media.view.Frame
 
307
         * @augments wp.media.View
 
308
         * @augments wp.Backbone.View
 
309
         * @augments Backbone.View
 
310
         * @mixes wp.media.controller.StateMachine
 
311
         */
 
312
        media.view.MediaFrame.MediaDetails = media.view.MediaFrame.Select.extend({
 
313
                defaults: {
 
314
                        id:      'media',
 
315
                        url:     '',
 
316
                        menu:    'media-details',
 
317
                        content: 'media-details',
 
318
                        toolbar: 'media-details',
 
319
                        type:    'link',
 
320
                        priority: 120
 
321
                },
 
322
 
 
323
                initialize: function( options ) {
 
324
                        this.DetailsView = options.DetailsView;
 
325
                        this.cancelText = options.cancelText;
 
326
                        this.addText = options.addText;
 
327
 
 
328
                        this.media = new media.model.PostMedia( options.metadata );
 
329
                        this.options.selection = new media.model.Selection( this.media.attachment, { multiple: false } );
 
330
                        media.view.MediaFrame.Select.prototype.initialize.apply( this, arguments );
 
331
                },
 
332
 
 
333
                bindHandlers: function() {
 
334
                        var menu = this.defaults.menu;
 
335
 
 
336
                        media.view.MediaFrame.Select.prototype.bindHandlers.apply( this, arguments );
 
337
 
 
338
                        this.on( 'menu:create:' + menu, this.createMenu, this );
 
339
                        this.on( 'content:render:' + menu, this.renderDetailsContent, this );
 
340
                        this.on( 'menu:render:' + menu, this.renderMenu, this );
 
341
                        this.on( 'toolbar:render:' + menu, this.renderDetailsToolbar, this );
 
342
                },
 
343
 
 
344
                renderDetailsContent: function() {
 
345
                        var view = new this.DetailsView({
 
346
                                controller: this,
 
347
                                model: this.state().media,
 
348
                                attachment: this.state().media.attachment
 
349
                        }).render();
 
350
 
 
351
                        this.content.set( view );
 
352
                },
 
353
 
 
354
                renderMenu: function( view ) {
 
355
                        var lastState = this.lastState(),
 
356
                                previous = lastState && lastState.id,
 
357
                                frame = this;
 
358
 
 
359
                        view.set({
 
360
                                cancel: {
 
361
                                        text:     this.cancelText,
 
362
                                        priority: 20,
 
363
                                        click:    function() {
 
364
                                                if ( previous ) {
 
365
                                                        frame.setState( previous );
 
366
                                                } else {
 
367
                                                        frame.close();
 
368
                                                }
 
369
                                        }
 
370
                                },
 
371
                                separateCancel: new media.View({
 
372
                                        className: 'separator',
 
373
                                        priority: 40
 
374
                                })
 
375
                        });
 
376
 
 
377
                },
 
378
 
 
379
                setPrimaryButton: function(text, handler) {
 
380
                        this.toolbar.set( new media.view.Toolbar({
 
381
                                controller: this,
 
382
                                items: {
 
383
                                        button: {
 
384
                                                style:    'primary',
 
385
                                                text:     text,
 
386
                                                priority: 80,
 
387
                                                click:    function() {
 
388
                                                        var controller = this.controller;
 
389
                                                        handler.call( this, controller, controller.state() );
 
390
                                                        // Restore and reset the default state.
 
391
                                                        controller.setState( controller.options.state );
 
392
                                                        controller.reset();
 
393
                                                }
 
394
                                        }
 
395
                                }
 
396
                        }) );
 
397
                },
 
398
 
 
399
                renderDetailsToolbar: function() {
 
400
                        this.setPrimaryButton( l10n.update, function( controller, state ) {
 
401
                                controller.close();
 
402
                                state.trigger( 'update', controller.media.toJSON() );
 
403
                        } );
 
404
                },
 
405
 
 
406
                renderReplaceToolbar: function() {
 
407
                        this.setPrimaryButton( l10n.replace, function( controller, state ) {
 
408
                                var attachment = state.get( 'selection' ).single();
 
409
                                controller.media.changeAttachment( attachment );
 
410
                                state.trigger( 'replace', controller.media.toJSON() );
 
411
                        } );
 
412
                },
 
413
 
 
414
                renderAddSourceToolbar: function() {
 
415
                        this.setPrimaryButton( this.addText, function( controller, state ) {
 
416
                                var attachment = state.get( 'selection' ).single();
 
417
                                controller.media.setSource( attachment );
 
418
                                state.trigger( 'add-source', controller.media.toJSON() );
 
419
                        } );
 
420
                }
 
421
        });
 
422
 
 
423
        /**
 
424
         * wp.media.view.MediaFrame.AudioDetails
 
425
         *
 
426
         * @constructor
 
427
         * @augments wp.media.view.MediaFrame.MediaDetails
 
428
         * @augments wp.media.view.MediaFrame.Select
 
429
         * @augments wp.media.view.MediaFrame
 
430
         * @augments wp.media.view.Frame
 
431
         * @augments wp.media.View
 
432
         * @augments wp.Backbone.View
 
433
         * @augments Backbone.View
 
434
         * @mixes wp.media.controller.StateMachine
 
435
         */
 
436
        media.view.MediaFrame.AudioDetails = media.view.MediaFrame.MediaDetails.extend({
 
437
                defaults: {
 
438
                        id:      'audio',
 
439
                        url:     '',
 
440
                        menu:    'audio-details',
 
441
                        content: 'audio-details',
 
442
                        toolbar: 'audio-details',
 
443
                        type:    'link',
 
444
                        title:    l10n.audioDetailsTitle,
 
445
                        priority: 120
 
446
                },
 
447
 
 
448
                initialize: function( options ) {
 
449
                        options.DetailsView = media.view.AudioDetails;
 
450
                        options.cancelText = l10n.audioDetailsCancel;
 
451
                        options.addText = l10n.audioAddSourceTitle;
 
452
 
 
453
                        media.view.MediaFrame.MediaDetails.prototype.initialize.call( this, options );
 
454
                },
 
455
 
 
456
                bindHandlers: function() {
 
457
                        media.view.MediaFrame.MediaDetails.prototype.bindHandlers.apply( this, arguments );
 
458
 
 
459
                        this.on( 'toolbar:render:replace-audio', this.renderReplaceToolbar, this );
 
460
                        this.on( 'toolbar:render:add-audio-source', this.renderAddSourceToolbar, this );
 
461
                },
 
462
 
 
463
                createStates: function() {
 
464
                        this.states.add([
 
465
                                new media.controller.AudioDetails( {
 
466
                                        media: this.media
 
467
                                } ),
 
468
 
 
469
                                new media.controller.MediaLibrary( {
 
470
                                        type: 'audio',
 
471
                                        id: 'replace-audio',
 
472
                                        title: l10n.audioReplaceTitle,
 
473
                                        toolbar: 'replace-audio',
 
474
                                        media: this.media,
 
475
                                        menu: 'audio-details'
 
476
                                } ),
 
477
 
 
478
                                new media.controller.MediaLibrary( {
 
479
                                        type: 'audio',
 
480
                                        id: 'add-audio-source',
 
481
                                        title: l10n.audioAddSourceTitle,
 
482
                                        toolbar: 'add-audio-source',
 
483
                                        media: this.media,
 
484
                                        menu: false
 
485
                                } )
 
486
                        ]);
 
487
                }
 
488
        });
 
489
 
 
490
        /**
 
491
         * wp.media.view.MediaFrame.VideoDetails
 
492
         *
 
493
         * @constructor
 
494
         * @augments wp.media.view.MediaFrame.MediaDetails
 
495
         * @augments wp.media.view.MediaFrame.Select
 
496
         * @augments wp.media.view.MediaFrame
 
497
         * @augments wp.media.view.Frame
 
498
         * @augments wp.media.View
 
499
         * @augments wp.Backbone.View
 
500
         * @augments Backbone.View
 
501
         * @mixes wp.media.controller.StateMachine
 
502
         */
 
503
        media.view.MediaFrame.VideoDetails = media.view.MediaFrame.MediaDetails.extend({
 
504
                defaults: {
 
505
                        id:      'video',
 
506
                        url:     '',
 
507
                        menu:    'video-details',
 
508
                        content: 'video-details',
 
509
                        toolbar: 'video-details',
 
510
                        type:    'link',
 
511
                        title:    l10n.videoDetailsTitle,
 
512
                        priority: 120
 
513
                },
 
514
 
 
515
                initialize: function( options ) {
 
516
                        options.DetailsView = media.view.VideoDetails;
 
517
                        options.cancelText = l10n.videoDetailsCancel;
 
518
                        options.addText = l10n.videoAddSourceTitle;
 
519
 
 
520
                        media.view.MediaFrame.MediaDetails.prototype.initialize.call( this, options );
 
521
                },
 
522
 
 
523
                bindHandlers: function() {
 
524
                        media.view.MediaFrame.MediaDetails.prototype.bindHandlers.apply( this, arguments );
 
525
 
 
526
                        this.on( 'toolbar:render:replace-video', this.renderReplaceToolbar, this );
 
527
                        this.on( 'toolbar:render:add-video-source', this.renderAddSourceToolbar, this );
 
528
                        this.on( 'toolbar:render:select-poster-image', this.renderSelectPosterImageToolbar, this );
 
529
                        this.on( 'toolbar:render:add-track', this.renderAddTrackToolbar, this );
 
530
                },
 
531
 
 
532
                createStates: function() {
 
533
                        this.states.add([
 
534
                                new media.controller.VideoDetails({
 
535
                                        media: this.media
 
536
                                }),
 
537
 
 
538
                                new media.controller.MediaLibrary( {
 
539
                                        type: 'video',
 
540
                                        id: 'replace-video',
 
541
                                        title: l10n.videoReplaceTitle,
 
542
                                        toolbar: 'replace-video',
 
543
                                        media: this.media,
 
544
                                        menu: 'video-details'
 
545
                                } ),
 
546
 
 
547
                                new media.controller.MediaLibrary( {
 
548
                                        type: 'video',
 
549
                                        id: 'add-video-source',
 
550
                                        title: l10n.videoAddSourceTitle,
 
551
                                        toolbar: 'add-video-source',
 
552
                                        media: this.media,
 
553
                                        menu: false
 
554
                                } ),
 
555
 
 
556
                                new media.controller.MediaLibrary( {
 
557
                                        type: 'image',
 
558
                                        id: 'select-poster-image',
 
559
                                        title: l10n.videoSelectPosterImageTitle,
 
560
                                        toolbar: 'select-poster-image',
 
561
                                        media: this.media,
 
562
                                        menu: 'video-details'
 
563
                                } ),
 
564
 
 
565
                                new media.controller.MediaLibrary( {
 
566
                                        type: 'text',
 
567
                                        id: 'add-track',
 
568
                                        title: l10n.videoAddTrackTitle,
 
569
                                        toolbar: 'add-track',
 
570
                                        media: this.media,
 
571
                                        menu: 'video-details'
 
572
                                } )
 
573
                        ]);
 
574
                },
 
575
 
 
576
                renderSelectPosterImageToolbar: function() {
 
577
                        this.setPrimaryButton( l10n.videoSelectPosterImageTitle, function( controller, state ) {
 
578
                                var urls = [], attachment = state.get( 'selection' ).single();
 
579
 
 
580
                                controller.media.set( 'poster', attachment.get( 'url' ) );
 
581
                                state.trigger( 'set-poster-image', controller.media.toJSON() );
 
582
 
 
583
                                _.each( wp.media.view.settings.embedExts, function (ext) {
 
584
                                        if ( controller.media.get( ext ) ) {
 
585
                                                urls.push( controller.media.get( ext ) );
 
586
                                        }
 
587
                                } );
 
588
 
 
589
                                wp.ajax.send( 'set-attachment-thumbnail', {
 
590
                                        data : {
 
591
                                                urls: urls,
 
592
                                                thumbnail_id: attachment.get( 'id' )
 
593
                                        }
 
594
                                } );
 
595
                        } );
 
596
                },
 
597
 
 
598
                renderAddTrackToolbar: function() {
 
599
                        this.setPrimaryButton( l10n.videoAddTrackTitle, function( controller, state ) {
 
600
                                var attachment = state.get( 'selection' ).single(),
 
601
                                        content = controller.media.get( 'content' );
 
602
 
 
603
                                if ( -1 === content.indexOf( attachment.get( 'url' ) ) ) {
 
604
                                        content += [
 
605
                                                '<track srclang="en" label="English"kind="subtitles" src="',
 
606
                                                attachment.get( 'url' ),
 
607
                                                '" />'
 
608
                                        ].join('');
 
609
 
 
610
                                        controller.media.set( 'content', content );
 
611
                                }
 
612
                                state.trigger( 'add-track', controller.media.toJSON() );
 
613
                        } );
 
614
                }
 
615
        });
 
616
 
 
617
        /**
 
618
         * wp.media.view.MediaDetails
 
619
         *
 
620
         * @constructor
 
621
         * @augments wp.media.view.Settings.AttachmentDisplay
 
622
         * @augments wp.media.view.Settings
 
623
         * @augments wp.media.View
 
624
         * @augments wp.Backbone.View
 
625
         * @augments Backbone.View
 
626
         */
 
627
        media.view.MediaDetails = media.view.Settings.AttachmentDisplay.extend({
 
628
                initialize: function() {
 
629
                        _.bindAll(this, 'success');
 
630
                        this.players = [];
 
631
                        this.listenTo( this.controller, 'close', media.mixin.unsetPlayers );
 
632
                        this.on( 'ready', this.setPlayer );
 
633
                        this.on( 'media:setting:remove', media.mixin.unsetPlayers, this );
 
634
                        this.on( 'media:setting:remove', this.render );
 
635
                        this.on( 'media:setting:remove', this.setPlayer );
 
636
                        this.events = _.extend( this.events, {
 
637
                                'click .remove-setting' : 'removeSetting',
 
638
                                'change .content-track' : 'setTracks',
 
639
                                'click .remove-track' : 'setTracks',
 
640
                                'click .add-media-source' : 'addSource'
 
641
                        } );
 
642
 
 
643
                        media.view.Settings.AttachmentDisplay.prototype.initialize.apply( this, arguments );
 
644
                },
 
645
 
 
646
                prepare: function() {
 
647
                        return _.defaults({
 
648
                                model: this.model.toJSON()
 
649
                        }, this.options );
 
650
                },
 
651
 
 
652
                /**
 
653
                 * Remove a setting's UI when the model unsets it
 
654
                 *
 
655
                 * @fires wp.media.view.MediaDetails#media:setting:remove
 
656
                 *
 
657
                 * @param {Event} e
 
658
                 */
 
659
                removeSetting : function(e) {
 
660
                        var wrap = $( e.currentTarget ).parent(), setting;
 
661
                        setting = wrap.find( 'input' ).data( 'setting' );
 
662
 
 
663
                        if ( setting ) {
 
664
                                this.model.unset( setting );
 
665
                                this.trigger( 'media:setting:remove', this );
 
666
                        }
 
667
 
 
668
                        wrap.remove();
 
669
                },
 
670
 
 
671
                /**
 
672
                 *
 
673
                 * @fires wp.media.view.MediaDetails#media:setting:remove
 
674
                 */
 
675
                setTracks : function() {
 
676
                        var tracks = '';
 
677
 
 
678
                        _.each( this.$('.content-track'), function(track) {
 
679
                                tracks += $( track ).val();
 
680
                        } );
 
681
 
 
682
                        this.model.set( 'content', tracks );
 
683
                        this.trigger( 'media:setting:remove', this );
 
684
                },
 
685
 
 
686
                addSource : function( e ) {
 
687
                        this.controller.lastMime = $( e.currentTarget ).data( 'mime' );
 
688
                        this.controller.setState( 'add-' + this.controller.defaults.id + '-source' );
 
689
                },
 
690
 
 
691
                /**
 
692
                 * @global MediaElementPlayer
 
693
                 */
 
694
                setPlayer : function() {
 
695
                        if ( ! this.players.length && this.media ) {
 
696
                                this.players.push( new MediaElementPlayer( this.media, this.settings ) );
 
697
                        }
 
698
                },
 
699
 
 
700
                /**
 
701
                 * @abstract
 
702
                 */
 
703
                setMedia : function() {
 
704
                        return this;
 
705
                },
 
706
 
 
707
                success : function(mejs) {
 
708
                        var autoplay = mejs.attributes.autoplay && 'false' !== mejs.attributes.autoplay;
 
709
 
 
710
                        if ( 'flash' === mejs.pluginType && autoplay ) {
 
711
                                mejs.addEventListener( 'canplay', function() {
 
712
                                        mejs.play();
 
713
                                }, false );
 
714
                        }
 
715
 
 
716
                        this.mejs = mejs;
 
717
                },
 
718
 
 
719
                /**
 
720
                 * @returns {media.view.MediaDetails} Returns itself to allow chaining
 
721
                 */
 
722
                render: function() {
 
723
                        var self = this;
 
724
 
 
725
                        media.view.Settings.AttachmentDisplay.prototype.render.apply( this, arguments );
 
726
                        setTimeout( function() { self.resetFocus(); }, 10 );
 
727
 
 
728
                        this.settings = _.defaults( {
 
729
                                success : this.success
 
730
                        }, baseSettings );
 
731
 
 
732
                        return this.setMedia();
 
733
                },
 
734
 
 
735
                resetFocus: function() {
 
736
                        this.$( '.embed-media-settings' ).scrollTop( 0 );
 
737
                }
 
738
        }, {
 
739
                instances : 0,
 
740
 
 
741
                /**
 
742
                 * When multiple players in the DOM contain the same src, things get weird.
 
743
                 *
 
744
                 * @param {HTMLElement} elem
 
745
                 * @returns {HTMLElement}
 
746
                 */
 
747
                prepareSrc : function( elem ) {
 
748
                        var i = media.view.MediaDetails.instances++;
 
749
                        _.each( $( elem ).find( 'source' ), function( source ) {
 
750
                                source.src = [
 
751
                                        source.src,
 
752
                                        source.src.indexOf('?') > -1 ? '&' : '?',
 
753
                                        '_=',
 
754
                                        i
 
755
                                ].join('');
 
756
                        } );
 
757
 
 
758
                        return elem;
 
759
                }
 
760
        });
 
761
 
 
762
        /**
 
763
         * wp.media.view.AudioDetails
 
764
         *
 
765
         * @constructor
 
766
         * @augments wp.media.view.MediaDetails
 
767
         * @augments wp.media.view.Settings.AttachmentDisplay
 
768
         * @augments wp.media.view.Settings
 
769
         * @augments wp.media.View
 
770
         * @augments wp.Backbone.View
 
771
         * @augments Backbone.View
 
772
         */
 
773
        media.view.AudioDetails = media.view.MediaDetails.extend({
 
774
                className: 'audio-details',
 
775
                template:  media.template('audio-details'),
 
776
 
 
777
                setMedia: function() {
 
778
                        var audio = this.$('.wp-audio-shortcode');
 
779
 
 
780
                        if ( audio.find( 'source' ).length ) {
 
781
                                if ( audio.is(':hidden') ) {
 
782
                                        audio.show();
 
783
                                }
 
784
                                this.media = media.view.MediaDetails.prepareSrc( audio.get(0) );
 
785
                        } else {
 
786
                                audio.hide();
 
787
                                this.media = false;
 
788
                        }
 
789
 
 
790
                        return this;
 
791
                }
 
792
        });
 
793
 
 
794
        /**
 
795
         * wp.media.view.VideoDetails
 
796
         *
 
797
         * @constructor
 
798
         * @augments wp.media.view.MediaDetails
 
799
         * @augments wp.media.view.Settings.AttachmentDisplay
 
800
         * @augments wp.media.view.Settings
 
801
         * @augments wp.media.View
 
802
         * @augments wp.Backbone.View
 
803
         * @augments Backbone.View
 
804
         */
 
805
        media.view.VideoDetails = media.view.MediaDetails.extend({
 
806
                className: 'video-details',
 
807
                template:  media.template('video-details'),
 
808
 
 
809
                setMedia: function() {
 
810
                        var video = this.$('.wp-video-shortcode');
 
811
 
 
812
                        if ( video.find( 'source' ).length ) {
 
813
                                if ( video.is(':hidden') ) {
 
814
                                        video.show();
 
815
                                }
 
816
 
 
817
                                if ( ! video.hasClass('youtube-video') ) {
 
818
                                        this.media = media.view.MediaDetails.prepareSrc( video.get(0) );
 
819
                                } else {
 
820
                                        this.media = video.get(0);
 
821
                                }
 
822
                        } else {
 
823
                                video.hide();
 
824
                                this.media = false;
 
825
                        }
 
826
 
 
827
                        return this;
 
828
                }
 
829
        });
 
830
 
 
831
}(jQuery, _, Backbone));