mirror of
https://github.com/gosticks/wordpress-develop.git
synced 2026-07-01 07:40:07 +00:00
Widgets: Introduce media widgets for images, audio, and video with extensible base for additional media widgets in the future.
The last time a new widget was introduced, Vuvuzelas were a thing, Angry Birds started taking over phones, and WordPress stopped shipping with Kubrick. Seven years and 17 releases without new widgets have been enough, time to spice up your sidebar! Props westonruter, melchoyce, obenland, timmydcrawford, adamsilverstein, gonom9, wonderboymusic, Fab1en, DrewAPicture, sirbrillig, joen, matias, samikeijonen, afercia, celloexpressions, designsimply, michelleweber, ranh, kjellr, karmatosed. Fixes #32417, #39993, #39994, #39995. git-svn-id: https://develop.svn.wordpress.org/trunk@40640 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
@@ -55,6 +55,110 @@
|
||||
color: #a0a5aa;
|
||||
}
|
||||
|
||||
/* Media Widgets */
|
||||
.wp-core-ui .media-widget-control.selected .placeholder,
|
||||
.wp-core-ui .media-widget-control.selected .not-selected,
|
||||
.wp-core-ui .media-widget-control .selected {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.media-widget-control.selected .selected {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.media-widget-buttons {
|
||||
text-align: left;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.media-widget-control .media-widget-buttons .button {
|
||||
margin-left: 8px;
|
||||
width: auto;
|
||||
}
|
||||
.media-widget-control:not(.selected) .media-widget-buttons .button,
|
||||
.media-widget-buttons .button:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.media-widget-control .placeholder {
|
||||
border: 1px dashed #b4b9be;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
cursor: default;
|
||||
line-height: 20px;
|
||||
padding: 9px 0;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.media-widget-control .media-widget-preview {
|
||||
text-align: center;
|
||||
}
|
||||
.media-widget-control .media-widget-preview .notice {
|
||||
text-align: initial;
|
||||
}
|
||||
.media-frame .media-widget-embed-notice p code,
|
||||
.media-widget-control .notice p code {
|
||||
padding: 0 3px 0 0;
|
||||
}
|
||||
.media-frame .media-widget-embed-notice {
|
||||
margin-top: 16px;
|
||||
}
|
||||
.media-widget-control .media-widget-preview img {
|
||||
max-width: 100%;
|
||||
}
|
||||
.media-widget-control .media-widget-preview .wp-video-shortcode {
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.media-frame.media-widget .media-toolbar-secondary {
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
.media-frame.media-widget .image-details .embed-media-settings .setting.align,
|
||||
.media-frame.media-widget .attachment-display-settings .setting.align,
|
||||
.media-frame.media-widget .embed-media-settings .setting.align,
|
||||
.media-frame.media-widget .embed-link-settings .setting.link-text,
|
||||
.media-frame.media-widget .replace-attachment,
|
||||
.media-frame.media-widget .checkbox-setting.autoplay {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.media-widget-video-preview {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.media-widget-video-link {
|
||||
display: inline-block;
|
||||
min-height: 132px;
|
||||
width: 100%;
|
||||
background: black;
|
||||
}
|
||||
|
||||
.media-widget-video-link .dashicons {
|
||||
font: normal 60px/1 'dashicons';
|
||||
position: relative;
|
||||
width: 100%;
|
||||
top: -90px;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.media-widget-video-link.no-poster .dashicons {
|
||||
top: 30px;
|
||||
}
|
||||
|
||||
.media-frame #embed-url-field.invalid {
|
||||
border: 1px solid #f00;
|
||||
}
|
||||
|
||||
.wp-customizer .mejs-controls a:focus > .mejs-offscreen,
|
||||
.widgets-php .mejs-controls a:focus > .mejs-offscreen {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* Widget Dragging Helpers */
|
||||
.widget.ui-draggable-dragging {
|
||||
min-width: 100%;
|
||||
|
||||
150
src/wp-admin/js/widgets/media-audio-widget.js
Normal file
150
src/wp-admin/js/widgets/media-audio-widget.js
Normal file
@@ -0,0 +1,150 @@
|
||||
/* eslint consistent-this: [ "error", "control" ] */
|
||||
(function( component ) {
|
||||
'use strict';
|
||||
|
||||
var AudioWidgetModel, AudioWidgetControl, AudioDetailsMediaFrame;
|
||||
|
||||
/**
|
||||
* Custom audio details frame that removes the replace-audio state.
|
||||
*
|
||||
* @class AudioDetailsMediaFrame
|
||||
* @constructor
|
||||
*/
|
||||
AudioDetailsMediaFrame = wp.media.view.MediaFrame.AudioDetails.extend({
|
||||
|
||||
/**
|
||||
* Create the default states.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
createStates: function createStates() {
|
||||
this.states.add([
|
||||
new wp.media.controller.AudioDetails( {
|
||||
media: this.media
|
||||
} ),
|
||||
|
||||
new wp.media.controller.MediaLibrary( {
|
||||
type: 'audio',
|
||||
id: 'add-audio-source',
|
||||
title: wp.media.view.l10n.audioAddSourceTitle,
|
||||
toolbar: 'add-audio-source',
|
||||
media: this.media,
|
||||
menu: false
|
||||
} )
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Audio widget model.
|
||||
*
|
||||
* See WP_Widget_Audio::enqueue_admin_scripts() for amending prototype from PHP exports.
|
||||
*
|
||||
* @class AudioWidgetModel
|
||||
* @constructor
|
||||
*/
|
||||
AudioWidgetModel = component.MediaWidgetModel.extend( {} );
|
||||
|
||||
/**
|
||||
* Audio widget control.
|
||||
*
|
||||
* See WP_Widget_Audio::enqueue_admin_scripts() for amending prototype from PHP exports.
|
||||
*
|
||||
* @class AudioWidgetModel
|
||||
* @constructor
|
||||
*/
|
||||
AudioWidgetControl = component.MediaWidgetControl.extend( {
|
||||
|
||||
/**
|
||||
* Show display settings.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
showDisplaySettings: false,
|
||||
|
||||
/**
|
||||
* Map model props to media frame props.
|
||||
*
|
||||
* @param {Object} modelProps - Model props.
|
||||
* @returns {Object} Media frame props.
|
||||
*/
|
||||
mapModelToMediaFrameProps: function mapModelToMediaFrameProps( modelProps ) {
|
||||
var control = this, mediaFrameProps;
|
||||
mediaFrameProps = component.MediaWidgetControl.prototype.mapModelToMediaFrameProps.call( control, modelProps );
|
||||
mediaFrameProps.link = 'embed';
|
||||
return mediaFrameProps;
|
||||
},
|
||||
|
||||
/**
|
||||
* Render preview.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
renderPreview: function renderPreview() {
|
||||
var control = this, previewContainer, previewTemplate, attachmentId, attachmentUrl;
|
||||
attachmentId = control.model.get( 'attachment_id' );
|
||||
attachmentUrl = control.model.get( 'url' );
|
||||
|
||||
if ( ! attachmentId && ! attachmentUrl ) {
|
||||
return;
|
||||
}
|
||||
|
||||
previewContainer = control.$el.find( '.media-widget-preview' );
|
||||
previewTemplate = wp.template( 'wp-media-widget-audio-preview' );
|
||||
|
||||
previewContainer.html( previewTemplate( {
|
||||
model: {
|
||||
attachment_id: control.model.get( 'attachment_id' ),
|
||||
src: attachmentUrl
|
||||
},
|
||||
error: control.model.get( 'error' )
|
||||
} ) );
|
||||
wp.mediaelement.initialize();
|
||||
},
|
||||
|
||||
/**
|
||||
* Open the media audio-edit frame to modify the selected item.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
editMedia: function editMedia() {
|
||||
var control = this, mediaFrame, metadata, updateCallback;
|
||||
|
||||
metadata = control.mapModelToMediaFrameProps( control.model.toJSON() );
|
||||
|
||||
// Set up the media frame.
|
||||
mediaFrame = new AudioDetailsMediaFrame({
|
||||
frame: 'audio',
|
||||
state: 'audio-details',
|
||||
metadata: metadata
|
||||
} );
|
||||
wp.media.frame = mediaFrame;
|
||||
mediaFrame.$el.addClass( 'media-widget' );
|
||||
|
||||
updateCallback = function( mediaFrameProps ) {
|
||||
|
||||
// Update cached attachment object to avoid having to re-fetch. This also triggers re-rendering of preview.
|
||||
control.selectedAttachment.set( mediaFrameProps );
|
||||
|
||||
control.model.set( _.extend(
|
||||
control.model.defaults(),
|
||||
control.mapMediaToModelProps( mediaFrameProps ),
|
||||
{ error: false }
|
||||
) );
|
||||
};
|
||||
|
||||
mediaFrame.state( 'audio-details' ).on( 'update', updateCallback );
|
||||
mediaFrame.state( 'replace-audio' ).on( 'replace', updateCallback );
|
||||
mediaFrame.on( 'close', function() {
|
||||
mediaFrame.detach();
|
||||
});
|
||||
|
||||
mediaFrame.open();
|
||||
}
|
||||
} );
|
||||
|
||||
// Exports.
|
||||
component.controlConstructors.media_audio = AudioWidgetControl;
|
||||
component.modelConstructors.media_audio = AudioWidgetModel;
|
||||
|
||||
})( wp.mediaWidgets );
|
||||
129
src/wp-admin/js/widgets/media-image-widget.js
Normal file
129
src/wp-admin/js/widgets/media-image-widget.js
Normal file
@@ -0,0 +1,129 @@
|
||||
/* eslint consistent-this: [ "error", "control" ] */
|
||||
(function( component, $ ) {
|
||||
'use strict';
|
||||
|
||||
var ImageWidgetModel, ImageWidgetControl;
|
||||
|
||||
/**
|
||||
* Image widget model.
|
||||
*
|
||||
* See WP_Widget_Media_Image::enqueue_admin_scripts() for amending prototype from PHP exports.
|
||||
*
|
||||
* @class ImageWidgetModel
|
||||
* @constructor
|
||||
*/
|
||||
ImageWidgetModel = component.MediaWidgetModel.extend({});
|
||||
|
||||
/**
|
||||
* Image widget control.
|
||||
*
|
||||
* See WP_Widget_Media_Image::enqueue_admin_scripts() for amending prototype from PHP exports.
|
||||
*
|
||||
* @class ImageWidgetModel
|
||||
* @constructor
|
||||
*/
|
||||
ImageWidgetControl = component.MediaWidgetControl.extend({
|
||||
|
||||
/**
|
||||
* Render preview.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
renderPreview: function renderPreview() {
|
||||
var control = this, previewContainer, previewTemplate;
|
||||
if ( ! control.model.get( 'attachment_id' ) && ! control.model.get( 'url' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
previewContainer = control.$el.find( '.media-widget-preview' );
|
||||
previewTemplate = wp.template( 'wp-media-widget-image-preview' );
|
||||
previewContainer.html( previewTemplate( _.extend( control.previewTemplateProps.toJSON() ) ) );
|
||||
},
|
||||
|
||||
/**
|
||||
* Open the media image-edit frame to modify the selected item.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
editMedia: function editMedia() {
|
||||
var control = this, mediaFrame, updateCallback, defaultSync, metadata;
|
||||
|
||||
metadata = control.mapModelToMediaFrameProps( control.model.toJSON() );
|
||||
|
||||
// Needed or else none will not be selected if linkUrl is not also empty.
|
||||
if ( 'none' === metadata.link ) {
|
||||
metadata.linkUrl = '';
|
||||
}
|
||||
|
||||
// Set up the media frame.
|
||||
mediaFrame = wp.media({
|
||||
frame: 'image',
|
||||
state: 'image-details',
|
||||
metadata: metadata
|
||||
});
|
||||
mediaFrame.$el.addClass( 'media-widget' );
|
||||
|
||||
updateCallback = function() {
|
||||
var mediaProps;
|
||||
|
||||
// Update cached attachment object to avoid having to re-fetch. This also triggers re-rendering of preview.
|
||||
mediaProps = mediaFrame.state().attributes.image.toJSON();
|
||||
control.selectedAttachment.set( mediaProps );
|
||||
|
||||
control.model.set( _.extend(
|
||||
control.mapMediaToModelProps( mediaProps ),
|
||||
{ error: false }
|
||||
) );
|
||||
};
|
||||
|
||||
mediaFrame.state( 'image-details' ).on( 'update', updateCallback );
|
||||
mediaFrame.state( 'replace-image' ).on( 'replace', updateCallback );
|
||||
|
||||
// Disable syncing of attachment changes back to server. See <https://core.trac.wordpress.org/ticket/40403>.
|
||||
defaultSync = wp.media.model.Attachment.prototype.sync;
|
||||
wp.media.model.Attachment.prototype.sync = function rejectedSync() {
|
||||
return $.Deferred().rejectWith( this ).promise();
|
||||
};
|
||||
mediaFrame.on( 'close', function onClose() {
|
||||
mediaFrame.detach();
|
||||
wp.media.model.Attachment.prototype.sync = defaultSync;
|
||||
});
|
||||
|
||||
mediaFrame.open();
|
||||
},
|
||||
|
||||
/**
|
||||
* Get props which are merged on top of the model when an embed is chosen (as opposed to an attachment).
|
||||
*
|
||||
* @returns {Object} Reset/override props.
|
||||
*/
|
||||
getEmbedResetProps: function getEmbedResetProps() {
|
||||
return _.extend(
|
||||
component.MediaWidgetControl.prototype.getEmbedResetProps.call( this ),
|
||||
{
|
||||
size: 'full',
|
||||
width: 0,
|
||||
height: 0
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Map model props to preview template props.
|
||||
*
|
||||
* @returns {Object} Preview template props.
|
||||
*/
|
||||
mapModelToPreviewTemplateProps: function mapModelToPreviewTemplateProps() {
|
||||
var control = this, mediaFrameProps, url;
|
||||
url = control.model.get( 'url' );
|
||||
mediaFrameProps = component.MediaWidgetControl.prototype.mapModelToPreviewTemplateProps.call( control );
|
||||
mediaFrameProps.currentFilename = url ? url.replace( /\?.*$/, '' ).replace( /^.+\//, '' ) : '';
|
||||
return mediaFrameProps;
|
||||
}
|
||||
});
|
||||
|
||||
// Exports.
|
||||
component.controlConstructors.media_image = ImageWidgetControl;
|
||||
component.modelConstructors.media_image = ImageWidgetModel;
|
||||
|
||||
})( wp.mediaWidgets, jQuery );
|
||||
228
src/wp-admin/js/widgets/media-video-widget.js
Normal file
228
src/wp-admin/js/widgets/media-video-widget.js
Normal file
@@ -0,0 +1,228 @@
|
||||
/* eslint consistent-this: [ "error", "control" ] */
|
||||
(function( component ) {
|
||||
'use strict';
|
||||
|
||||
var VideoWidgetModel, VideoWidgetControl, VideoDetailsMediaFrame;
|
||||
|
||||
/**
|
||||
* Custom video details frame that removes the replace-video state.
|
||||
*
|
||||
* @class VideoDetailsMediaFrame
|
||||
* @constructor
|
||||
*/
|
||||
VideoDetailsMediaFrame = wp.media.view.MediaFrame.VideoDetails.extend({
|
||||
|
||||
/**
|
||||
* Create the default states.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
createStates: function createStates() {
|
||||
this.states.add([
|
||||
new wp.media.controller.VideoDetails({
|
||||
media: this.media
|
||||
}),
|
||||
|
||||
new wp.media.controller.MediaLibrary( {
|
||||
type: 'video',
|
||||
id: 'add-video-source',
|
||||
title: wp.media.view.l10n.videoAddSourceTitle,
|
||||
toolbar: 'add-video-source',
|
||||
media: this.media,
|
||||
menu: false
|
||||
} ),
|
||||
|
||||
new wp.media.controller.MediaLibrary( {
|
||||
type: 'text',
|
||||
id: 'add-track',
|
||||
title: wp.media.view.l10n.videoAddTrackTitle,
|
||||
toolbar: 'add-track',
|
||||
media: this.media,
|
||||
menu: 'video-details'
|
||||
} )
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Video widget model.
|
||||
*
|
||||
* See WP_Widget_Video::enqueue_admin_scripts() for amending prototype from PHP exports.
|
||||
*
|
||||
* @class VideoWidgetModel
|
||||
* @constructor
|
||||
*/
|
||||
VideoWidgetModel = component.MediaWidgetModel.extend( {} );
|
||||
|
||||
/**
|
||||
* Video widget control.
|
||||
*
|
||||
* See WP_Widget_Video::enqueue_admin_scripts() for amending prototype from PHP exports.
|
||||
*
|
||||
* @class VideoWidgetControl
|
||||
* @constructor
|
||||
*/
|
||||
VideoWidgetControl = component.MediaWidgetControl.extend( {
|
||||
|
||||
/**
|
||||
* Show display settings.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
showDisplaySettings: false,
|
||||
|
||||
/**
|
||||
* Cache of oembed responses.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
oembedResponses: {},
|
||||
|
||||
/**
|
||||
* Map model props to media frame props.
|
||||
*
|
||||
* @param {Object} modelProps - Model props.
|
||||
* @returns {Object} Media frame props.
|
||||
*/
|
||||
mapModelToMediaFrameProps: function mapModelToMediaFrameProps( modelProps ) {
|
||||
var control = this, mediaFrameProps;
|
||||
mediaFrameProps = component.MediaWidgetControl.prototype.mapModelToMediaFrameProps.call( control, modelProps );
|
||||
mediaFrameProps.link = 'embed';
|
||||
return mediaFrameProps;
|
||||
},
|
||||
|
||||
/**
|
||||
* Fetches embed data for external videos.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
fetchEmbed: function fetchEmbed() {
|
||||
var control = this, url;
|
||||
url = control.model.get( 'url' );
|
||||
|
||||
// If we already have a local cache of the embed response, return.
|
||||
if ( control.oembedResponses[ url ] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If there is an in-flight embed request, abort it.
|
||||
if ( control.fetchEmbedDfd && 'pending' === control.fetchEmbedDfd.state() ) {
|
||||
control.fetchEmbedDfd.abort();
|
||||
}
|
||||
|
||||
control.fetchEmbedDfd = jQuery.ajax({
|
||||
url: 'https://noembed.com/embed',
|
||||
data: {
|
||||
url: control.model.get( 'url' ),
|
||||
maxwidth: control.model.get( 'width' ),
|
||||
maxheight: control.model.get( 'height' )
|
||||
},
|
||||
type: 'GET',
|
||||
crossDomain: true,
|
||||
dataType: 'json'
|
||||
});
|
||||
|
||||
control.fetchEmbedDfd.done( function( response ) {
|
||||
control.oembedResponses[ url ] = response;
|
||||
control.renderPreview();
|
||||
});
|
||||
|
||||
control.fetchEmbedDfd.fail( function() {
|
||||
control.oembedResponses[ url ] = null;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Render preview.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
renderPreview: function renderPreview() {
|
||||
var control = this, previewContainer, previewTemplate, attachmentId, attachmentUrl, poster, isHostedEmbed = false, parsedUrl, mime, error;
|
||||
attachmentId = control.model.get( 'attachment_id' );
|
||||
attachmentUrl = control.model.get( 'url' );
|
||||
error = control.model.get( 'error' );
|
||||
|
||||
if ( ! attachmentId && ! attachmentUrl ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! attachmentId && attachmentUrl ) {
|
||||
parsedUrl = document.createElement( 'a' );
|
||||
parsedUrl.href = attachmentUrl;
|
||||
isHostedEmbed = /vimeo|youtu\.?be/.test( parsedUrl.host );
|
||||
}
|
||||
|
||||
if ( isHostedEmbed ) {
|
||||
control.fetchEmbed();
|
||||
poster = control.oembedResponses[ attachmentUrl ] ? control.oembedResponses[ attachmentUrl ].thumbnail_url : null;
|
||||
}
|
||||
|
||||
// Verify the selected attachment mime is supported.
|
||||
mime = control.selectedAttachment.get( 'mime' );
|
||||
if ( mime && attachmentId ) {
|
||||
if ( ! _.contains( _.values( wp.media.view.settings.embedMimes ), mime ) ) {
|
||||
error = 'unsupported_file_type';
|
||||
}
|
||||
}
|
||||
|
||||
previewContainer = control.$el.find( '.media-widget-preview' );
|
||||
previewTemplate = wp.template( 'wp-media-widget-video-preview' );
|
||||
|
||||
previewContainer.html( previewTemplate( {
|
||||
model: {
|
||||
attachment_id: control.model.get( 'attachment_id' ),
|
||||
src: attachmentUrl,
|
||||
poster: poster
|
||||
},
|
||||
is_hosted_embed: isHostedEmbed,
|
||||
error: error
|
||||
} ) );
|
||||
},
|
||||
|
||||
/**
|
||||
* Open the media image-edit frame to modify the selected item.
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
editMedia: function editMedia() {
|
||||
var control = this, mediaFrame, metadata, updateCallback;
|
||||
|
||||
metadata = control.mapModelToMediaFrameProps( control.model.toJSON() );
|
||||
|
||||
// Set up the media frame.
|
||||
mediaFrame = new VideoDetailsMediaFrame({
|
||||
frame: 'video',
|
||||
state: 'video-details',
|
||||
metadata: metadata
|
||||
});
|
||||
wp.media.frame = mediaFrame;
|
||||
mediaFrame.$el.addClass( 'media-widget' );
|
||||
|
||||
updateCallback = function( mediaFrameProps ) {
|
||||
|
||||
// Update cached attachment object to avoid having to re-fetch. This also triggers re-rendering of preview.
|
||||
control.selectedAttachment.set( mediaFrameProps );
|
||||
|
||||
control.model.set( _.extend(
|
||||
_.omit( control.model.defaults(), 'title' ),
|
||||
control.mapMediaToModelProps( mediaFrameProps ),
|
||||
{ error: false }
|
||||
) );
|
||||
};
|
||||
|
||||
mediaFrame.state( 'video-details' ).on( 'update', updateCallback );
|
||||
mediaFrame.state( 'replace-video' ).on( 'replace', updateCallback );
|
||||
mediaFrame.on( 'close', function() {
|
||||
mediaFrame.detach();
|
||||
});
|
||||
|
||||
mediaFrame.open();
|
||||
}
|
||||
} );
|
||||
|
||||
// Exports.
|
||||
component.controlConstructors.media_video = VideoWidgetControl;
|
||||
component.modelConstructors.media_video = VideoWidgetModel;
|
||||
|
||||
})( wp.mediaWidgets );
|
||||
1133
src/wp-admin/js/widgets/media-widgets.js
Normal file
1133
src/wp-admin/js/widgets/media-widgets.js
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user