85
85
component.MediaEmbedView = wp.media.view.Embed.extend({
92
* @param {object} options - Options.
95
initialize: function( options ) {
96
var view = this, embedController; // eslint-disable-line consistent-this
97
wp.media.view.Embed.prototype.initialize.call( view, options );
98
if ( 'image' !== view.controller.options.mimeType ) {
99
embedController = view.controller.states.get( 'embed' );
100
embedController.off( 'scan', embedController.scanImage, embedController );
88
105
* Refresh embed view.
90
107
* Forked override of {wp.media.view.Embed#refresh()} to suppress irrelevant "link text" field.
166
updateoEmbed: function() {
167
var embedLinkView = this, url; // eslint-disable-line consistent-this
169
url = embedLinkView.model.get( 'url' );
171
// Abort if the URL field was emptied out.
173
embedLinkView.setErrorNotice( '' );
174
embedLinkView.setAddToWidgetButtonDisabled( true );
178
if ( ! url.match( /^(http|https):\/\/.+\// ) ) {
179
embedLinkView.controller.$el.find( '#embed-url-field' ).addClass( 'invalid' );
180
embedLinkView.setAddToWidgetButtonDisabled( true );
183
wp.media.view.EmbedLink.prototype.updateoEmbed.call( embedLinkView );
145
189
* @returns {void}
147
191
fetch: function() {
148
var embedLinkView = this, fetchSuccess, matches, fileExt, urlParser; // eslint-disable-line consistent-this
192
var embedLinkView = this, fetchSuccess, matches, fileExt, urlParser, url, re, youTubeEmbedMatch; // eslint-disable-line consistent-this
193
url = embedLinkView.model.get( 'url' );
150
195
if ( embedLinkView.dfd && 'pending' === embedLinkView.dfd.state() ) {
151
196
embedLinkView.dfd.abort();
154
// Abort if the URL field was emptied out.
155
if ( ! embedLinkView.model.get( 'url' ) ) {
156
embedLinkView.setErrorNotice( '' );
160
199
fetchSuccess = function( response ) {
161
200
embedLinkView.renderoEmbed({
167
$( '#embed-url-field' ).removeClass( 'invalid' );
206
embedLinkView.controller.$el.find( '#embed-url-field' ).removeClass( 'invalid' );
168
207
embedLinkView.setErrorNotice( '' );
169
208
embedLinkView.setAddToWidgetButtonDisabled( false );
172
211
urlParser = document.createElement( 'a' );
173
urlParser.href = embedLinkView.model.get( 'url' );
212
urlParser.href = url;
174
213
matches = urlParser.pathname.toLowerCase().match( /\.(\w+)$/ );
176
215
fileExt = matches[1];
187
// If video, test for Vimeo and YouTube, otherwise, renderFail(). This should be removed once #34115 is resolved.
188
if ( 'video' === this.controller.options.mimeType && ! /vimeo|youtu\.?be/.test( urlParser.host ) ) {
189
embedLinkView.renderFail();
226
// Support YouTube embed links.
227
re = /https?:\/\/www\.youtube\.com\/embed\/([^/]+)/;
228
youTubeEmbedMatch = re.exec( url );
229
if ( youTubeEmbedMatch ) {
230
url = 'https://www.youtube.com/watch?v=' + youTubeEmbedMatch[ 1 ];
231
// silently change url to proper oembed-able version.
232
embedLinkView.model.attributes.url = url;
193
embedLinkView.dfd = $.ajax({
235
embedLinkView.dfd = wp.apiRequest({
194
236
url: wp.media.view.settings.oEmbedProxyUrl,
196
url: embedLinkView.model.get( 'url' ),
197
239
maxwidth: embedLinkView.model.get( 'width' ),
198
240
maxheight: embedLinkView.model.get( 'height' ),
199
_wpnonce: wp.media.view.settings.nonce.wpRestApi,
226
267
renderFail: function renderFail() {
227
268
var embedLinkView = this; // eslint-disable-line consistent-this
228
$( '#embed-url-field' ).addClass( 'invalid' );
269
embedLinkView.controller.$el.find( '#embed-url-field' ).addClass( 'invalid' );
229
270
embedLinkView.setErrorNotice( embedLinkView.controller.options.invalidEmbedTypeError || 'ERROR' );
230
271
embedLinkView.setAddToWidgetButtonDisabled( true );
421
462
'click .notice-missing-attachment a': 'handleMediaLibraryLinkClick',
422
463
'click .select-media': 'selectMedia',
464
'click .placeholder': 'selectMedia',
423
465
'click .edit-media': 'editMedia'
548
// Update link_url attribute.
549
control.$el.on( 'input change', '.link', function updateLinkUrl() {
550
var linkUrl = $.trim( $( this ).val() ), linkType = 'custom';
551
if ( control.selectedAttachment.get( 'linkUrl' ) === linkUrl || control.selectedAttachment.get( 'link' ) === linkUrl ) {
553
} else if ( control.selectedAttachment.get( 'url' ) === linkUrl ) {
561
// Update display settings for the next time the user opens to select from the media library.
562
control.displaySettings.set( {
507
569
* Copy current display settings from the widget model to serve as basis
508
570
* of customized display settings for the current media frame session.
562
624
syncModelToInputs: function syncModelToInputs() {
563
625
var control = this;
564
626
control.syncContainer.find( '.media-widget-instance-property' ).each( function() {
565
var input = $( this ), value;
566
value = control.model.get( input.data( 'property' ) );
627
var input = $( this ), value, propertyName;
628
propertyName = input.data( 'property' );
629
value = control.model.get( propertyName );
567
630
if ( _.isUndefined( value ) ) {
570
value = String( value );
571
if ( input.val() === value ) {
575
input.trigger( 'change' );
634
if ( 'array' === control.model.schema[ propertyName ].type && _.isArray( value ) ) {
635
value = value.join( ',' );
636
} else if ( 'boolean' === control.model.schema[ propertyName ].type ) {
637
value = value ? '1' : ''; // Because in PHP, strval( true ) === '1' && strval( false ) === ''.
639
value = String( value );
642
if ( input.val() !== value ) {
644
input.trigger( 'change' );
699
769
control.model.set( control.getModelPropsFromMediaFrame( mediaFrame ) );
702
// Disable syncing of attachment changes back to server. See <https://core.trac.wordpress.org/ticket/40403>.
772
// Disable syncing of attachment changes back to server (except for deletions). See <https://core.trac.wordpress.org/ticket/40403>.
703
773
defaultSync = wp.media.model.Attachment.prototype.sync;
704
wp.media.model.Attachment.prototype.sync = function rejectedSync() {
705
return $.Deferred().rejectWith( this ).promise();
774
wp.media.model.Attachment.prototype.sync = function( method ) {
775
if ( 'delete' === method ) {
776
return defaultSync.apply( this, arguments );
778
return $.Deferred().rejectWith( this ).promise();
707
781
mediaFrame.on( 'close', function onClose() {
708
782
wp.media.model.Attachment.prototype.sync = defaultSync;
811
885
if ( 'post' === mediaFrameProps.link ) {
812
modelProps.link_url = mediaFrameProps.postUrl;
886
modelProps.link_url = mediaFrameProps.postUrl || mediaFrameProps.linkUrl;
813
887
} else if ( 'file' === mediaFrameProps.link ) {
814
888
modelProps.link_url = mediaFrameProps.url;
971
1045
type = model.schema[ name ].type;
972
if ( 'integer' === type ) {
1046
if ( 'array' === type ) {
1047
castedAttrs[ name ] = value;
1048
if ( ! _.isArray( castedAttrs[ name ] ) ) {
1049
castedAttrs[ name ] = castedAttrs[ name ].split( /,/ ); // Good enough for parsing an ID list.
1051
if ( model.schema[ name ].items && 'integer' === model.schema[ name ].items.type ) {
1052
castedAttrs[ name ] = _.filter(
1053
_.map( castedAttrs[ name ], function( id ) {
1054
return parseInt( id, 10 );
1057
return 'number' === typeof id;
1061
} else if ( 'integer' === type ) {
973
1062
castedAttrs[ name ] = parseInt( value, 10 );
974
1063
} else if ( 'boolean' === type ) {
975
1064
castedAttrs[ name ] = ! ( ! value || '0' === value || 'false' === value );
1017
1106
* @returns {void}
1019
1108
component.handleWidgetAdded = function handleWidgetAdded( event, widgetContainer ) {
1020
var fieldContainer, syncContainer, widgetForm, idBase, ControlConstructor, ModelConstructor, modelAttributes, widgetControl, widgetModel, widgetId, widgetInside, animatedCheckDelay = 50, renderWhenAnimationDone;
1109
var fieldContainer, syncContainer, widgetForm, idBase, ControlConstructor, ModelConstructor, modelAttributes, widgetControl, widgetModel, widgetId, animatedCheckDelay = 50, renderWhenAnimationDone;
1021
1110
widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' ); // Note: '.form' appears in the customizer, whereas 'form' on the widgets admin screen.
1022
1111
idBase = widgetForm.find( '> .id_base' ).val();
1023
1112
widgetId = widgetForm.find( '> .widget-id' ).val();
1038
1127
* Create a container element for the widget control (Backbone.View).
1039
* This is inserted into the DOM immediately before the the .widget-content
1128
* This is inserted into the DOM immediately before the .widget-content
1040
1129
* element because the contents of this element are essentially "managed"
1041
1130
* by PHP, where each widget update cause the entire element to be emptied
1042
1131
* and replaced with the rendered output of WP_Widget::form() which is
1075
1164
* This ensures that the container's dimensions are fixed so that ME.js
1076
1165
* can initialize with the proper dimensions.
1078
widgetInside = widgetContainer.parent();
1079
1167
renderWhenAnimationDone = function() {
1080
if ( widgetInside.is( ':animated' ) ) {
1168
if ( ! widgetContainer.hasClass( 'open' ) ) {
1081
1169
setTimeout( renderWhenAnimationDone, animatedCheckDelay );
1083
1171
widgetControl.render();