This repository has been archived on 2023-08-16. You can view files and clone it, but cannot push or open issues or pull requests.
Omphaloskepsis/plugins/jetpack/modules/videopress/js/videopress-admin.js

503 lines
14 KiB
JavaScript
Raw Permalink Normal View History

2018-03-21 18:19:20 +00:00
/* jshint onevar: false, smarttabs: true, devel: true */
/* global VideoPressAdminSettings, setUserSetting */
/**
* VideoPress Admin
*
* @todo i18n
*/
(function($) {
var media = wp.media;
var VideoPress = VideoPress || {};
VideoPress.caps = VideoPressAdminSettings.caps;
VideoPress.l10n = VideoPressAdminSettings.l10n;
/**
* Create a new controller that simply adds a videopress key
* to the library query
*/
media.controller.VideoPress = media.controller.Library.extend({
defaults: _.defaults({
id: 'videopress',
router: 'videopress',
toolbar: 'videopress-toolbar',
title: 'VideoPress',
priority: 200,
searchable: true,
sortable: false
}, media.controller.Library.prototype.defaults ),
initialize: function() {
if ( ! this.get('library') ) {
this.set( 'library', media.query({ videopress: true }) );
}
media.controller.Library.prototype.initialize.apply( this, arguments );
},
/**
* The original function saves content for the browse router only,
* so we hi-jack it a little bit.
*/
saveContentMode: function() {
if ( 'videopress' !== this.get('router') ) {
return;
}
var mode = this.frame.content.mode(),
view = this.frame.router.get();
if ( view && view.get( mode ) ) {
// Map the Upload a Video back to the regular Upload Files.
if ( 'upload_videopress' === mode ) {
mode = 'upload';
}
setUserSetting( 'libraryContent', mode );
}
}
});
/**
* VideoPress Uploader
*/
media.view.VideoPressUploader = media.View.extend({
tagName: 'div',
className: 'uploader-videopress',
template: media.template('videopress-uploader'),
events: {
'submit .videopress-upload-form': 'submitForm'
},
initialize: function() {
var that = this;
if ( ! window.addEventListener ) {
window.attachEvent( 'onmessage', function() { return that.messageHandler.apply( that, arguments ); } );
} else {
window.addEventListener( 'message', function() { return that.messageHandler.apply( that, arguments ); }, false );
}
return media.View.prototype.initialize.apply( this, arguments );
},
submitForm: function() {
var data = false;
this.clearErrors();
if ( this.$( 'input[name="videopress_file"]').val().length < 1 ) {
this.error( VideoPress.l10n.selectVideoFile );
return false;
}
// Prevent multiple submissions.
this.$( '.videopress-upload-form .button' ).prop( 'disabled', true );
// A non-async request for an upload token.
media.ajax( 'videopress-get-upload-token', { async: false } ).done( function( response ) {
data = response;
data.success = true;
}).fail( function( response ) {
data = response;
data.success = false;
});
if ( ! data.success ) {
// Re-enable form elements.
this.$( '.videopress-upload-form .button' ).prop( 'disabled', false );
// Display an error message and cancel form submission.
this.error( data.message );
return false;
}
this.error( VideoPress.l10n.videoUploading, 'updated' );
// Set the form token.
this.$( 'input[name="videopress_blog_id"]' ).val( data.videopress_blog_id );
this.$( 'input[name="videopress_token"]' ).val( data.videopress_token );
this.$( '.videopress-upload-form' ).attr( 'action', data.videopress_action_url );
return true;
},
error: function( message, type ) {
type = type || 'error';
var div = $( '<div />' ).html( $( '<p />' ).text( message ) ).addClass( type );
this.$( '.videopress-errors' ).html( div );
return this;
},
success: function( message ) {
return this.error( message, 'updated' );
},
clearErrors: function() {
this.$( '.videopress-errors' ).html('');
return this;
},
messageHandler: function( event ) {
if ( ! event.origin.match( /\.wordpress\.com$/ ) ) {
return;
}
if ( event.data.indexOf && event.data.indexOf( 'vpUploadResult::' ) === 0 ) {
var result = JSON.parse( event.data.substr( 16 ) );
if ( ! result || ! result.code ) {
this.error( VideoPress.l10n.unknownError );
this.$( '.videopress-upload-form .button' ).prop( 'disabled', false );
return;
}
if ( 'success' === result.code && result.data ) {
var that = this, controller = this.controller,
state = controller.states.get( 'videopress' );
// Our new video has been added, so we need to reset the library.
// Since the Media API caches all queries, we add a random attribute
// to avoid the cache, then call more() to actually fetch the data.
state.set( 'library', media.query({ videopress:true, vp_random:Math.random() }) );
state.get( 'library' ).more().done(function(){
var model = state.get( 'library' ).get( result.data.attachment_id );
// Clear errors and select the uploaded item.
that.clearErrors();
state.get( 'selection' ).reset([ model ]);
controller.content.mode( 'browse' );
});
} else {
this.error( result.code );
// Re-enable form elements.
this.$( '.videopress-upload-form .button' ).prop( 'disabled', false );
}
}
}
});
/**
* Add a custom sync function that would add a few extra
* options for models which are VideoPress videos.
*/
var attachmentSync = media.model.Attachment.prototype.sync;
media.model.Attachment.prototype.sync = function( method, model, options ) {
if ( model.get( 'vp_isVideoPress' ) ) {
console.log( 'syncing ' + model.get( 'vp_guid' ) );
options.data = _.extend( options.data || {}, {
is_videopress: true,
vp_nonces: model.get( 'vp_nonces' )
} );
}
// Call the original sync routine.
return attachmentSync.apply( this, arguments );
};
/**
* Extend the default Attachment Details view. Check for vp_isVideoPress before
* adding anything to these methods.
*/
var AttachmentDetails = media.view.Attachment.Details;
media.view.Attachment.Details = AttachmentDetails.extend({
initialize: function() {
if ( this.model.get( 'vp_isVideoPress' ) ) {
_.extend( this.events, {
'click a.videopress-preview': 'vpPreview',
'change .vp-radio': 'vpRadioChange',
'change .vp-checkbox': 'vpCheckboxChange'
});
}
return AttachmentDetails.prototype.initialize.apply( this, arguments );
},
render: function() {
var r = AttachmentDetails.prototype.render.apply( this, arguments );
if ( this.model.get( 'vp_isVideoPress' ) ) {
var template = media.template( 'videopress-attachment' );
var options = this.model.toJSON();
options.can = {};
options.can.save = !! options.nonces.update;
this.$el.append( template( options ) );
}
return r;
},
// Handle radio buttons
vpRadioChange: function(e) {
$( e.target ).parents( '.vp-setting' ).find( '.vp-radio-text' ).val( e.target.value ).change();
},
// And checkboxes
vpCheckboxChange: function(e) {
$( e.target ).parents( '.vp-setting' ).find( '.vp-checkbox-text' ).val( Number( e.target.checked ) ).change();
},
vpPreview: function() {
VideoPressModal.render( this );
return this;
}
});
/**
* Don't display the uploader dropzone for the VideoPress router.
*/
var UploaderWindow = media.view.UploaderWindow;
media.view.UploaderWindow = UploaderWindow.extend({
show: function() {
if ( 'videopress' !== this.controller.state().get('id') ) {
UploaderWindow.prototype.show.apply( this, arguments );
}
return this;
}
});
/**
* Don't display the uploader in the attachments browser.
*/
var AttachmentsBrowser = media.view.AttachmentsBrowser;
media.view.AttachmentsBrowser = AttachmentsBrowser.extend({
/**
* Snag the Core 3.9.2 versions as a quick fix to avoid
* the breakage introduced by r29364-core
*/
updateContent: function() {
var view = this;
if( ! this.attachments ) {
this.createAttachments();
}
if ( ! this.collection.length ) {
this.toolbar.get( 'spinner' ).show();
this.collection.more().done(function() {
if ( ! view.collection.length ) {
view.createUploader();
}
view.toolbar.get( 'spinner' ).hide();
});
} else {
view.toolbar.get( 'spinner' ).hide();
}
},
/**
* Empty out to avoid breakage.
*/
toggleUploader: function() {},
createUploader: function() {
if ( 'videopress' !== this.controller.state().get('id') ) {
return AttachmentsBrowser.prototype.createUploader.apply( this, arguments );
}
}
});
/**
* Add VideoPress-specific methods for all frames.
*/
_.extend( media.view.MediaFrame.prototype, { VideoPress: { // this.VideoPress.method()
// When the VideoPress router is activated.
activate: function() {
var view = _.first( this.views.get( '.media-frame-router' ) ),
viewSettings = {};
if ( VideoPress.caps.read_videos ) {
viewSettings.browse = { text: VideoPress.l10n.VideoPressLibraryRouter, priority: 40 };
}
if ( VideoPress.caps.upload_videos ) {
viewSettings.upload_videopress = { text: VideoPress.l10n.uploadVideoRouter, priority: 20 };
}
view.set( viewSettings );
// Intercept and clear all incoming uploads
wp.Uploader.queue.on( 'add', this.VideoPress.disableUpload, this );
// Map the Upload Files view to the Upload a Video one (upload_videopress vs. upload)
if ( 'upload' === this.content.mode() && VideoPress.caps.upload_videos ) {
this.content.mode( 'upload_videopress' );
} else {
this.content.mode( 'browse' );
}
},
// When navigated away from the VideoPress router.
deactivate: function( /*view*/ ) {
wp.Uploader.queue.off( 'add', this.VideoPress.disableUpload );
},
// Disable dragdrop uploads in the VideoPress router.
disableUpload: function( attachment ) {
var uploader = this.uploader.uploader.uploader;
uploader.stop();
uploader.splice();
attachment.destroy();
},
// Runs on videopress:insert event fired by our custom toolbar
insert: function( selection ) {
var guid = selection.models[0].get( 'vp_guid' ).replace( /[^a-zA-Z0-9]+/, '' );
media.editor.insert( '[wpvideo ' + guid + ']' );
return this;
},
// Triggered by the upload_videopress router item.
uploadVideo: function() {
this.content.set( new media.view.VideoPressUploader({
controller: this
}) );
return this;
},
// Create a custom toolbar
createToolbar: function( /*toolbar*/ ) {
// Alow an option to hide the toolbar.
if ( this.options.VideoPress && this.options.VideoPress.hideToolbar ) {
return this;
}
var controller = this;
this.toolbar.set( new media.view.Toolbar({
controller: this,
items: {
insert: {
style: 'primary',
text: VideoPress.l10n.insertVideoButton,
priority: 80,
requires: {
library: true,
selection: true
},
click: function() {
var state = controller.state(),
selection = state.get('selection');
controller.close();
state.trigger( 'videopress:insert', selection ).reset();
}
}
}
}) );
}
}});
var MediaFrame = {};
/**
* Extend the selection media frame
*/
MediaFrame.Select = media.view.MediaFrame.Select;
media.view.MediaFrame.Select = MediaFrame.Select.extend({
bindHandlers: function() {
MediaFrame.Select.prototype.bindHandlers.apply( this, arguments );
this.on( 'router:create:videopress', this.createRouter, this );
this.on( 'router:activate:videopress', this.VideoPress.activate, this );
this.on( 'router:deactivate:videopress', this.VideoPress.deactivate, this );
this.on( 'content:render:upload_videopress', this.VideoPress.uploadVideo, this );
this.on( 'toolbar:create:videopress-toolbar', this.VideoPress.createToolbar, this );
this.on( 'videopress:insert', this.VideoPress.insert, this );
}
});
/**
* Extend the post editor media frame with our own
*/
MediaFrame.Post = media.view.MediaFrame.Post;
media.view.MediaFrame.Post = MediaFrame.Post.extend({
createStates: function() {
MediaFrame.Post.prototype.createStates.apply( this, arguments );
this.states.add([ new media.controller.VideoPress() ]);
}
});
/**
* A VideoPress Modal view that we can use to preview videos.
* Expects a controller object on render.
*/
var VideoPressModalView = Backbone.View.extend({
'className': 'videopress-modal-container',
'template': wp.media.template( 'videopress-media-modal' ),
// Render the VideoPress modal with a video object by guid.
render: function( controller ) {
this.delegateEvents( {
'click .videopress-modal-close': 'closeModal',
'click .videopress-modal-backdrop': 'closeModal'
} );
this.model = controller.model;
this.guid = this.model.get( 'vp_guid' );
if ( ! this.$frame ) {
this.$frame = $( '.media-frame-content' );
}
this.$el.html( this.template( { 'video' : this.model.get( 'vp_embed' ) } ) );
this.$modal = this.$( '.videopress-modal' );
this.$modal.hide();
this.$frame.append( this.$el );
this.$modal.slideDown( 'fast' );
return this;
},
closeModal: function() {
var view = this;
this.$modal.slideUp( 'fast', function() { view.remove(); } );
return this;
}
});
var VideoPressModal = new VideoPressModalView();
// Configuration screen behavior
$(document).on( 'ready', function() {
var $form = $( '#videopress-settings' );
// Not on a configuration screen
if ( ! $form.length ) {
return;
}
var $access = $form.find( 'input[name="videopress-access"]' ),
$upload = $form.find( 'input[name="videopress-upload"]' );
$access.on( 'change', function() {
var access = $access.filter( ':checked' ).val();
$upload.attr( 'disabled', ! access );
if ( ! access ) {
$upload.attr( 'checked', false );
}
});
$access.trigger( 'change' );
});
// Media -> VideoPress menu
$(document).on( 'click', '#videopress-browse', function() {
wp.media({
state: 'videopress',
states: [ new media.controller.VideoPress() ],
VideoPress: { hideToolbar: true }
}).open();
return false;
});
})(jQuery);