PK �8FZ�JIr( r( media-gallery-widget.jsnu �[��� /**
* @output wp-admin/js/widgets/media-gallery-widget.js
*/
/* eslint consistent-this: [ "error", "control" ] */
(function( component ) {
'use strict';
var GalleryWidgetModel, GalleryWidgetControl, GalleryDetailsMediaFrame;
/**
* Custom gallery details frame.
*
* @since 4.9.0
* @class wp.mediaWidgets~GalleryDetailsMediaFrame
* @augments wp.media.view.MediaFrame.Post
*/
GalleryDetailsMediaFrame = wp.media.view.MediaFrame.Post.extend(/** @lends wp.mediaWidgets~GalleryDetailsMediaFrame.prototype */{
/**
* Create the default states.
*
* @since 4.9.0
* @return {void}
*/
createStates: function createStates() {
this.states.add([
new wp.media.controller.Library({
id: 'gallery',
title: wp.media.view.l10n.createGalleryTitle,
priority: 40,
toolbar: 'main-gallery',
filterable: 'uploaded',
multiple: 'add',
editable: true,
library: wp.media.query( _.defaults({
type: 'image'
}, this.options.library ) )
}),
// Gallery states.
new wp.media.controller.GalleryEdit({
library: this.options.selection,
editing: this.options.editing,
menu: 'gallery'
}),
new wp.media.controller.GalleryAdd()
]);
}
} );
/**
* Gallery widget model.
*
* See WP_Widget_Gallery::enqueue_admin_scripts() for amending prototype from PHP exports.
*
* @since 4.9.0
*
* @class wp.mediaWidgets.modelConstructors.media_gallery
* @augments wp.mediaWidgets.MediaWidgetModel
*/
GalleryWidgetModel = component.MediaWidgetModel.extend(/** @lends wp.mediaWidgets.modelConstructors.media_gallery.prototype */{} );
GalleryWidgetControl = component.MediaWidgetControl.extend(/** @lends wp.mediaWidgets.controlConstructors.media_gallery.prototype */{
/**
* View events.
*
* @since 4.9.0
* @type {object}
*/
events: _.extend( {}, component.MediaWidgetControl.prototype.events, {
'click .media-widget-gallery-preview': 'editMedia'
} ),
/**
* Gallery widget control.
*
* See WP_Widget_Gallery::enqueue_admin_scripts() for amending prototype from PHP exports.
*
* @constructs wp.mediaWidgets.controlConstructors.media_gallery
* @augments wp.mediaWidgets.MediaWidgetControl
*
* @since 4.9.0
* @param {Object} options - Options.
* @param {Backbone.Model} options.model - Model.
* @param {jQuery} options.el - Control field container element.
* @param {jQuery} options.syncContainer - Container element where fields are synced for the server.
* @return {void}
*/
initialize: function initialize( options ) {
var control = this;
component.MediaWidgetControl.prototype.initialize.call( control, options );
_.bindAll( control, 'updateSelectedAttachments', 'handleAttachmentDestroy' );
control.selectedAttachments = new wp.media.model.Attachments();
control.model.on( 'change:ids', control.updateSelectedAttachments );
control.selectedAttachments.on( 'change', control.renderPreview );
control.selectedAttachments.on( 'reset', control.renderPreview );
control.updateSelectedAttachments();
/*
* Refresh a Gallery widget partial when the user modifies one of the selected attachments.
* This ensures that when an attachment's caption is updated in the media modal the Gallery
* widget in the preview will then be refreshed to show the change. Normally doing this
* would not be necessary because all of the state should be contained inside the changeset,
* as everything done in the Customizer should not make a change to the site unless the
* changeset itself is published. Attachments are a current exception to this rule.
* For a proposal to include attachments in the customized state, see #37887.
*/
if ( wp.customize && wp.customize.previewer ) {
control.selectedAttachments.on( 'change', function() {
wp.customize.previewer.send( 'refresh-widget-partial', control.model.get( 'widget_id' ) );
} );
}
},
/**
* Update the selected attachments if necessary.
*
* @since 4.9.0
* @return {void}
*/
updateSelectedAttachments: function updateSelectedAttachments() {
var control = this, newIds, oldIds, removedIds, addedIds, addedQuery;
newIds = control.model.get( 'ids' );
oldIds = _.pluck( control.selectedAttachments.models, 'id' );
removedIds = _.difference( oldIds, newIds );
_.each( removedIds, function( removedId ) {
control.selectedAttachments.remove( control.selectedAttachments.get( removedId ) );
});
addedIds = _.difference( newIds, oldIds );
if ( addedIds.length ) {
addedQuery = wp.media.query({
order: 'ASC',
orderby: 'post__in',
perPage: -1,
post__in: newIds,
query: true,
type: 'image'
});
addedQuery.more().done( function() {
control.selectedAttachments.reset( addedQuery.models );
});
}
},
/**
* Render preview.
*
* @since 4.9.0
* @return {void}
*/
renderPreview: function renderPreview() {
var control = this, previewContainer, previewTemplate, data;
previewContainer = control.$el.find( '.media-widget-preview' );
previewTemplate = wp.template( 'wp-media-widget-gallery-preview' );
data = control.previewTemplateProps.toJSON();
data.attachments = {};
control.selectedAttachments.each( function( attachment ) {
data.attachments[ attachment.id ] = attachment.toJSON();
} );
previewContainer.html( previewTemplate( data ) );
},
/**
* Determine whether there are selected attachments.
*
* @since 4.9.0
* @return {boolean} Selected.
*/
isSelected: function isSelected() {
var control = this;
if ( control.model.get( 'error' ) ) {
return false;
}
return control.model.get( 'ids' ).length > 0;
},
/**
* Open the media select frame to edit images.
*
* @since 4.9.0
* @return {void}
*/
editMedia: function editMedia() {
var control = this, selection, mediaFrame, mediaFrameProps;
selection = new wp.media.model.Selection( control.selectedAttachments.models, {
multiple: true
});
mediaFrameProps = control.mapModelToMediaFrameProps( control.model.toJSON() );
selection.gallery = new Backbone.Model( mediaFrameProps );
if ( mediaFrameProps.size ) {
control.displaySettings.set( 'size', mediaFrameProps.size );
}
mediaFrame = new GalleryDetailsMediaFrame({
frame: 'manage',
text: control.l10n.add_to_widget,
selection: selection,
mimeType: control.mime_type,
selectedDisplaySettings: control.displaySettings,
showDisplaySettings: control.showDisplaySettings,
metadata: mediaFrameProps,
editing: true,
multiple: true,
state: 'gallery-edit'
});
wp.media.frame = mediaFrame; // See wp.media().
// Handle selection of a media item.
mediaFrame.on( 'update', function onUpdate( newSelection ) {
var state = mediaFrame.state(), resultSelection;
resultSelection = newSelection || state.get( 'selection' );
if ( ! resultSelection ) {
return;
}
// Copy orderby_random from gallery state.
if ( resultSelection.gallery ) {
control.model.set( control.mapMediaToModelProps( resultSelection.gallery.toJSON() ) );
}
// Directly update selectedAttachments to prevent needing to do additional request.
control.selectedAttachments.reset( resultSelection.models );
// Update models in the widget instance.
control.model.set( {
ids: _.pluck( resultSelection.models, 'id' )
} );
} );
mediaFrame.$el.addClass( 'media-widget' );
mediaFrame.open();
if ( selection ) {
selection.on( 'destroy', control.handleAttachmentDestroy );
}
},
/**
* Open the media select frame to chose an item.
*
* @since 4.9.0
* @return {void}
*/
selectMedia: function selectMedia() {
var control = this, selection, mediaFrame, mediaFrameProps;
selection = new wp.media.model.Selection( control.selectedAttachments.models, {
multiple: true
});
mediaFrameProps = control.mapModelToMediaFrameProps( control.model.toJSON() );
if ( mediaFrameProps.size ) {
control.displaySettings.set( 'size', mediaFrameProps.size );
}
mediaFrame = new GalleryDetailsMediaFrame({
frame: 'select',
text: control.l10n.add_to_widget,
selection: selection,
mimeType: control.mime_type,
selectedDisplaySettings: control.displaySettings,
showDisplaySettings: control.showDisplaySettings,
metadata: mediaFrameProps,
state: 'gallery'
});
wp.media.frame = mediaFrame; // See wp.media().
// Handle selection of a media item.
mediaFrame.on( 'update', function onUpdate( newSelection ) {
var state = mediaFrame.state(), resultSelection;
resultSelection = newSelection || state.get( 'selection' );
if ( ! resultSelection ) {
return;
}
// Copy orderby_random from gallery state.
if ( resultSelection.gallery ) {
control.model.set( control.mapMediaToModelProps( resultSelection.gallery.toJSON() ) );
}
// Directly update selectedAttachments to prevent needing to do additional request.
control.selectedAttachments.reset( resultSelection.models );
// Update widget instance.
control.model.set( {
ids: _.pluck( resultSelection.models, 'id' )
} );
} );
mediaFrame.$el.addClass( 'media-widget' );
mediaFrame.open();
if ( selection ) {
selection.on( 'destroy', control.handleAttachmentDestroy );
}
/*
* Make sure focus is set inside of modal so that hitting Esc will close
* the modal and not inadvertently cause the widget to collapse in the customizer.
*/
mediaFrame.$el.find( ':focusable:first' ).focus();
},
/**
* Clear the selected attachment when it is deleted in the media select frame.
*
* @since 4.9.0
* @param {wp.media.models.Attachment} attachment - Attachment.
* @return {void}
*/
handleAttachmentDestroy: function handleAttachmentDestroy( attachment ) {
var control = this;
control.model.set( {
ids: _.difference(
control.model.get( 'ids' ),
[ attachment.id ]
)
} );
}
} );
// Exports.
component.controlConstructors.media_gallery = GalleryWidgetControl;
component.modelConstructors.media_gallery = GalleryWidgetModel;
})( wp.mediaWidgets );
PK �8FZ�r�
�
media-video-widget.min.jsnu �[��� /*! This file is auto-generated */
!function(t){"use strict";var i=wp.media.view.MediaFrame.VideoDetails.extend({createStates:function(){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:!1}),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"})])}}),e=t.MediaWidgetModel.extend({}),d=t.MediaWidgetControl.extend({showDisplaySettings:!1,oembedResponses:{},mapModelToMediaFrameProps:function(e){e=t.MediaWidgetControl.prototype.mapModelToMediaFrameProps.call(this,e);return e.link="embed",e},fetchEmbed:function(){var t=this,d=t.model.get("url");t.oembedResponses[d]||(t.fetchEmbedDfd&&"pending"===t.fetchEmbedDfd.state()&&t.fetchEmbedDfd.abort(),t.fetchEmbedDfd=wp.apiRequest({url:wp.media.view.settings.oEmbedProxyUrl,data:{url:t.model.get("url"),maxwidth:t.model.get("width"),maxheight:t.model.get("height"),discover:!1},type:"GET",dataType:"json",context:t}),t.fetchEmbedDfd.done(function(e){t.oembedResponses[d]=e,t.renderPreview()}),t.fetchEmbedDfd.fail(function(){t.oembedResponses[d]=null}))},isHostedVideo:function(){return!0},renderPreview:function(){var e,t,d=this,i="",o=!1,a=d.model.get("attachment_id"),s=d.model.get("url"),m=d.model.get("error");(a||s)&&((t=d.selectedAttachment.get("mime"))&&a?_.contains(_.values(wp.media.view.settings.embedMimes),t)||(m="unsupported_file_type"):a||((t=document.createElement("a")).href=s,(t=t.pathname.toLowerCase().match(/\.(\w+)$/))?_.contains(_.keys(wp.media.view.settings.embedMimes),t[1])||(m="unsupported_file_type"):o=!0),o&&(d.fetchEmbed(),d.oembedResponses[s])&&(e=d.oembedResponses[s].thumbnail_url,i=d.oembedResponses[s].html.replace(/\swidth="\d+"/,' width="100%"').replace(/\sheight="\d+"/,"")),t=d.$el.find(".media-widget-preview"),d=wp.template("wp-media-widget-video-preview"),t.html(d({model:{attachment_id:a,html:i,src:s,poster:e},is_oembed:o,error:m})),wp.mediaelement.initialize())},editMedia:function(){var t=this,e=t.mapModelToMediaFrameProps(t.model.toJSON()),d=new i({frame:"video",state:"video-details",metadata:e});(wp.media.frame=d).$el.addClass("media-widget"),e=function(e){t.selectedAttachment.set(e),t.model.set(_.extend(_.omit(t.model.defaults(),"title"),t.mapMediaToModelProps(e),{error:!1}))},d.state("video-details").on("update",e),d.state("replace-video").on("replace",e),d.on("close",function(){d.detach()}),d.open()}});t.controlConstructors.media_video=d,t.modelConstructors.media_video=e}(wp.mediaWidgets);PK �8FZ�!�� � media-audio-widget.min.jsnu �[��� /*! This file is auto-generated */
!function(t){"use strict";var a=wp.media.view.MediaFrame.AudioDetails.extend({createStates:function(){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:!1})])}}),e=t.MediaWidgetModel.extend({}),d=t.MediaWidgetControl.extend({showDisplaySettings:!1,mapModelToMediaFrameProps:function(e){e=t.MediaWidgetControl.prototype.mapModelToMediaFrameProps.call(this,e);return e.link="embed",e},renderPreview:function(){var e,t=this,d=t.model.get("attachment_id"),a=t.model.get("url");(d||a)&&(d=t.$el.find(".media-widget-preview"),e=wp.template("wp-media-widget-audio-preview"),d.html(e({model:{attachment_id:t.model.get("attachment_id"),src:a},error:t.model.get("error")})),wp.mediaelement.initialize())},editMedia:function(){var t=this,e=t.mapModelToMediaFrameProps(t.model.toJSON()),d=new a({frame:"audio",state:"audio-details",metadata:e});(wp.media.frame=d).$el.addClass("media-widget"),e=function(e){t.selectedAttachment.set(e),t.model.set(_.extend(t.model.defaults(),t.mapMediaToModelProps(e),{error:!1}))},d.state("audio-details").on("update",e),d.state("replace-audio").on("replace",e),d.on("close",function(){d.detach()}),d.open()}});t.controlConstructors.media_audio=d,t.modelConstructors.media_audio=e}(wp.mediaWidgets);PK �8FZ�i��� � custom-html-widgets.min.jsnu �[��� /*! This file is auto-generated */
wp.customHtmlWidgets=function(a){"use strict";var s={idBases:["custom_html"],codeEditorSettings:{},l10n:{errorNotice:{singular:"",plural:""}}};return s.CustomHtmlWidgetControl=Backbone.View.extend({events:{},initialize:function(e){var n=this;if(!e.el)throw new Error("Missing options.el");if(!e.syncContainer)throw new Error("Missing options.syncContainer");Backbone.View.prototype.initialize.call(n,e),n.syncContainer=e.syncContainer,n.widgetIdBase=n.syncContainer.parent().find(".id_base").val(),n.widgetNumber=n.syncContainer.parent().find(".widget_number").val(),n.customizeSettingId="widget_"+n.widgetIdBase+"["+String(n.widgetNumber)+"]",n.$el.addClass("custom-html-widget-fields"),n.$el.html(wp.template("widget-custom-html-control-fields")({codeEditorDisabled:s.codeEditorSettings.disabled})),n.errorNoticeContainer=n.$el.find(".code-editor-error-container"),n.currentErrorAnnotations=[],n.saveButton=n.syncContainer.add(n.syncContainer.parent().find(".widget-control-actions")).find(".widget-control-save, #savewidget"),n.saveButton.addClass("custom-html-widget-save-button"),n.fields={title:n.$el.find(".title"),content:n.$el.find(".content")},_.each(n.fields,function(t,i){t.on("input change",function(){var e=n.syncContainer.find(".sync-input."+i);e.val()!==t.val()&&(e.val(t.val()),e.trigger("change"))}),t.val(n.syncContainer.find(".sync-input."+i).val())})},updateFields:function(){var e,t=this;t.fields.title.is(document.activeElement)||(e=t.syncContainer.find(".sync-input.title"),t.fields.title.val(e.val())),t.contentUpdateBypassed=t.fields.content.is(document.activeElement)||t.editor&&t.editor.codemirror.state.focused||0!==t.currentErrorAnnotations.length,t.contentUpdateBypassed||(e=t.syncContainer.find(".sync-input.content"),t.fields.content.val(e.val()))},updateErrorNotice:function(e){var t,i=this,n="";1===e.length?n=s.l10n.errorNotice.singular.replace("%d","1"):1<e.length&&(n=s.l10n.errorNotice.plural.replace("%d",String(e.length))),i.fields.content[0].setCustomValidity&&i.fields.content[0].setCustomValidity(n),wp.customize&&wp.customize.has(i.customizeSettingId)?((t=wp.customize(i.customizeSettingId)).notifications.remove("htmlhint_error"),0!==e.length&&t.notifications.add("htmlhint_error",new wp.customize.Notification("htmlhint_error",{message:n,type:"error"}))):0!==e.length?((t=a('<div class="inline notice notice-error notice-alt" role="alert"></div>')).append(a("<p></p>",{text:n})),i.errorNoticeContainer.empty(),i.errorNoticeContainer.append(t),i.errorNoticeContainer.slideDown("fast"),wp.a11y.speak(n)):i.errorNoticeContainer.slideUp("fast")},initializeEditor:function(){var e,t=this;s.codeEditorSettings.disabled||(e=_.extend({},s.codeEditorSettings,{onTabPrevious:function(){t.fields.title.focus()},onTabNext:function(){t.syncContainer.add(t.syncContainer.parent().find(".widget-position, .widget-control-actions")).find(":tabbable").first().focus()},onChangeLintingErrors:function(e){t.currentErrorAnnotations=e},onUpdateErrorNotice:function(e){t.saveButton.toggleClass("validation-blocked disabled",0<e.length),t.updateErrorNotice(e)}}),t.editor=wp.codeEditor.initialize(t.fields.content,e),a(t.editor.codemirror.display.lineDiv).attr({role:"textbox","aria-multiline":"true","aria-labelledby":t.fields.content[0].id+"-label","aria-describedby":"editor-keyboard-trap-help-1 editor-keyboard-trap-help-2 editor-keyboard-trap-help-3 editor-keyboard-trap-help-4"}),a("#"+t.fields.content[0].id+"-label").on("click",function(){t.editor.codemirror.focus()}),t.fields.content.on("change",function(){this.value!==t.editor.codemirror.getValue()&&t.editor.codemirror.setValue(this.value)}),t.editor.codemirror.on("change",function(){var e=t.editor.codemirror.getValue();e!==t.fields.content.val()&&t.fields.content.val(e).trigger("change")}),t.editor.codemirror.on("blur",function(){t.contentUpdateBypassed&&t.syncContainer.find(".sync-input.content").trigger("change")}),wp.customize&&t.editor.codemirror.on("keydown",function(e,t){27===t.keyCode&&t.stopPropagation()}))}}),s.widgetControls={},s.handleWidgetAdded=function(e,t){var i,n,o,d=t.find("> .widget-inside > .form, > .widget-inside > form"),r=d.find("> .id_base").val();-1===s.idBases.indexOf(r)||(r=d.find(".widget-id").val(),s.widgetControls[r])||(d=a("<div></div>"),(o=t.find(".widget-content:first")).before(d),i=new s.CustomHtmlWidgetControl({el:d,syncContainer:o}),s.widgetControls[r]=i,(n=function(){(wp.customize?t.parent().hasClass("expanded"):t.hasClass("open"))?i.initializeEditor():setTimeout(n,50)})())},s.setupAccessibleMode=function(){var e,t=a(".editwidget > form");0!==t.length&&(e=t.find(".id_base").val(),-1!==s.idBases.indexOf(e))&&(e=a("<div></div>"),(t=t.find("> .widget-inside")).before(e),new s.CustomHtmlWidgetControl({el:e,syncContainer:t}).initializeEditor())},s.handleWidgetUpdated=function(e,t){var t=t.find("> .widget-inside > .form, > .widget-inside > form"),i=t.find("> .id_base").val();-1!==s.idBases.indexOf(i)&&(i=t.find("> .widget-id").val(),t=s.widgetControls[i])&&t.updateFields()},s.init=function(e){var t=a(document);_.extend(s.codeEditorSettings,e),t.on("widget-added",s.handleWidgetAdded),t.on("widget-synced widget-updated",s.handleWidgetUpdated),a(function(){"widgets"===window.pagenow&&(a(".widgets-holder-wrap:not(#available-widgets)").find("div.widget").one("click.toggle-widget-expanded",function(){var e=a(this);s.handleWidgetAdded(new jQuery.Event("widget-added"),e)}),"complete"===document.readyState?s.setupAccessibleMode():a(window).on("load",function(){s.setupAccessibleMode()}))})},s}(jQuery);PK �8FZ|yN�� � media-image-widget.min.jsnu �[��� /*! This file is auto-generated */
!function(a,o){"use strict";var e=a.MediaWidgetModel.extend({}),t=a.MediaWidgetControl.extend({events:_.extend({},a.MediaWidgetControl.prototype.events,{"click .media-widget-preview.populated":"editMedia"}),renderPreview:function(){var e,t,i=this;(i.model.get("attachment_id")||i.model.get("url"))&&(t=i.$el.find(".media-widget-preview"),e=wp.template("wp-media-widget-image-preview"),t.html(e(i.previewTemplateProps.toJSON())),t.addClass("populated"),i.$el.find(".link").is(document.activeElement)||(e=i.$el.find(".media-widget-fields"),t=wp.template("wp-media-widget-image-fields"),e.html(t(i.previewTemplateProps.toJSON()))))},editMedia:function(){var i,e,a=this,t=a.mapModelToMediaFrameProps(a.model.toJSON());"none"===t.link&&(t.linkUrl=""),(i=wp.media({frame:"image",state:"image-details",metadata:t})).$el.addClass("media-widget"),t=function(){var e=i.state().attributes.image.toJSON(),t=e.link;e.link=e.linkUrl,a.selectedAttachment.set(e),a.displaySettings.set("link",t),a.model.set(_.extend(a.mapMediaToModelProps(e),{error:!1}))},i.state("image-details").on("update",t),i.state("replace-image").on("replace",t),e=wp.media.model.Attachment.prototype.sync,wp.media.model.Attachment.prototype.sync=function(){return o.Deferred().rejectWith(this).promise()},i.on("close",function(){i.detach(),wp.media.model.Attachment.prototype.sync=e}),i.open()},getEmbedResetProps:function(){return _.extend(a.MediaWidgetControl.prototype.getEmbedResetProps.call(this),{size:"full",width:0,height:0})},getModelPropsFromMediaFrame:function(e){return _.omit(a.MediaWidgetControl.prototype.getModelPropsFromMediaFrame.call(this,e),"image_title")},mapModelToPreviewTemplateProps:function(){var e=this,t=e.model.get("url"),i=a.MediaWidgetControl.prototype.mapModelToPreviewTemplateProps.call(e);return i.currentFilename=t?t.replace(/\?.*$/,"").replace(/^.+\//,""):"",i.link_url=e.model.get("link_url"),i}});a.controlConstructors.media_image=t,a.modelConstructors.media_image=e}(wp.mediaWidgets,jQuery);PK �8FZ���l�7 �7 media-widgets.min.jsnu �[��� /*! This file is auto-generated */
wp.mediaWidgets=function(c){"use strict";var m={controlConstructors:{},modelConstructors:{}};return m.PersistentDisplaySettingsLibrary=wp.media.controller.Library.extend({initialize:function(e){_.bindAll(this,"handleDisplaySettingChange"),wp.media.controller.Library.prototype.initialize.call(this,e)},handleDisplaySettingChange:function(e){this.get("selectedDisplaySettings").set(e.attributes)},display:function(e){var t=this.get("selectedDisplaySettings"),e=wp.media.controller.Library.prototype.display.call(this,e);return e.off("change",this.handleDisplaySettingChange),e.set(t.attributes),"custom"===t.get("link_type")&&(e.linkUrl=t.get("link_url")),e.on("change",this.handleDisplaySettingChange),e}}),m.MediaEmbedView=wp.media.view.Embed.extend({initialize:function(e){var t=this;wp.media.view.Embed.prototype.initialize.call(t,e),"image"!==t.controller.options.mimeType&&(e=t.controller.states.get("embed")).off("scan",e.scanImage,e)},refresh:function(){var e="image"===this.controller.options.mimeType?wp.media.view.EmbedImage:wp.media.view.EmbedLink.extend({setAddToWidgetButtonDisabled:function(e){this.views.parent.views.parent.views.get(".media-frame-toolbar")[0].$el.find(".media-button-select").prop("disabled",e)},setErrorNotice:function(e){var t=this.views.parent.$el.find("> .notice:first-child");e?(t.length||((t=c('<div class="media-widget-embed-notice notice notice-error notice-alt" role="alert"></div>')).hide(),this.views.parent.$el.prepend(t)),t.empty(),t.append(c("<p>",{html:e})),t.slideDown("fast")):t.length&&t.slideUp("fast")},updateoEmbed:function(){var e=this,t=e.model.get("url");t?(t.match(/^(http|https):\/\/.+\//)||(e.controller.$el.find("#embed-url-field").addClass("invalid"),e.setAddToWidgetButtonDisabled(!0)),wp.media.view.EmbedLink.prototype.updateoEmbed.call(e)):(e.setErrorNotice(""),e.setAddToWidgetButtonDisabled(!0))},fetch:function(){var t,e,i=this,n=i.model.get("url");i.dfd&&"pending"===i.dfd.state()&&i.dfd.abort(),t=function(e){i.renderoEmbed({data:{body:e}}),i.controller.$el.find("#embed-url-field").removeClass("invalid"),i.setErrorNotice(""),i.setAddToWidgetButtonDisabled(!1)},(e=document.createElement("a")).href=n,(e=e.pathname.toLowerCase().match(/\.(\w+)$/))?(e=e[1],!wp.media.view.settings.embedMimes[e]||0!==wp.media.view.settings.embedMimes[e].indexOf(i.controller.options.mimeType)?i.renderFail():t("\x3c!--success--\x3e")):((e=/https?:\/\/www\.youtube\.com\/embed\/([^/]+)/.exec(n))&&(n="https://www.youtube.com/watch?v="+e[1],i.model.attributes.url=n),i.dfd=wp.apiRequest({url:wp.media.view.settings.oEmbedProxyUrl,data:{url:n,maxwidth:i.model.get("width"),maxheight:i.model.get("height"),discover:!1},type:"GET",dataType:"json",context:i}),i.dfd.done(function(e){i.controller.options.mimeType!==e.type?i.renderFail():t(e.html)}),i.dfd.fail(_.bind(i.renderFail,i)))},renderFail:function(){var e=this;e.controller.$el.find("#embed-url-field").addClass("invalid"),e.setErrorNotice(e.controller.options.invalidEmbedTypeError||"ERROR"),e.setAddToWidgetButtonDisabled(!0)}});this.settings(new e({controller:this.controller,model:this.model.props,priority:40}))}}),m.MediaFrameSelect=wp.media.view.MediaFrame.Post.extend({createStates:function(){var t=this.options.mimeType,i=[];_.each(wp.media.view.settings.embedMimes,function(e){0===e.indexOf(t)&&i.push(e)}),0<i.length&&(t=i),this.states.add([new m.PersistentDisplaySettingsLibrary({id:"insert",title:this.options.title,selection:this.options.selection,priority:20,toolbar:"main-insert",filterable:"dates",library:wp.media.query({type:t}),multiple:!1,editable:!0,selectedDisplaySettings:this.options.selectedDisplaySettings,displaySettings:!!_.isUndefined(this.options.showDisplaySettings)||this.options.showDisplaySettings,displayUserSettings:!1}),new wp.media.controller.EditImage({model:this.options.editImage}),new wp.media.controller.Embed({metadata:this.options.metadata,type:"image"===this.options.mimeType?"image":"link",invalidEmbedTypeError:this.options.invalidEmbedTypeError})])},mainInsertToolbar:function(e){var i=this;e.set("insert",{style:"primary",priority:80,text:i.options.text,requires:{selection:!0},click:function(){var e=i.state(),t=e.get("selection");i.close(),e.trigger("insert",t).reset()}})},mainEmbedToolbar:function(e){e.view=new wp.media.view.Toolbar.Embed({controller:this,text:this.options.text,event:"insert"})},embedContent:function(){var e=new m.MediaEmbedView({controller:this,model:this.state()}).render();this.content.set(e)}}),m.MediaWidgetControl=Backbone.View.extend({l10n:{add_to_widget:"{{add_to_widget}}",add_media:"{{add_media}}"},id_base:"",mime_type:"",events:{"click .notice-missing-attachment a":"handleMediaLibraryLinkClick","click .select-media":"selectMedia","click .placeholder":"selectMedia","click .edit-media":"editMedia"},showDisplaySettings:!0,initialize:function(e){var i=this;if(Backbone.View.prototype.initialize.call(i,e),!(i.model instanceof m.MediaWidgetModel))throw new Error("Missing options.model");if(!e.el)throw new Error("Missing options.el");if(!e.syncContainer)throw new Error("Missing options.syncContainer");if(i.syncContainer=e.syncContainer,i.$el.addClass("media-widget-control"),_.bindAll(i,"syncModelToInputs","render","updateSelectedAttachment","renderPreview"),!i.id_base&&(_.find(m.controlConstructors,function(e,t){return i instanceof e&&(i.id_base=t,!0)}),!i.id_base))throw new Error("Missing id_base.");i.previewTemplateProps=new Backbone.Model(i.mapModelToPreviewTemplateProps()),i.selectedAttachment=new wp.media.model.Attachment,i.renderPreview=_.debounce(i.renderPreview),i.listenTo(i.previewTemplateProps,"change",i.renderPreview),i.model.on("change:attachment_id",i.updateSelectedAttachment),i.model.on("change:url",i.updateSelectedAttachment),i.updateSelectedAttachment(),i.listenTo(i.model,"change",i.syncModelToInputs),i.listenTo(i.model,"change",i.syncModelToPreviewProps),i.listenTo(i.model,"change",i.render),i.$el.on("input change",".title",function(){i.model.set({title:c(this).val().trim()})}),i.$el.on("input change",".link",function(){var e=c(this).val().trim(),t="custom";i.selectedAttachment.get("linkUrl")===e||i.selectedAttachment.get("link")===e?t="post":i.selectedAttachment.get("url")===e&&(t="file"),i.model.set({link_url:e,link_type:t}),i.displaySettings.set({link:t,linkUrl:e})}),i.displaySettings=new Backbone.Model(_.pick(i.mapModelToMediaFrameProps(_.extend(i.model.defaults(),i.model.toJSON())),_.keys(wp.media.view.settings.defaultProps)))},updateSelectedAttachment:function(){var e,t=this;0===t.model.get("attachment_id")?(t.selectedAttachment.clear(),t.model.set("error",!1)):t.model.get("attachment_id")!==t.selectedAttachment.get("id")&&(e=new wp.media.model.Attachment({id:t.model.get("attachment_id")})).fetch().done(function(){t.model.set("error",!1),t.selectedAttachment.set(e.toJSON())}).fail(function(){t.model.set("error","missing_attachment")})},syncModelToPreviewProps:function(){this.previewTemplateProps.set(this.mapModelToPreviewTemplateProps())},syncModelToInputs:function(){var n=this;n.syncContainer.find(".media-widget-instance-property").each(function(){var e=c(this),t=e.data("property"),i=n.model.get(t);_.isUndefined(i)||(i="array"===n.model.schema[t].type&&_.isArray(i)?i.join(","):"boolean"===n.model.schema[t].type?i?"1":"":String(i),e.val()!==i&&(e.val(i),e.trigger("change")))})},template:function(){if(c("#tmpl-widget-media-"+this.id_base+"-control").length)return wp.template("widget-media-"+this.id_base+"-control");throw new Error("Missing widget control template for "+this.id_base)},render:function(){var e,t=this;t.templateRendered||(t.$el.html(t.template()(t.model.toJSON())),t.renderPreview(),t.templateRendered=!0),(e=t.$el.find(".title")).is(document.activeElement)||e.val(t.model.get("title")),t.$el.toggleClass("selected",t.isSelected())},renderPreview:function(){throw new Error("renderPreview must be implemented")},isSelected:function(){return!this.model.get("error")&&Boolean(this.model.get("attachment_id")||this.model.get("url"))},handleMediaLibraryLinkClick:function(e){e.preventDefault(),this.selectMedia()},selectMedia:function(){var i,t,e,n=this,d=[];n.isSelected()&&0!==n.model.get("attachment_id")&&d.push(n.selectedAttachment),d=new wp.media.model.Selection(d,{multiple:!1}),(e=n.mapModelToMediaFrameProps(n.model.toJSON())).size&&n.displaySettings.set("size",e.size),i=new m.MediaFrameSelect({title:n.l10n.add_media,frame:"post",text:n.l10n.add_to_widget,selection:d,mimeType:n.mime_type,selectedDisplaySettings:n.displaySettings,showDisplaySettings:n.showDisplaySettings,metadata:e,state:n.isSelected()&&0===n.model.get("attachment_id")?"embed":"insert",invalidEmbedTypeError:n.l10n.unsupported_file_type}),(wp.media.frame=i).on("insert",function(){var e={},t=i.state();"embed"===t.get("id")?_.extend(e,{id:0},t.props.toJSON()):_.extend(e,t.get("selection").first().toJSON()),n.selectedAttachment.set(e),n.model.set("error",!1),n.model.set(n.getModelPropsFromMediaFrame(i))}),t=wp.media.model.Attachment.prototype.sync,wp.media.model.Attachment.prototype.sync=function(e){return"delete"===e?t.apply(this,arguments):c.Deferred().rejectWith(this).promise()},i.on("close",function(){wp.media.model.Attachment.prototype.sync=t}),i.$el.addClass("media-widget"),i.open(),d&&d.on("destroy",function(e){n.model.get("attachment_id")===e.get("id")&&n.model.set({attachment_id:0,url:""})}),i.$el.find(".media-frame-menu .media-menu-item.active").focus()},getModelPropsFromMediaFrame:function(e){var t,i,n=this,d=e.state();if("insert"===d.get("id"))(t=d.get("selection").first().toJSON()).postUrl=t.link,n.showDisplaySettings&&_.extend(t,e.content.get(".attachments-browser").sidebar.get("display").model.toJSON()),t.sizes&&t.size&&t.sizes[t.size]&&(t.url=t.sizes[t.size].url);else{if("embed"!==d.get("id"))throw new Error("Unexpected state: "+d.get("id"));t=_.extend(d.props.toJSON(),{attachment_id:0},n.model.getEmbedResetProps())}return t.id&&(t.attachment_id=t.id),i=n.mapMediaToModelProps(t),_.each(wp.media.view.settings.embedExts,function(e){e in n.model.schema&&i.url!==i[e]&&(i[e]="")}),i},mapMediaToModelProps:function(e){var t,i=this,n={},d={};return _.each(i.model.schema,function(e,t){"title"!==t&&(n[e.media_prop||t]=t)}),_.each(e,function(e,t){t=n[t]||t;i.model.schema[t]&&(d[t]=e)}),"custom"===e.size&&(d.width=e.customWidth,d.height=e.customHeight),"post"===e.link?d.link_url=e.postUrl||e.linkUrl:"file"===e.link&&(d.link_url=e.url),!e.attachment_id&&e.id&&(d.attachment_id=e.id),e.url&&(t=e.url.replace(/#.*$/,"").replace(/\?.*$/,"").split(".").pop().toLowerCase())in i.model.schema&&(d[t]=e.url),_.omit(d,"title")},mapModelToMediaFrameProps:function(e){var n=this,d={};return _.each(e,function(e,t){var i=n.model.schema[t]||{};d[i.media_prop||t]=e}),d.attachment_id=d.id,"custom"===d.size&&(d.customWidth=n.model.get("width"),d.customHeight=n.model.get("height")),d},mapModelToPreviewTemplateProps:function(){var i=this,n={};return _.each(i.model.schema,function(e,t){e.hasOwnProperty("should_preview_update")&&!e.should_preview_update||(n[t]=i.model.get(t))}),n.error=i.model.get("error"),n},editMedia:function(){throw new Error("editMedia not implemented")}}),m.MediaWidgetModel=Backbone.Model.extend({idAttribute:"widget_id",schema:{title:{type:"string",default:""},attachment_id:{type:"integer",default:0},url:{type:"string",default:""}},defaults:function(){var i={};return _.each(this.schema,function(e,t){i[t]=e.default}),i},set:function(e,t,i){var n,d,o=this;return null===e?o:(e="object"==typeof e?(n=e,t):((n={})[e]=t,i),d={},_.each(n,function(e,t){var i;o.schema[t]?"array"===(i=o.schema[t].type)?(d[t]=e,_.isArray(d[t])||(d[t]=d[t].split(/,/)),o.schema[t].items&&"integer"===o.schema[t].items.type&&(d[t]=_.filter(_.map(d[t],function(e){return parseInt(e,10)},function(e){return"number"==typeof e})))):d[t]="integer"===i?parseInt(e,10):"boolean"===i?!(!e||"0"===e||"false"===e):e:d[t]=e}),Backbone.Model.prototype.set.call(this,d,e))},getEmbedResetProps:function(){return{id:0}}}),m.modelCollection=new(Backbone.Collection.extend({model:m.MediaWidgetModel})),m.widgetControls={},m.handleWidgetAdded=function(e,t){var i,n,d,o,a,s,r=t.find("> .widget-inside > .form, > .widget-inside > form"),l=r.find("> .id_base").val(),r=r.find("> .widget-id").val();m.widgetControls[r]||(d=m.controlConstructors[l])&&(l=m.modelConstructors[l]||m.MediaWidgetModel,i=c("<div></div>"),(n=t.find(".widget-content:first")).before(i),o={},n.find(".media-widget-instance-property").each(function(){var e=c(this);o[e.data("property")]=e.val()}),o.widget_id=r,r=new l(o),a=new d({el:i,syncContainer:n,model:r}),(s=function(){t.hasClass("open")?a.render():setTimeout(s,50)})(),m.modelCollection.add([r]),m.widgetControls[r.get("widget_id")]=a)},m.setupAccessibleMode=function(){var e,t,i,n,d,o=c(".editwidget > form");0!==o.length&&(i=o.find(".id_base").val(),t=m.controlConstructors[i])&&(e=o.find("> .widget-control-actions > .widget-id").val(),i=m.modelConstructors[i]||m.MediaWidgetModel,d=c("<div></div>"),(o=o.find("> .widget-inside")).before(d),n={},o.find(".media-widget-instance-property").each(function(){var e=c(this);n[e.data("property")]=e.val()}),n.widget_id=e,e=new t({el:d,syncContainer:o,model:new i(n)}),m.modelCollection.add([e.model]),(m.widgetControls[e.model.get("widget_id")]=e).render())},m.handleWidgetUpdated=function(e,t){var i={},t=t.find("> .widget-inside > .form, > .widget-inside > form"),n=t.find("> .widget-id").val(),n=m.widgetControls[n];n&&(t.find("> .widget-content").find(".media-widget-instance-property").each(function(){var e=c(this).data("property");i[e]=c(this).val()}),n.stopListening(n.model,"change",n.syncModelToInputs),n.model.set(i),n.listenTo(n.model,"change",n.syncModelToInputs))},m.init=function(){var e=c(document);e.on("widget-added",m.handleWidgetAdded),e.on("widget-synced widget-updated",m.handleWidgetUpdated),c(function(){"widgets"===window.pagenow&&(c(".widgets-holder-wrap:not(#available-widgets)").find("div.widget").one("click.toggle-widget-expanded",function(){var e=c(this);m.handleWidgetAdded(new jQuery.Event("widget-added"),e)}),"complete"===document.readyState?m.setupAccessibleMode():c(window).on("load",function(){m.setupAccessibleMode()}))})},m}(jQuery);PK �8FZ��YD� � text-widgets.min.jsnu �[��� /*! This file is auto-generated */
wp.textWidgets=function(r){"use strict";var u={dismissedPointers:[],idBases:["text"]};return u.TextWidgetControl=Backbone.View.extend({events:{},initialize:function(e){var n=this;if(!e.el)throw new Error("Missing options.el");if(!e.syncContainer)throw new Error("Missing options.syncContainer");Backbone.View.prototype.initialize.call(n,e),n.syncContainer=e.syncContainer,n.$el.addClass("text-widget-fields"),n.$el.html(wp.template("widget-text-control-fields")),n.customHtmlWidgetPointer=n.$el.find(".wp-pointer.custom-html-widget-pointer"),n.customHtmlWidgetPointer.length&&(n.customHtmlWidgetPointer.find(".close").on("click",function(e){e.preventDefault(),n.customHtmlWidgetPointer.hide(),r("#"+n.fields.text.attr("id")+"-html").trigger("focus"),n.dismissPointers(["text_widget_custom_html"])}),n.customHtmlWidgetPointer.find(".add-widget").on("click",function(e){e.preventDefault(),n.customHtmlWidgetPointer.hide(),n.openAvailableWidgetsPanel()})),n.pasteHtmlPointer=n.$el.find(".wp-pointer.paste-html-pointer"),n.pasteHtmlPointer.length&&n.pasteHtmlPointer.find(".close").on("click",function(e){e.preventDefault(),n.pasteHtmlPointer.hide(),n.editor.focus(),n.dismissPointers(["text_widget_custom_html","text_widget_paste_html"])}),n.fields={title:n.$el.find(".title"),text:n.$el.find(".text")},_.each(n.fields,function(t,i){t.on("input change",function(){var e=n.syncContainer.find(".sync-input."+i);e.val()!==t.val()&&(e.val(t.val()),e.trigger("change"))}),t.val(n.syncContainer.find(".sync-input."+i).val())})},dismissPointers:function(e){_.each(e,function(e){wp.ajax.post("dismiss-wp-pointer",{pointer:e}),u.dismissedPointers.push(e)})},openAvailableWidgetsPanel:function(){var t;wp.customize.section.each(function(e){e.extended(wp.customize.Widgets.SidebarSection)&&e.expanded()&&(t=wp.customize.control("sidebars_widgets["+e.params.sidebarId+"]"))}),t&&setTimeout(function(){wp.customize.Widgets.availableWidgetsPanel.open(t),wp.customize.Widgets.availableWidgetsPanel.$search.val("HTML").trigger("keyup")})},updateFields:function(){var e,t=this;t.fields.title.is(document.activeElement)||(e=t.syncContainer.find(".sync-input.title"),t.fields.title.val(e.val())),e=t.syncContainer.find(".sync-input.text"),t.fields.text.is(":visible")?t.fields.text.is(document.activeElement)||t.fields.text.val(e.val()):t.editor&&!t.editorFocused&&e.val()!==t.fields.text.val()&&t.editor.setContent(wp.oldEditor.autop(e.val()))},initializeEditor:function(){var d,e,o,t,s=this,a=1e3,l=!1,c=!1;e=s.fields.text,d=e.attr("id"),t=e.val(),o=function(){s.editor.isDirty()&&(wp.customize&&wp.customize.state&&(wp.customize.state("processing").set(wp.customize.state("processing").get()+1),_.delay(function(){wp.customize.state("processing").set(wp.customize.state("processing").get()-1)},300)),s.editor.isHidden()||s.editor.save()),c&&t!==e.val()&&(e.trigger("change"),c=!1,t=e.val())},s.syncContainer.closest(".widget").find("[name=savewidget]:first").on("click",function(){o()}),function e(){var t,i,n;if(document.getElementById(d))if(void 0===window.tinymce)wp.oldEditor.initialize(d,{quicktags:!0,mediaButtons:!0});else{if(tinymce.get(d)&&(l=tinymce.get(d).isHidden(),wp.oldEditor.remove(d)),r(document).one("wp-before-tinymce-init.text-widget-init",function(e,t){t.plugins&&!/\bwpview\b/.test(t.plugins)&&(t.plugins+=",wpview")}),wp.oldEditor.initialize(d,{tinymce:{wpautop:!0},quicktags:!0,mediaButtons:!0}),n=function(e){e.show(),e.find(".close").trigger("focus"),wp.a11y.speak(e.find("h3, p").map(function(){return r(this).text()}).get().join("\n\n"))},!(t=window.tinymce.get(d)))throw new Error("Failed to initialize editor");i=function(){r(t.getWin()).on("pagehide",function(){_.defer(e)}),l&&switchEditors.go(d,"html"),r("#"+d+"-html").on("click",function(){s.pasteHtmlPointer.hide(),-1===u.dismissedPointers.indexOf("text_widget_custom_html")&&n(s.customHtmlWidgetPointer)}),r("#"+d+"-tmce").on("click",function(){s.customHtmlWidgetPointer.hide()}),t.on("pastepreprocess",function(e){e=e.content,-1===u.dismissedPointers.indexOf("text_widget_paste_html")&&e&&/<\w+.*?>/.test(e)&&_.delay(function(){n(s.pasteHtmlPointer)},250)})},t.initialized?i():t.on("init",i),s.editorFocused=!1,t.on("focus",function(){s.editorFocused=!0}),t.on("paste",function(){t.setDirty(!0),o()}),t.on("NodeChange",function(){c=!0}),t.on("NodeChange",_.debounce(o,a)),t.on("blur hide",function(){s.editorFocused=!1,o()}),s.editor=t}}()}}),u.widgetControls={},u.handleWidgetAdded=function(e,t){var i,n,d,o=t.find("> .widget-inside > .form, > .widget-inside > form"),s=o.find("> .id_base").val();-1===u.idBases.indexOf(s)||(s=o.find(".widget-id").val(),u.widgetControls[s])||o.find(".visual").val()&&(o=r("<div></div>"),(d=t.find(".widget-content:first")).before(o),i=new u.TextWidgetControl({el:o,syncContainer:d}),u.widgetControls[s]=i,(n=function(){t.hasClass("open")?i.initializeEditor():setTimeout(n,50)})())},u.setupAccessibleMode=function(){var e,t=r(".editwidget > form");0!==t.length&&(e=t.find(".id_base").val(),-1!==u.idBases.indexOf(e))&&t.find(".visual").val()&&(e=r("<div></div>"),(t=t.find("> .widget-inside")).before(e),new u.TextWidgetControl({el:e,syncContainer:t}).initializeEditor())},u.handleWidgetUpdated=function(e,t){var t=t.find("> .widget-inside > .form, > .widget-inside > form"),i=t.find("> .id_base").val();-1!==u.idBases.indexOf(i)&&(i=t.find("> .widget-id").val(),t=u.widgetControls[i])&&t.updateFields()},u.init=function(){var e=r(document);e.on("widget-added",u.handleWidgetAdded),e.on("widget-synced widget-updated",u.handleWidgetUpdated),r(function(){"widgets"===window.pagenow&&(r(".widgets-holder-wrap:not(#available-widgets)").find("div.widget").one("click.toggle-widget-expanded",function(){var e=r(this);u.handleWidgetAdded(new jQuery.Event("widget-added"),e)}),u.setupAccessibleMode())})},u}(jQuery);PK �8FZ'��p� p� media-widgets.jsnu �[��� /**
* @output wp-admin/js/widgets/media-widgets.js
*/
/* eslint consistent-this: [ "error", "control" ] */
/**
* @namespace wp.mediaWidgets
* @memberOf wp
*/
wp.mediaWidgets = ( function( $ ) {
'use strict';
var component = {};
/**
* Widget control (view) constructors, mapping widget id_base to subclass of MediaWidgetControl.
*
* Media widgets register themselves by assigning subclasses of MediaWidgetControl onto this object by widget ID base.
*
* @memberOf wp.mediaWidgets
*
* @type {Object.<string, wp.mediaWidgets.MediaWidgetModel>}
*/
component.controlConstructors = {};
/**
* Widget model constructors, mapping widget id_base to subclass of MediaWidgetModel.
*
* Media widgets register themselves by assigning subclasses of MediaWidgetControl onto this object by widget ID base.
*
* @memberOf wp.mediaWidgets
*
* @type {Object.<string, wp.mediaWidgets.MediaWidgetModel>}
*/
component.modelConstructors = {};
component.PersistentDisplaySettingsLibrary = wp.media.controller.Library.extend(/** @lends wp.mediaWidgets.PersistentDisplaySettingsLibrary.prototype */{
/**
* Library which persists the customized display settings across selections.
*
* @constructs wp.mediaWidgets.PersistentDisplaySettingsLibrary
* @augments wp.media.controller.Library
*
* @param {Object} options - Options.
*
* @return {void}
*/
initialize: function initialize( options ) {
_.bindAll( this, 'handleDisplaySettingChange' );
wp.media.controller.Library.prototype.initialize.call( this, options );
},
/**
* Sync changes to the current display settings back into the current customized.
*
* @param {Backbone.Model} displaySettings - Modified display settings.
* @return {void}
*/
handleDisplaySettingChange: function handleDisplaySettingChange( displaySettings ) {
this.get( 'selectedDisplaySettings' ).set( displaySettings.attributes );
},
/**
* Get the display settings model.
*
* Model returned is updated with the current customized display settings,
* and an event listener is added so that changes made to the settings
* will sync back into the model storing the session's customized display
* settings.
*
* @param {Backbone.Model} model - Display settings model.
* @return {Backbone.Model} Display settings model.
*/
display: function getDisplaySettingsModel( model ) {
var display, selectedDisplaySettings = this.get( 'selectedDisplaySettings' );
display = wp.media.controller.Library.prototype.display.call( this, model );
display.off( 'change', this.handleDisplaySettingChange ); // Prevent duplicated event handlers.
display.set( selectedDisplaySettings.attributes );
if ( 'custom' === selectedDisplaySettings.get( 'link_type' ) ) {
display.linkUrl = selectedDisplaySettings.get( 'link_url' );
}
display.on( 'change', this.handleDisplaySettingChange );
return display;
}
});
/**
* Extended view for managing the embed UI.
*
* @class wp.mediaWidgets.MediaEmbedView
* @augments wp.media.view.Embed
*/
component.MediaEmbedView = wp.media.view.Embed.extend(/** @lends wp.mediaWidgets.MediaEmbedView.prototype */{
/**
* Initialize.
*
* @since 4.9.0
*
* @param {Object} options - Options.
* @return {void}
*/
initialize: function( options ) {
var view = this, embedController; // eslint-disable-line consistent-this
wp.media.view.Embed.prototype.initialize.call( view, options );
if ( 'image' !== view.controller.options.mimeType ) {
embedController = view.controller.states.get( 'embed' );
embedController.off( 'scan', embedController.scanImage, embedController );
}
},
/**
* Refresh embed view.
*
* Forked override of {wp.media.view.Embed#refresh()} to suppress irrelevant "link text" field.
*
* @return {void}
*/
refresh: function refresh() {
/**
* @class wp.mediaWidgets~Constructor
*/
var Constructor;
if ( 'image' === this.controller.options.mimeType ) {
Constructor = wp.media.view.EmbedImage;
} else {
// This should be eliminated once #40450 lands of when this is merged into core.
Constructor = wp.media.view.EmbedLink.extend(/** @lends wp.mediaWidgets~Constructor.prototype */{
/**
* Set the disabled state on the Add to Widget button.
*
* @param {boolean} disabled - Disabled.
* @return {void}
*/
setAddToWidgetButtonDisabled: function setAddToWidgetButtonDisabled( disabled ) {
this.views.parent.views.parent.views.get( '.media-frame-toolbar' )[0].$el.find( '.media-button-select' ).prop( 'disabled', disabled );
},
/**
* Set or clear an error notice.
*
* @param {string} notice - Notice.
* @return {void}
*/
setErrorNotice: function setErrorNotice( notice ) {
var embedLinkView = this, noticeContainer; // eslint-disable-line consistent-this
noticeContainer = embedLinkView.views.parent.$el.find( '> .notice:first-child' );
if ( ! notice ) {
if ( noticeContainer.length ) {
noticeContainer.slideUp( 'fast' );
}
} else {
if ( ! noticeContainer.length ) {
noticeContainer = $( '<div class="media-widget-embed-notice notice notice-error notice-alt" role="alert"></div>' );
noticeContainer.hide();
embedLinkView.views.parent.$el.prepend( noticeContainer );
}
noticeContainer.empty();
noticeContainer.append( $( '<p>', {
html: notice
}));
noticeContainer.slideDown( 'fast' );
}
},
/**
* Update oEmbed.
*
* @since 4.9.0
*
* @return {void}
*/
updateoEmbed: function() {
var embedLinkView = this, url; // eslint-disable-line consistent-this
url = embedLinkView.model.get( 'url' );
// Abort if the URL field was emptied out.
if ( ! url ) {
embedLinkView.setErrorNotice( '' );
embedLinkView.setAddToWidgetButtonDisabled( true );
return;
}
if ( ! url.match( /^(http|https):\/\/.+\// ) ) {
embedLinkView.controller.$el.find( '#embed-url-field' ).addClass( 'invalid' );
embedLinkView.setAddToWidgetButtonDisabled( true );
}
wp.media.view.EmbedLink.prototype.updateoEmbed.call( embedLinkView );
},
/**
* Fetch media.
*
* @return {void}
*/
fetch: function() {
var embedLinkView = this, fetchSuccess, matches, fileExt, urlParser, url, re, youTubeEmbedMatch; // eslint-disable-line consistent-this
url = embedLinkView.model.get( 'url' );
if ( embedLinkView.dfd && 'pending' === embedLinkView.dfd.state() ) {
embedLinkView.dfd.abort();
}
fetchSuccess = function( response ) {
embedLinkView.renderoEmbed({
data: {
body: response
}
});
embedLinkView.controller.$el.find( '#embed-url-field' ).removeClass( 'invalid' );
embedLinkView.setErrorNotice( '' );
embedLinkView.setAddToWidgetButtonDisabled( false );
};
urlParser = document.createElement( 'a' );
urlParser.href = url;
matches = urlParser.pathname.toLowerCase().match( /\.(\w+)$/ );
if ( matches ) {
fileExt = matches[1];
if ( ! wp.media.view.settings.embedMimes[ fileExt ] ) {
embedLinkView.renderFail();
} else if ( 0 !== wp.media.view.settings.embedMimes[ fileExt ].indexOf( embedLinkView.controller.options.mimeType ) ) {
embedLinkView.renderFail();
} else {
fetchSuccess( '<!--success-->' );
}
return;
}
// Support YouTube embed links.
re = /https?:\/\/www\.youtube\.com\/embed\/([^/]+)/;
youTubeEmbedMatch = re.exec( url );
if ( youTubeEmbedMatch ) {
url = 'https://www.youtube.com/watch?v=' + youTubeEmbedMatch[ 1 ];
// silently change url to proper oembed-able version.
embedLinkView.model.attributes.url = url;
}
embedLinkView.dfd = wp.apiRequest({
url: wp.media.view.settings.oEmbedProxyUrl,
data: {
url: url,
maxwidth: embedLinkView.model.get( 'width' ),
maxheight: embedLinkView.model.get( 'height' ),
discover: false
},
type: 'GET',
dataType: 'json',
context: embedLinkView
});
embedLinkView.dfd.done( function( response ) {
if ( embedLinkView.controller.options.mimeType !== response.type ) {
embedLinkView.renderFail();
return;
}
fetchSuccess( response.html );
});
embedLinkView.dfd.fail( _.bind( embedLinkView.renderFail, embedLinkView ) );
},
/**
* Handle render failure.
*
* Overrides the {EmbedLink#renderFail()} method to prevent showing the "Link Text" field.
* The element is getting display:none in the stylesheet, but the underlying method uses
* uses {jQuery.fn.show()} which adds an inline style. This avoids the need for !important.
*
* @return {void}
*/
renderFail: function renderFail() {
var embedLinkView = this; // eslint-disable-line consistent-this
embedLinkView.controller.$el.find( '#embed-url-field' ).addClass( 'invalid' );
embedLinkView.setErrorNotice( embedLinkView.controller.options.invalidEmbedTypeError || 'ERROR' );
embedLinkView.setAddToWidgetButtonDisabled( true );
}
});
}
this.settings( new Constructor({
controller: this.controller,
model: this.model.props,
priority: 40
}));
}
});
/**
* Custom media frame for selecting uploaded media or providing media by URL.
*
* @class wp.mediaWidgets.MediaFrameSelect
* @augments wp.media.view.MediaFrame.Post
*/
component.MediaFrameSelect = wp.media.view.MediaFrame.Post.extend(/** @lends wp.mediaWidgets.MediaFrameSelect.prototype */{
/**
* Create the default states.
*
* @return {void}
*/
createStates: function createStates() {
var mime = this.options.mimeType, specificMimes = [];
_.each( wp.media.view.settings.embedMimes, function( embedMime ) {
if ( 0 === embedMime.indexOf( mime ) ) {
specificMimes.push( embedMime );
}
});
if ( specificMimes.length > 0 ) {
mime = specificMimes;
}
this.states.add([
// Main states.
new component.PersistentDisplaySettingsLibrary({
id: 'insert',
title: this.options.title,
selection: this.options.selection,
priority: 20,
toolbar: 'main-insert',
filterable: 'dates',
library: wp.media.query({
type: mime
}),
multiple: false,
editable: true,
selectedDisplaySettings: this.options.selectedDisplaySettings,
displaySettings: _.isUndefined( this.options.showDisplaySettings ) ? true : this.options.showDisplaySettings,
displayUserSettings: false // We use the display settings from the current/default widget instance props.
}),
new wp.media.controller.EditImage({ model: this.options.editImage }),
// Embed states.
new wp.media.controller.Embed({
metadata: this.options.metadata,
type: 'image' === this.options.mimeType ? 'image' : 'link',
invalidEmbedTypeError: this.options.invalidEmbedTypeError
})
]);
},
/**
* Main insert toolbar.
*
* Forked override of {wp.media.view.MediaFrame.Post#mainInsertToolbar()} to override text.
*
* @param {wp.Backbone.View} view - Toolbar view.
* @this {wp.media.controller.Library}
* @return {void}
*/
mainInsertToolbar: function mainInsertToolbar( view ) {
var controller = this; // eslint-disable-line consistent-this
view.set( 'insert', {
style: 'primary',
priority: 80,
text: controller.options.text, // The whole reason for the fork.
requires: { selection: true },
/**
* Handle click.
*
* @ignore
*
* @fires wp.media.controller.State#insert()
* @return {void}
*/
click: function onClick() {
var state = controller.state(),
selection = state.get( 'selection' );
controller.close();
state.trigger( 'insert', selection ).reset();
}
});
},
/**
* Main embed toolbar.
*
* Forked override of {wp.media.view.MediaFrame.Post#mainEmbedToolbar()} to override text.
*
* @param {wp.Backbone.View} toolbar - Toolbar view.
* @this {wp.media.controller.Library}
* @return {void}
*/
mainEmbedToolbar: function mainEmbedToolbar( toolbar ) {
toolbar.view = new wp.media.view.Toolbar.Embed({
controller: this,
text: this.options.text,
event: 'insert'
});
},
/**
* Embed content.
*
* Forked override of {wp.media.view.MediaFrame.Post#embedContent()} to suppress irrelevant "link text" field.
*
* @return {void}
*/
embedContent: function embedContent() {
var view = new component.MediaEmbedView({
controller: this,
model: this.state()
}).render();
this.content.set( view );
}
});
component.MediaWidgetControl = Backbone.View.extend(/** @lends wp.mediaWidgets.MediaWidgetControl.prototype */{
/**
* Translation strings.
*
* The mapping of translation strings is handled by media widget subclasses,
* exported from PHP to JS such as is done in WP_Widget_Media_Image::enqueue_admin_scripts().
*
* @type {Object}
*/
l10n: {
add_to_widget: '{{add_to_widget}}',
add_media: '{{add_media}}'
},
/**
* Widget ID base.
*
* This may be defined by the subclass. It may be exported from PHP to JS
* such as is done in WP_Widget_Media_Image::enqueue_admin_scripts(). If not,
* it will attempt to be discovered by looking to see if this control
* instance extends each member of component.controlConstructors, and if
* it does extend one, will use the key as the id_base.
*
* @type {string}
*/
id_base: '',
/**
* Mime type.
*
* This must be defined by the subclass. It may be exported from PHP to JS
* such as is done in WP_Widget_Media_Image::enqueue_admin_scripts().
*
* @type {string}
*/
mime_type: '',
/**
* View events.
*
* @type {Object}
*/
events: {
'click .notice-missing-attachment a': 'handleMediaLibraryLinkClick',
'click .select-media': 'selectMedia',
'click .placeholder': 'selectMedia',
'click .edit-media': 'editMedia'
},
/**
* Show display settings.
*
* @type {boolean}
*/
showDisplaySettings: true,
/**
* Media Widget Control.
*
* @constructs wp.mediaWidgets.MediaWidgetControl
* @augments Backbone.View
* @abstract
*
* @param {Object} options - Options.
* @param {Backbone.Model} options.model - Model.
* @param {jQuery} options.el - Control field container element.
* @param {jQuery} options.syncContainer - Container element where fields are synced for the server.
*
* @return {void}
*/
initialize: function initialize( options ) {
var control = this;
Backbone.View.prototype.initialize.call( control, options );
if ( ! ( control.model instanceof component.MediaWidgetModel ) ) {
throw new Error( 'Missing options.model' );
}
if ( ! options.el ) {
throw new Error( 'Missing options.el' );
}
if ( ! options.syncContainer ) {
throw new Error( 'Missing options.syncContainer' );
}
control.syncContainer = options.syncContainer;
control.$el.addClass( 'media-widget-control' );
// Allow methods to be passed in with control context preserved.
_.bindAll( control, 'syncModelToInputs', 'render', 'updateSelectedAttachment', 'renderPreview' );
if ( ! control.id_base ) {
_.find( component.controlConstructors, function( Constructor, idBase ) {
if ( control instanceof Constructor ) {
control.id_base = idBase;
return true;
}
return false;
});
if ( ! control.id_base ) {
throw new Error( 'Missing id_base.' );
}
}
// Track attributes needed to renderPreview in it's own model.
control.previewTemplateProps = new Backbone.Model( control.mapModelToPreviewTemplateProps() );
// Re-render the preview when the attachment changes.
control.selectedAttachment = new wp.media.model.Attachment();
control.renderPreview = _.debounce( control.renderPreview );
control.listenTo( control.previewTemplateProps, 'change', control.renderPreview );
// Make sure a copy of the selected attachment is always fetched.
control.model.on( 'change:attachment_id', control.updateSelectedAttachment );
control.model.on( 'change:url', control.updateSelectedAttachment );
control.updateSelectedAttachment();
/*
* Sync the widget instance model attributes onto the hidden inputs that widgets currently use to store the state.
* In the future, when widgets are JS-driven, the underlying widget instance data should be exposed as a model
* from the start, without having to sync with hidden fields. See <https://core.trac.wordpress.org/ticket/33507>.
*/
control.listenTo( control.model, 'change', control.syncModelToInputs );
control.listenTo( control.model, 'change', control.syncModelToPreviewProps );
control.listenTo( control.model, 'change', control.render );
// Update the title.
control.$el.on( 'input change', '.title', function updateTitle() {
control.model.set({
title: $( this ).val().trim()
});
});
// Update link_url attribute.
control.$el.on( 'input change', '.link', function updateLinkUrl() {
var linkUrl = $( this ).val().trim(), linkType = 'custom';
if ( control.selectedAttachment.get( 'linkUrl' ) === linkUrl || control.selectedAttachment.get( 'link' ) === linkUrl ) {
linkType = 'post';
} else if ( control.selectedAttachment.get( 'url' ) === linkUrl ) {
linkType = 'file';
}
control.model.set( {
link_url: linkUrl,
link_type: linkType
});
// Update display settings for the next time the user opens to select from the media library.
control.displaySettings.set( {
link: linkType,
linkUrl: linkUrl
});
});
/*
* Copy current display settings from the widget model to serve as basis
* of customized display settings for the current media frame session.
* Changes to display settings will be synced into this model, and
* when a new selection is made, the settings from this will be synced
* into that AttachmentDisplay's model to persist the setting changes.
*/
control.displaySettings = new Backbone.Model( _.pick(
control.mapModelToMediaFrameProps(
_.extend( control.model.defaults(), control.model.toJSON() )
),
_.keys( wp.media.view.settings.defaultProps )
) );
},
/**
* Update the selected attachment if necessary.
*
* @return {void}
*/
updateSelectedAttachment: function updateSelectedAttachment() {
var control = this, attachment;
if ( 0 === control.model.get( 'attachment_id' ) ) {
control.selectedAttachment.clear();
control.model.set( 'error', false );
} else if ( control.model.get( 'attachment_id' ) !== control.selectedAttachment.get( 'id' ) ) {
attachment = new wp.media.model.Attachment({
id: control.model.get( 'attachment_id' )
});
attachment.fetch()
.done( function done() {
control.model.set( 'error', false );
control.selectedAttachment.set( attachment.toJSON() );
})
.fail( function fail() {
control.model.set( 'error', 'missing_attachment' );
});
}
},
/**
* Sync the model attributes to the hidden inputs, and update previewTemplateProps.
*
* @return {void}
*/
syncModelToPreviewProps: function syncModelToPreviewProps() {
var control = this;
control.previewTemplateProps.set( control.mapModelToPreviewTemplateProps() );
},
/**
* Sync the model attributes to the hidden inputs, and update previewTemplateProps.
*
* @return {void}
*/
syncModelToInputs: function syncModelToInputs() {
var control = this;
control.syncContainer.find( '.media-widget-instance-property' ).each( function() {
var input = $( this ), value, propertyName;
propertyName = input.data( 'property' );
value = control.model.get( propertyName );
if ( _.isUndefined( value ) ) {
return;
}
if ( 'array' === control.model.schema[ propertyName ].type && _.isArray( value ) ) {
value = value.join( ',' );
} else if ( 'boolean' === control.model.schema[ propertyName ].type ) {
value = value ? '1' : ''; // Because in PHP, strval( true ) === '1' && strval( false ) === ''.
} else {
value = String( value );
}
if ( input.val() !== value ) {
input.val( value );
input.trigger( 'change' );
}
});
},
/**
* Get template.
*
* @return {Function} Template.
*/
template: function template() {
var control = this;
if ( ! $( '#tmpl-widget-media-' + control.id_base + '-control' ).length ) {
throw new Error( 'Missing widget control template for ' + control.id_base );
}
return wp.template( 'widget-media-' + control.id_base + '-control' );
},
/**
* Render template.
*
* @return {void}
*/
render: function render() {
var control = this, titleInput;
if ( ! control.templateRendered ) {
control.$el.html( control.template()( control.model.toJSON() ) );
control.renderPreview(); // Hereafter it will re-render when control.selectedAttachment changes.
control.templateRendered = true;
}
titleInput = control.$el.find( '.title' );
if ( ! titleInput.is( document.activeElement ) ) {
titleInput.val( control.model.get( 'title' ) );
}
control.$el.toggleClass( 'selected', control.isSelected() );
},
/**
* Render media preview.
*
* @abstract
* @return {void}
*/
renderPreview: function renderPreview() {
throw new Error( 'renderPreview must be implemented' );
},
/**
* Whether a media item is selected.
*
* @return {boolean} Whether selected and no error.
*/
isSelected: function isSelected() {
var control = this;
if ( control.model.get( 'error' ) ) {
return false;
}
return Boolean( control.model.get( 'attachment_id' ) || control.model.get( 'url' ) );
},
/**
* Handle click on link to Media Library to open modal, such as the link that appears when in the missing attachment error notice.
*
* @param {jQuery.Event} event - Event.
* @return {void}
*/
handleMediaLibraryLinkClick: function handleMediaLibraryLinkClick( event ) {
var control = this;
event.preventDefault();
control.selectMedia();
},
/**
* Open the media select frame to chose an item.
*
* @return {void}
*/
selectMedia: function selectMedia() {
var control = this, selection, mediaFrame, defaultSync, mediaFrameProps, selectionModels = [];
if ( control.isSelected() && 0 !== control.model.get( 'attachment_id' ) ) {
selectionModels.push( control.selectedAttachment );
}
selection = new wp.media.model.Selection( selectionModels, { multiple: false } );
mediaFrameProps = control.mapModelToMediaFrameProps( control.model.toJSON() );
if ( mediaFrameProps.size ) {
control.displaySettings.set( 'size', mediaFrameProps.size );
}
mediaFrame = new component.MediaFrameSelect({
title: control.l10n.add_media,
frame: 'post',
text: control.l10n.add_to_widget,
selection: selection,
mimeType: control.mime_type,
selectedDisplaySettings: control.displaySettings,
showDisplaySettings: control.showDisplaySettings,
metadata: mediaFrameProps,
state: control.isSelected() && 0 === control.model.get( 'attachment_id' ) ? 'embed' : 'insert',
invalidEmbedTypeError: control.l10n.unsupported_file_type
});
wp.media.frame = mediaFrame; // See wp.media().
// Handle selection of a media item.
mediaFrame.on( 'insert', function onInsert() {
var attachment = {}, state = mediaFrame.state();
// Update cached attachment object to avoid having to re-fetch. This also triggers re-rendering of preview.
if ( 'embed' === state.get( 'id' ) ) {
_.extend( attachment, { id: 0 }, state.props.toJSON() );
} else {
_.extend( attachment, state.get( 'selection' ).first().toJSON() );
}
control.selectedAttachment.set( attachment );
control.model.set( 'error', false );
// Update widget instance.
control.model.set( control.getModelPropsFromMediaFrame( mediaFrame ) );
});
// Disable syncing of attachment changes back to server (except for deletions). See <https://core.trac.wordpress.org/ticket/40403>.
defaultSync = wp.media.model.Attachment.prototype.sync;
wp.media.model.Attachment.prototype.sync = function( method ) {
if ( 'delete' === method ) {
return defaultSync.apply( this, arguments );
} else {
return $.Deferred().rejectWith( this ).promise();
}
};
mediaFrame.on( 'close', function onClose() {
wp.media.model.Attachment.prototype.sync = defaultSync;
});
mediaFrame.$el.addClass( 'media-widget' );
mediaFrame.open();
// Clear the selected attachment when it is deleted in the media select frame.
if ( selection ) {
selection.on( 'destroy', function onDestroy( attachment ) {
if ( control.model.get( 'attachment_id' ) === attachment.get( 'id' ) ) {
control.model.set({
attachment_id: 0,
url: ''
});
}
});
}
/*
* Make sure focus is set inside of modal so that hitting Esc will close
* the modal and not inadvertently cause the widget to collapse in the customizer.
*/
mediaFrame.$el.find( '.media-frame-menu .media-menu-item.active' ).focus();
},
/**
* Get the instance props from the media selection frame.
*
* @param {wp.media.view.MediaFrame.Select} mediaFrame - Select frame.
* @return {Object} Props.
*/
getModelPropsFromMediaFrame: function getModelPropsFromMediaFrame( mediaFrame ) {
var control = this, state, mediaFrameProps, modelProps;
state = mediaFrame.state();
if ( 'insert' === state.get( 'id' ) ) {
mediaFrameProps = state.get( 'selection' ).first().toJSON();
mediaFrameProps.postUrl = mediaFrameProps.link;
if ( control.showDisplaySettings ) {
_.extend(
mediaFrameProps,
mediaFrame.content.get( '.attachments-browser' ).sidebar.get( 'display' ).model.toJSON()
);
}
if ( mediaFrameProps.sizes && mediaFrameProps.size && mediaFrameProps.sizes[ mediaFrameProps.size ] ) {
mediaFrameProps.url = mediaFrameProps.sizes[ mediaFrameProps.size ].url;
}
} else if ( 'embed' === state.get( 'id' ) ) {
mediaFrameProps = _.extend(
state.props.toJSON(),
{ attachment_id: 0 }, // Because some media frames use `attachment_id` not `id`.
control.model.getEmbedResetProps()
);
} else {
throw new Error( 'Unexpected state: ' + state.get( 'id' ) );
}
if ( mediaFrameProps.id ) {
mediaFrameProps.attachment_id = mediaFrameProps.id;
}
modelProps = control.mapMediaToModelProps( mediaFrameProps );
// Clear the extension prop so sources will be reset for video and audio media.
_.each( wp.media.view.settings.embedExts, function( ext ) {
if ( ext in control.model.schema && modelProps.url !== modelProps[ ext ] ) {
modelProps[ ext ] = '';
}
});
return modelProps;
},
/**
* Map media frame props to model props.
*
* @param {Object} mediaFrameProps - Media frame props.
* @return {Object} Model props.
*/
mapMediaToModelProps: function mapMediaToModelProps( mediaFrameProps ) {
var control = this, mediaFramePropToModelPropMap = {}, modelProps = {}, extension;
_.each( control.model.schema, function( fieldSchema, modelProp ) {
// Ignore widget title attribute.
if ( 'title' === modelProp ) {
return;
}
mediaFramePropToModelPropMap[ fieldSchema.media_prop || modelProp ] = modelProp;
});
_.each( mediaFrameProps, function( value, mediaProp ) {
var propName = mediaFramePropToModelPropMap[ mediaProp ] || mediaProp;
if ( control.model.schema[ propName ] ) {
modelProps[ propName ] = value;
}
});
if ( 'custom' === mediaFrameProps.size ) {
modelProps.width = mediaFrameProps.customWidth;
modelProps.height = mediaFrameProps.customHeight;
}
if ( 'post' === mediaFrameProps.link ) {
modelProps.link_url = mediaFrameProps.postUrl || mediaFrameProps.linkUrl;
} else if ( 'file' === mediaFrameProps.link ) {
modelProps.link_url = mediaFrameProps.url;
}
// Because some media frames use `id` instead of `attachment_id`.
if ( ! mediaFrameProps.attachment_id && mediaFrameProps.id ) {
modelProps.attachment_id = mediaFrameProps.id;
}
if ( mediaFrameProps.url ) {
extension = mediaFrameProps.url.replace( /#.*$/, '' ).replace( /\?.*$/, '' ).split( '.' ).pop().toLowerCase();
if ( extension in control.model.schema ) {
modelProps[ extension ] = mediaFrameProps.url;
}
}
// Always omit the titles derived from mediaFrameProps.
return _.omit( modelProps, 'title' );
},
/**
* Map model props to media frame props.
*
* @param {Object} modelProps - Model props.
* @return {Object} Media frame props.
*/
mapModelToMediaFrameProps: function mapModelToMediaFrameProps( modelProps ) {
var control = this, mediaFrameProps = {};
_.each( modelProps, function( value, modelProp ) {
var fieldSchema = control.model.schema[ modelProp ] || {};
mediaFrameProps[ fieldSchema.media_prop || modelProp ] = value;
});
// Some media frames use attachment_id.
mediaFrameProps.attachment_id = mediaFrameProps.id;
if ( 'custom' === mediaFrameProps.size ) {
mediaFrameProps.customWidth = control.model.get( 'width' );
mediaFrameProps.customHeight = control.model.get( 'height' );
}
return mediaFrameProps;
},
/**
* Map model props to previewTemplateProps.
*
* @return {Object} Preview Template Props.
*/
mapModelToPreviewTemplateProps: function mapModelToPreviewTemplateProps() {
var control = this, previewTemplateProps = {};
_.each( control.model.schema, function( value, prop ) {
if ( ! value.hasOwnProperty( 'should_preview_update' ) || value.should_preview_update ) {
previewTemplateProps[ prop ] = control.model.get( prop );
}
});
// Templates need to be aware of the error.
previewTemplateProps.error = control.model.get( 'error' );
return previewTemplateProps;
},
/**
* Open the media frame to modify the selected item.
*
* @abstract
* @return {void}
*/
editMedia: function editMedia() {
throw new Error( 'editMedia not implemented' );
}
});
/**
* Media widget model.
*
* @class wp.mediaWidgets.MediaWidgetModel
* @augments Backbone.Model
*/
component.MediaWidgetModel = Backbone.Model.extend(/** @lends wp.mediaWidgets.MediaWidgetModel.prototype */{
/**
* Id attribute.
*
* @type {string}
*/
idAttribute: 'widget_id',
/**
* Instance schema.
*
* This adheres to JSON Schema and subclasses should have their schema
* exported from PHP to JS such as is done in WP_Widget_Media_Image::enqueue_admin_scripts().
*
* @type {Object.<string, Object>}
*/
schema: {
title: {
type: 'string',
'default': ''
},
attachment_id: {
type: 'integer',
'default': 0
},
url: {
type: 'string',
'default': ''
}
},
/**
* Get default attribute values.
*
* @return {Object} Mapping of property names to their default values.
*/
defaults: function() {
var defaults = {};
_.each( this.schema, function( fieldSchema, field ) {
defaults[ field ] = fieldSchema['default'];
});
return defaults;
},
/**
* Set attribute value(s).
*
* This is a wrapped version of Backbone.Model#set() which allows us to
* cast the attribute values from the hidden inputs' string values into
* the appropriate data types (integers or booleans).
*
* @param {string|Object} key - Attribute name or attribute pairs.
* @param {mixed|Object} [val] - Attribute value or options object.
* @param {Object} [options] - Options when attribute name and value are passed separately.
* @return {wp.mediaWidgets.MediaWidgetModel} This model.
*/
set: function set( key, val, options ) {
var model = this, attrs, opts, castedAttrs; // eslint-disable-line consistent-this
if ( null === key ) {
return model;
}
if ( 'object' === typeof key ) {
attrs = key;
opts = val;
} else {
attrs = {};
attrs[ key ] = val;
opts = options;
}
castedAttrs = {};
_.each( attrs, function( value, name ) {
var type;
if ( ! model.schema[ name ] ) {
castedAttrs[ name ] = value;
return;
}
type = model.schema[ name ].type;
if ( 'array' === type ) {
castedAttrs[ name ] = value;
if ( ! _.isArray( castedAttrs[ name ] ) ) {
castedAttrs[ name ] = castedAttrs[ name ].split( /,/ ); // Good enough for parsing an ID list.
}
if ( model.schema[ name ].items && 'integer' === model.schema[ name ].items.type ) {
castedAttrs[ name ] = _.filter(
_.map( castedAttrs[ name ], function( id ) {
return parseInt( id, 10 );
},
function( id ) {
return 'number' === typeof id;
}
) );
}
} else if ( 'integer' === type ) {
castedAttrs[ name ] = parseInt( value, 10 );
} else if ( 'boolean' === type ) {
castedAttrs[ name ] = ! ( ! value || '0' === value || 'false' === value );
} else {
castedAttrs[ name ] = value;
}
});
return Backbone.Model.prototype.set.call( this, castedAttrs, opts );
},
/**
* Get props which are merged on top of the model when an embed is chosen (as opposed to an attachment).
*
* @return {Object} Reset/override props.
*/
getEmbedResetProps: function getEmbedResetProps() {
return {
id: 0
};
}
});
/**
* Collection of all widget model instances.
*
* @memberOf wp.mediaWidgets
*
* @type {Backbone.Collection}
*/
component.modelCollection = new ( Backbone.Collection.extend( {
model: component.MediaWidgetModel
}) )();
/**
* Mapping of widget ID to instances of MediaWidgetControl subclasses.
*
* @memberOf wp.mediaWidgets
*
* @type {Object.<string, wp.mediaWidgets.MediaWidgetControl>}
*/
component.widgetControls = {};
/**
* Handle widget being added or initialized for the first time at the widget-added event.
*
* @memberOf wp.mediaWidgets
*
* @param {jQuery.Event} event - Event.
* @param {jQuery} widgetContainer - Widget container element.
*
* @return {void}
*/
component.handleWidgetAdded = function handleWidgetAdded( event, widgetContainer ) {
var fieldContainer, syncContainer, widgetForm, idBase, ControlConstructor, ModelConstructor, modelAttributes, widgetControl, widgetModel, widgetId, animatedCheckDelay = 50, renderWhenAnimationDone;
widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' ); // Note: '.form' appears in the customizer, whereas 'form' on the widgets admin screen.
idBase = widgetForm.find( '> .id_base' ).val();
widgetId = widgetForm.find( '> .widget-id' ).val();
// Prevent initializing already-added widgets.
if ( component.widgetControls[ widgetId ] ) {
return;
}
ControlConstructor = component.controlConstructors[ idBase ];
if ( ! ControlConstructor ) {
return;
}
ModelConstructor = component.modelConstructors[ idBase ] || component.MediaWidgetModel;
/*
* Create a container element for the widget control (Backbone.View).
* This is inserted into the DOM immediately before the .widget-content
* element because the contents of this element are essentially "managed"
* by PHP, where each widget update cause the entire element to be emptied
* and replaced with the rendered output of WP_Widget::form() which is
* sent back in Ajax request made to save/update the widget instance.
* To prevent a "flash of replaced DOM elements and re-initialized JS
* components", the JS template is rendered outside of the normal form
* container.
*/
fieldContainer = $( '<div></div>' );
syncContainer = widgetContainer.find( '.widget-content:first' );
syncContainer.before( fieldContainer );
/*
* Sync the widget instance model attributes onto the hidden inputs that widgets currently use to store the state.
* In the future, when widgets are JS-driven, the underlying widget instance data should be exposed as a model
* from the start, without having to sync with hidden fields. See <https://core.trac.wordpress.org/ticket/33507>.
*/
modelAttributes = {};
syncContainer.find( '.media-widget-instance-property' ).each( function() {
var input = $( this );
modelAttributes[ input.data( 'property' ) ] = input.val();
});
modelAttributes.widget_id = widgetId;
widgetModel = new ModelConstructor( modelAttributes );
widgetControl = new ControlConstructor({
el: fieldContainer,
syncContainer: syncContainer,
model: widgetModel
});
/*
* Render the widget once the widget parent's container finishes animating,
* as the widget-added event fires with a slideDown of the container.
* This ensures that the container's dimensions are fixed so that ME.js
* can initialize with the proper dimensions.
*/
renderWhenAnimationDone = function() {
if ( ! widgetContainer.hasClass( 'open' ) ) {
setTimeout( renderWhenAnimationDone, animatedCheckDelay );
} else {
widgetControl.render();
}
};
renderWhenAnimationDone();
/*
* Note that the model and control currently won't ever get garbage-collected
* when a widget gets removed/deleted because there is no widget-removed event.
*/
component.modelCollection.add( [ widgetModel ] );
component.widgetControls[ widgetModel.get( 'widget_id' ) ] = widgetControl;
};
/**
* Setup widget in accessibility mode.
*
* @memberOf wp.mediaWidgets
*
* @return {void}
*/
component.setupAccessibleMode = function setupAccessibleMode() {
var widgetForm, widgetId, idBase, widgetControl, ControlConstructor, ModelConstructor, modelAttributes, fieldContainer, syncContainer;
widgetForm = $( '.editwidget > form' );
if ( 0 === widgetForm.length ) {
return;
}
idBase = widgetForm.find( '.id_base' ).val();
ControlConstructor = component.controlConstructors[ idBase ];
if ( ! ControlConstructor ) {
return;
}
widgetId = widgetForm.find( '> .widget-control-actions > .widget-id' ).val();
ModelConstructor = component.modelConstructors[ idBase ] || component.MediaWidgetModel;
fieldContainer = $( '<div></div>' );
syncContainer = widgetForm.find( '> .widget-inside' );
syncContainer.before( fieldContainer );
modelAttributes = {};
syncContainer.find( '.media-widget-instance-property' ).each( function() {
var input = $( this );
modelAttributes[ input.data( 'property' ) ] = input.val();
});
modelAttributes.widget_id = widgetId;
widgetControl = new ControlConstructor({
el: fieldContainer,
syncContainer: syncContainer,
model: new ModelConstructor( modelAttributes )
});
component.modelCollection.add( [ widgetControl.model ] );
component.widgetControls[ widgetControl.model.get( 'widget_id' ) ] = widgetControl;
widgetControl.render();
};
/**
* Sync widget instance data sanitized from server back onto widget model.
*
* This gets called via the 'widget-updated' event when saving a widget from
* the widgets admin screen and also via the 'widget-synced' event when making
* a change to a widget in the customizer.
*
* @memberOf wp.mediaWidgets
*
* @param {jQuery.Event} event - Event.
* @param {jQuery} widgetContainer - Widget container element.
*
* @return {void}
*/
component.handleWidgetUpdated = function handleWidgetUpdated( event, widgetContainer ) {
var widgetForm, widgetContent, widgetId, widgetControl, attributes = {};
widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' );
widgetId = widgetForm.find( '> .widget-id' ).val();
widgetControl = component.widgetControls[ widgetId ];
if ( ! widgetControl ) {
return;
}
// Make sure the server-sanitized values get synced back into the model.
widgetContent = widgetForm.find( '> .widget-content' );
widgetContent.find( '.media-widget-instance-property' ).each( function() {
var property = $( this ).data( 'property' );
attributes[ property ] = $( this ).val();
});
// Suspend syncing model back to inputs when syncing from inputs to model, preventing infinite loop.
widgetControl.stopListening( widgetControl.model, 'change', widgetControl.syncModelToInputs );
widgetControl.model.set( attributes );
widgetControl.listenTo( widgetControl.model, 'change', widgetControl.syncModelToInputs );
};
/**
* Initialize functionality.
*
* This function exists to prevent the JS file from having to boot itself.
* When WordPress enqueues this script, it should have an inline script
* attached which calls wp.mediaWidgets.init().
*
* @memberOf wp.mediaWidgets
*
* @return {void}
*/
component.init = function init() {
var $document = $( document );
$document.on( 'widget-added', component.handleWidgetAdded );
$document.on( 'widget-synced widget-updated', component.handleWidgetUpdated );
/*
* Manually trigger widget-added events for media widgets on the admin
* screen once they are expanded. The widget-added event is not triggered
* for each pre-existing widget on the widgets admin screen like it is
* on the customizer. Likewise, the customizer only triggers widget-added
* when the widget is expanded to just-in-time construct the widget form
* when it is actually going to be displayed. So the following implements
* the same for the widgets admin screen, to invoke the widget-added
* handler when a pre-existing media widget is expanded.
*/
$( function initializeExistingWidgetContainers() {
var widgetContainers;
if ( 'widgets' !== window.pagenow ) {
return;
}
widgetContainers = $( '.widgets-holder-wrap:not(#available-widgets)' ).find( 'div.widget' );
widgetContainers.one( 'click.toggle-widget-expanded', function toggleWidgetExpanded() {
var widgetContainer = $( this );
component.handleWidgetAdded( new jQuery.Event( 'widget-added' ), widgetContainer );
});
// Accessibility mode.
if ( document.readyState === 'complete' ) {
// Page is fully loaded.
component.setupAccessibleMode();
} else {
// Page is still loading.
$( window ).on( 'load', function() {
component.setupAccessibleMode();
});
}
});
};
return component;
})( jQuery );
PK �8FZ�Y� � � media-gallery-widget.min.jsnu �[��� /*! This file is auto-generated */
!function(i){"use strict";var a=wp.media.view.MediaFrame.Post.extend({createStates:function(){this.states.add([new wp.media.controller.Library({id:"gallery",title:wp.media.view.l10n.createGalleryTitle,priority:40,toolbar:"main-gallery",filterable:"uploaded",multiple:"add",editable:!0,library:wp.media.query(_.defaults({type:"image"},this.options.library))}),new wp.media.controller.GalleryEdit({library:this.options.selection,editing:this.options.editing,menu:"gallery"}),new wp.media.controller.GalleryAdd])}}),e=i.MediaWidgetModel.extend({}),t=i.MediaWidgetControl.extend({events:_.extend({},i.MediaWidgetControl.prototype.events,{"click .media-widget-gallery-preview":"editMedia"}),initialize:function(e){var t=this;i.MediaWidgetControl.prototype.initialize.call(t,e),_.bindAll(t,"updateSelectedAttachments","handleAttachmentDestroy"),t.selectedAttachments=new wp.media.model.Attachments,t.model.on("change:ids",t.updateSelectedAttachments),t.selectedAttachments.on("change",t.renderPreview),t.selectedAttachments.on("reset",t.renderPreview),t.updateSelectedAttachments(),wp.customize&&wp.customize.previewer&&t.selectedAttachments.on("change",function(){wp.customize.previewer.send("refresh-widget-partial",t.model.get("widget_id"))})},updateSelectedAttachments:function(){var e,t=this,i=t.model.get("ids"),d=_.pluck(t.selectedAttachments.models,"id"),a=_.difference(d,i);_.each(a,function(e){t.selectedAttachments.remove(t.selectedAttachments.get(e))}),_.difference(i,d).length&&(e=wp.media.query({order:"ASC",orderby:"post__in",perPage:-1,post__in:i,query:!0,type:"image"})).more().done(function(){t.selectedAttachments.reset(e.models)})},renderPreview:function(){var e=this,t=e.$el.find(".media-widget-preview"),i=wp.template("wp-media-widget-gallery-preview"),d=e.previewTemplateProps.toJSON();d.attachments={},e.selectedAttachments.each(function(e){d.attachments[e.id]=e.toJSON()}),t.html(i(d))},isSelected:function(){return!this.model.get("error")&&0<this.model.get("ids").length},editMedia:function(){var i,d=this,e=new wp.media.model.Selection(d.selectedAttachments.models,{multiple:!0}),t=d.mapModelToMediaFrameProps(d.model.toJSON());e.gallery=new Backbone.Model(t),t.size&&d.displaySettings.set("size",t.size),i=new a({frame:"manage",text:d.l10n.add_to_widget,selection:e,mimeType:d.mime_type,selectedDisplaySettings:d.displaySettings,showDisplaySettings:d.showDisplaySettings,metadata:t,editing:!0,multiple:!0,state:"gallery-edit"}),(wp.media.frame=i).on("update",function(e){var t=i.state(),e=e||t.get("selection");e&&(e.gallery&&d.model.set(d.mapMediaToModelProps(e.gallery.toJSON())),d.selectedAttachments.reset(e.models),d.model.set({ids:_.pluck(e.models,"id")}))}),i.$el.addClass("media-widget"),i.open(),e&&e.on("destroy",d.handleAttachmentDestroy)},selectMedia:function(){var i,d=this,e=new wp.media.model.Selection(d.selectedAttachments.models,{multiple:!0}),t=d.mapModelToMediaFrameProps(d.model.toJSON());t.size&&d.displaySettings.set("size",t.size),i=new a({frame:"select",text:d.l10n.add_to_widget,selection:e,mimeType:d.mime_type,selectedDisplaySettings:d.displaySettings,showDisplaySettings:d.showDisplaySettings,metadata:t,state:"gallery"}),(wp.media.frame=i).on("update",function(e){var t=i.state(),e=e||t.get("selection");e&&(e.gallery&&d.model.set(d.mapMediaToModelProps(e.gallery.toJSON())),d.selectedAttachments.reset(e.models),d.model.set({ids:_.pluck(e.models,"id")}))}),i.$el.addClass("media-widget"),i.open(),e&&e.on("destroy",d.handleAttachmentDestroy),i.$el.find(":focusable:first").focus()},handleAttachmentDestroy:function(e){this.model.set({ids:_.difference(this.model.get("ids"),[e.id])})}});i.controlConstructors.media_gallery=t,i.modelConstructors.media_gallery=e}(wp.mediaWidgets);PK �8FZ8v�\ \ media-image-widget.jsnu �[��� /**
* @output wp-admin/js/widgets/media-image-widget.js
*/
/* 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 wp.mediaWidgets.modelConstructors.media_image
* @augments wp.mediaWidgets.MediaWidgetModel
*/
ImageWidgetModel = component.MediaWidgetModel.extend({});
/**
* Image widget control.
*
* See WP_Widget_Media_Image::enqueue_admin_scripts() for amending prototype from PHP exports.
*
* @class wp.mediaWidgets.controlConstructors.media_audio
* @augments wp.mediaWidgets.MediaWidgetControl
*/
ImageWidgetControl = component.MediaWidgetControl.extend(/** @lends wp.mediaWidgets.controlConstructors.media_image.prototype */{
/**
* View events.
*
* @type {object}
*/
events: _.extend( {}, component.MediaWidgetControl.prototype.events, {
'click .media-widget-preview.populated': 'editMedia'
} ),
/**
* Render preview.
*
* @return {void}
*/
renderPreview: function renderPreview() {
var control = this, previewContainer, previewTemplate, fieldsContainer, fieldsTemplate, linkInput;
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( control.previewTemplateProps.toJSON() ) );
previewContainer.addClass( 'populated' );
linkInput = control.$el.find( '.link' );
if ( ! linkInput.is( document.activeElement ) ) {
fieldsContainer = control.$el.find( '.media-widget-fields' );
fieldsTemplate = wp.template( 'wp-media-widget-image-fields' );
fieldsContainer.html( fieldsTemplate( control.previewTemplateProps.toJSON() ) );
}
},
/**
* Open the media image-edit frame to modify the selected item.
*
* @return {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, linkType;
// Update cached attachment object to avoid having to re-fetch. This also triggers re-rendering of preview.
mediaProps = mediaFrame.state().attributes.image.toJSON();
linkType = mediaProps.link;
mediaProps.link = mediaProps.linkUrl;
control.selectedAttachment.set( mediaProps );
control.displaySettings.set( 'link', linkType );
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).
*
* @return {Object} Reset/override props.
*/
getEmbedResetProps: function getEmbedResetProps() {
return _.extend(
component.MediaWidgetControl.prototype.getEmbedResetProps.call( this ),
{
size: 'full',
width: 0,
height: 0
}
);
},
/**
* Get the instance props from the media selection frame.
*
* Prevent the image_title attribute from being initially set when adding an image from the media library.
*
* @param {wp.media.view.MediaFrame.Select} mediaFrame - Select frame.
* @return {Object} Props.
*/
getModelPropsFromMediaFrame: function getModelPropsFromMediaFrame( mediaFrame ) {
var control = this;
return _.omit(
component.MediaWidgetControl.prototype.getModelPropsFromMediaFrame.call( control, mediaFrame ),
'image_title'
);
},
/**
* Map model props to preview template props.
*
* @return {Object} Preview template props.
*/
mapModelToPreviewTemplateProps: function mapModelToPreviewTemplateProps() {
var control = this, previewTemplateProps, url;
url = control.model.get( 'url' );
previewTemplateProps = component.MediaWidgetControl.prototype.mapModelToPreviewTemplateProps.call( control );
previewTemplateProps.currentFilename = url ? url.replace( /\?.*$/, '' ).replace( /^.+\//, '' ) : '';
previewTemplateProps.link_url = control.model.get( 'link_url' );
return previewTemplateProps;
}
});
// Exports.
component.controlConstructors.media_image = ImageWidgetControl;
component.modelConstructors.media_image = ImageWidgetModel;
})( wp.mediaWidgets, jQuery );
PK �8FZ.�֛�= �= custom-html-widgets.jsnu �[��� /**
* @output wp-admin/js/widgets/custom-html-widgets.js
*/
/* global wp */
/* eslint consistent-this: [ "error", "control" ] */
/* eslint no-magic-numbers: ["error", { "ignore": [0,1,-1] }] */
/**
* @namespace wp.customHtmlWidget
* @memberOf wp
*/
wp.customHtmlWidgets = ( function( $ ) {
'use strict';
var component = {
idBases: [ 'custom_html' ],
codeEditorSettings: {},
l10n: {
errorNotice: {
singular: '',
plural: ''
}
}
};
component.CustomHtmlWidgetControl = Backbone.View.extend(/** @lends wp.customHtmlWidgets.CustomHtmlWidgetControl.prototype */{
/**
* View events.
*
* @type {Object}
*/
events: {},
/**
* Text widget control.
*
* @constructs wp.customHtmlWidgets.CustomHtmlWidgetControl
* @augments Backbone.View
* @abstract
*
* @param {Object} options - Options.
* @param {jQuery} options.el - Control field container element.
* @param {jQuery} options.syncContainer - Container element where fields are synced for the server.
*
* @return {void}
*/
initialize: function initialize( options ) {
var control = this;
if ( ! options.el ) {
throw new Error( 'Missing options.el' );
}
if ( ! options.syncContainer ) {
throw new Error( 'Missing options.syncContainer' );
}
Backbone.View.prototype.initialize.call( control, options );
control.syncContainer = options.syncContainer;
control.widgetIdBase = control.syncContainer.parent().find( '.id_base' ).val();
control.widgetNumber = control.syncContainer.parent().find( '.widget_number' ).val();
control.customizeSettingId = 'widget_' + control.widgetIdBase + '[' + String( control.widgetNumber ) + ']';
control.$el.addClass( 'custom-html-widget-fields' );
control.$el.html( wp.template( 'widget-custom-html-control-fields' )( { codeEditorDisabled: component.codeEditorSettings.disabled } ) );
control.errorNoticeContainer = control.$el.find( '.code-editor-error-container' );
control.currentErrorAnnotations = [];
control.saveButton = control.syncContainer.add( control.syncContainer.parent().find( '.widget-control-actions' ) ).find( '.widget-control-save, #savewidget' );
control.saveButton.addClass( 'custom-html-widget-save-button' ); // To facilitate style targeting.
control.fields = {
title: control.$el.find( '.title' ),
content: control.$el.find( '.content' )
};
// Sync input fields to hidden sync fields which actually get sent to the server.
_.each( control.fields, function( fieldInput, fieldName ) {
fieldInput.on( 'input change', function updateSyncField() {
var syncInput = control.syncContainer.find( '.sync-input.' + fieldName );
if ( syncInput.val() !== fieldInput.val() ) {
syncInput.val( fieldInput.val() );
syncInput.trigger( 'change' );
}
});
// Note that syncInput cannot be re-used because it will be destroyed with each widget-updated event.
fieldInput.val( control.syncContainer.find( '.sync-input.' + fieldName ).val() );
});
},
/**
* Update input fields from the sync fields.
*
* This function is called at the widget-updated and widget-synced events.
* A field will only be updated if it is not currently focused, to avoid
* overwriting content that the user is entering.
*
* @return {void}
*/
updateFields: function updateFields() {
var control = this, syncInput;
if ( ! control.fields.title.is( document.activeElement ) ) {
syncInput = control.syncContainer.find( '.sync-input.title' );
control.fields.title.val( syncInput.val() );
}
/*
* Prevent updating content when the editor is focused or if there are current error annotations,
* to prevent the editor's contents from getting sanitized as soon as a user removes focus from
* the editor. This is particularly important for users who cannot unfiltered_html.
*/
control.contentUpdateBypassed = control.fields.content.is( document.activeElement ) || control.editor && control.editor.codemirror.state.focused || 0 !== control.currentErrorAnnotations.length;
if ( ! control.contentUpdateBypassed ) {
syncInput = control.syncContainer.find( '.sync-input.content' );
control.fields.content.val( syncInput.val() );
}
},
/**
* Show linting error notice.
*
* @param {Array} errorAnnotations - Error annotations.
* @return {void}
*/
updateErrorNotice: function( errorAnnotations ) {
var control = this, errorNotice, message = '', customizeSetting;
if ( 1 === errorAnnotations.length ) {
message = component.l10n.errorNotice.singular.replace( '%d', '1' );
} else if ( errorAnnotations.length > 1 ) {
message = component.l10n.errorNotice.plural.replace( '%d', String( errorAnnotations.length ) );
}
if ( control.fields.content[0].setCustomValidity ) {
control.fields.content[0].setCustomValidity( message );
}
if ( wp.customize && wp.customize.has( control.customizeSettingId ) ) {
customizeSetting = wp.customize( control.customizeSettingId );
customizeSetting.notifications.remove( 'htmlhint_error' );
if ( 0 !== errorAnnotations.length ) {
customizeSetting.notifications.add( 'htmlhint_error', new wp.customize.Notification( 'htmlhint_error', {
message: message,
type: 'error'
} ) );
}
} else if ( 0 !== errorAnnotations.length ) {
errorNotice = $( '<div class="inline notice notice-error notice-alt" role="alert"></div>' );
errorNotice.append( $( '<p></p>', {
text: message
} ) );
control.errorNoticeContainer.empty();
control.errorNoticeContainer.append( errorNotice );
control.errorNoticeContainer.slideDown( 'fast' );
wp.a11y.speak( message );
} else {
control.errorNoticeContainer.slideUp( 'fast' );
}
},
/**
* Initialize editor.
*
* @return {void}
*/
initializeEditor: function initializeEditor() {
var control = this, settings;
if ( component.codeEditorSettings.disabled ) {
return;
}
settings = _.extend( {}, component.codeEditorSettings, {
/**
* Handle tabbing to the field before the editor.
*
* @ignore
*
* @return {void}
*/
onTabPrevious: function onTabPrevious() {
control.fields.title.focus();
},
/**
* Handle tabbing to the field after the editor.
*
* @ignore
*
* @return {void}
*/
onTabNext: function onTabNext() {
var tabbables = control.syncContainer.add( control.syncContainer.parent().find( '.widget-position, .widget-control-actions' ) ).find( ':tabbable' );
tabbables.first().focus();
},
/**
* Disable save button and store linting errors for use in updateFields.
*
* @ignore
*
* @param {Array} errorAnnotations - Error notifications.
* @return {void}
*/
onChangeLintingErrors: function onChangeLintingErrors( errorAnnotations ) {
control.currentErrorAnnotations = errorAnnotations;
},
/**
* Update error notice.
*
* @ignore
*
* @param {Array} errorAnnotations - Error annotations.
* @return {void}
*/
onUpdateErrorNotice: function onUpdateErrorNotice( errorAnnotations ) {
control.saveButton.toggleClass( 'validation-blocked disabled', errorAnnotations.length > 0 );
control.updateErrorNotice( errorAnnotations );
}
});
control.editor = wp.codeEditor.initialize( control.fields.content, settings );
// Improve the editor accessibility.
$( control.editor.codemirror.display.lineDiv )
.attr({
role: 'textbox',
'aria-multiline': 'true',
'aria-labelledby': control.fields.content[0].id + '-label',
'aria-describedby': 'editor-keyboard-trap-help-1 editor-keyboard-trap-help-2 editor-keyboard-trap-help-3 editor-keyboard-trap-help-4'
});
// Focus the editor when clicking on its label.
$( '#' + control.fields.content[0].id + '-label' ).on( 'click', function() {
control.editor.codemirror.focus();
});
control.fields.content.on( 'change', function() {
if ( this.value !== control.editor.codemirror.getValue() ) {
control.editor.codemirror.setValue( this.value );
}
});
control.editor.codemirror.on( 'change', function() {
var value = control.editor.codemirror.getValue();
if ( value !== control.fields.content.val() ) {
control.fields.content.val( value ).trigger( 'change' );
}
});
// Make sure the editor gets updated if the content was updated on the server (sanitization) but not updated in the editor since it was focused.
control.editor.codemirror.on( 'blur', function() {
if ( control.contentUpdateBypassed ) {
control.syncContainer.find( '.sync-input.content' ).trigger( 'change' );
}
});
// Prevent hitting Esc from collapsing the widget control.
if ( wp.customize ) {
control.editor.codemirror.on( 'keydown', function onKeydown( codemirror, event ) {
var escKeyCode = 27;
if ( escKeyCode === event.keyCode ) {
event.stopPropagation();
}
});
}
}
});
/**
* Mapping of widget ID to instances of CustomHtmlWidgetControl subclasses.
*
* @alias wp.customHtmlWidgets.widgetControls
*
* @type {Object.<string, wp.textWidgets.CustomHtmlWidgetControl>}
*/
component.widgetControls = {};
/**
* Handle widget being added or initialized for the first time at the widget-added event.
*
* @alias wp.customHtmlWidgets.handleWidgetAdded
*
* @param {jQuery.Event} event - Event.
* @param {jQuery} widgetContainer - Widget container element.
*
* @return {void}
*/
component.handleWidgetAdded = function handleWidgetAdded( event, widgetContainer ) {
var widgetForm, idBase, widgetControl, widgetId, animatedCheckDelay = 50, renderWhenAnimationDone, fieldContainer, syncContainer;
widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' ); // Note: '.form' appears in the customizer, whereas 'form' on the widgets admin screen.
idBase = widgetForm.find( '> .id_base' ).val();
if ( -1 === component.idBases.indexOf( idBase ) ) {
return;
}
// Prevent initializing already-added widgets.
widgetId = widgetForm.find( '.widget-id' ).val();
if ( component.widgetControls[ widgetId ] ) {
return;
}
/*
* Create a container element for the widget control fields.
* This is inserted into the DOM immediately before the the .widget-content
* element because the contents of this element are essentially "managed"
* by PHP, where each widget update cause the entire element to be emptied
* and replaced with the rendered output of WP_Widget::form() which is
* sent back in Ajax request made to save/update the widget instance.
* To prevent a "flash of replaced DOM elements and re-initialized JS
* components", the JS template is rendered outside of the normal form
* container.
*/
fieldContainer = $( '<div></div>' );
syncContainer = widgetContainer.find( '.widget-content:first' );
syncContainer.before( fieldContainer );
widgetControl = new component.CustomHtmlWidgetControl({
el: fieldContainer,
syncContainer: syncContainer
});
component.widgetControls[ widgetId ] = widgetControl;
/*
* Render the widget once the widget parent's container finishes animating,
* as the widget-added event fires with a slideDown of the container.
* This ensures that the textarea is visible and the editor can be initialized.
*/
renderWhenAnimationDone = function() {
if ( ! ( wp.customize ? widgetContainer.parent().hasClass( 'expanded' ) : widgetContainer.hasClass( 'open' ) ) ) { // Core merge: The wp.customize condition can be eliminated with this change being in core: https://github.com/xwp/wordpress-develop/pull/247/commits/5322387d
setTimeout( renderWhenAnimationDone, animatedCheckDelay );
} else {
widgetControl.initializeEditor();
}
};
renderWhenAnimationDone();
};
/**
* Setup widget in accessibility mode.
*
* @alias wp.customHtmlWidgets.setupAccessibleMode
*
* @return {void}
*/
component.setupAccessibleMode = function setupAccessibleMode() {
var widgetForm, idBase, widgetControl, fieldContainer, syncContainer;
widgetForm = $( '.editwidget > form' );
if ( 0 === widgetForm.length ) {
return;
}
idBase = widgetForm.find( '.id_base' ).val();
if ( -1 === component.idBases.indexOf( idBase ) ) {
return;
}
fieldContainer = $( '<div></div>' );
syncContainer = widgetForm.find( '> .widget-inside' );
syncContainer.before( fieldContainer );
widgetControl = new component.CustomHtmlWidgetControl({
el: fieldContainer,
syncContainer: syncContainer
});
widgetControl.initializeEditor();
};
/**
* Sync widget instance data sanitized from server back onto widget model.
*
* This gets called via the 'widget-updated' event when saving a widget from
* the widgets admin screen and also via the 'widget-synced' event when making
* a change to a widget in the customizer.
*
* @alias wp.customHtmlWidgets.handleWidgetUpdated
*
* @param {jQuery.Event} event - Event.
* @param {jQuery} widgetContainer - Widget container element.
* @return {void}
*/
component.handleWidgetUpdated = function handleWidgetUpdated( event, widgetContainer ) {
var widgetForm, widgetId, widgetControl, idBase;
widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' );
idBase = widgetForm.find( '> .id_base' ).val();
if ( -1 === component.idBases.indexOf( idBase ) ) {
return;
}
widgetId = widgetForm.find( '> .widget-id' ).val();
widgetControl = component.widgetControls[ widgetId ];
if ( ! widgetControl ) {
return;
}
widgetControl.updateFields();
};
/**
* Initialize functionality.
*
* This function exists to prevent the JS file from having to boot itself.
* When WordPress enqueues this script, it should have an inline script
* attached which calls wp.textWidgets.init().
*
* @alias wp.customHtmlWidgets.init
*
* @param {Object} settings - Options for code editor, exported from PHP.
*
* @return {void}
*/
component.init = function init( settings ) {
var $document = $( document );
_.extend( component.codeEditorSettings, settings );
$document.on( 'widget-added', component.handleWidgetAdded );
$document.on( 'widget-synced widget-updated', component.handleWidgetUpdated );
/*
* Manually trigger widget-added events for media widgets on the admin
* screen once they are expanded. The widget-added event is not triggered
* for each pre-existing widget on the widgets admin screen like it is
* on the customizer. Likewise, the customizer only triggers widget-added
* when the widget is expanded to just-in-time construct the widget form
* when it is actually going to be displayed. So the following implements
* the same for the widgets admin screen, to invoke the widget-added
* handler when a pre-existing media widget is expanded.
*/
$( function initializeExistingWidgetContainers() {
var widgetContainers;
if ( 'widgets' !== window.pagenow ) {
return;
}
widgetContainers = $( '.widgets-holder-wrap:not(#available-widgets)' ).find( 'div.widget' );
widgetContainers.one( 'click.toggle-widget-expanded', function toggleWidgetExpanded() {
var widgetContainer = $( this );
component.handleWidgetAdded( new jQuery.Event( 'widget-added' ), widgetContainer );
});
// Accessibility mode.
if ( document.readyState === 'complete' ) {
// Page is fully loaded.
component.setupAccessibleMode();
} else {
// Page is still loading.
$( window ).on( 'load', function() {
component.setupAccessibleMode();
});
}
});
};
return component;
})( jQuery );
PK �8FZ���^l l media-video-widget.jsnu �[��� /**
* @output wp-admin/js/widgets/media-video-widget.js
*/
/* eslint consistent-this: [ "error", "control" ] */
(function( component ) {
'use strict';
var VideoWidgetModel, VideoWidgetControl, VideoDetailsMediaFrame;
/**
* Custom video details frame that removes the replace-video state.
*
* @class wp.mediaWidgets.controlConstructors~VideoDetailsMediaFrame
* @augments wp.media.view.MediaFrame.VideoDetails
*
* @private
*/
VideoDetailsMediaFrame = wp.media.view.MediaFrame.VideoDetails.extend(/** @lends wp.mediaWidgets.controlConstructors~VideoDetailsMediaFrame.prototype */{
/**
* Create the default states.
*
* @return {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 wp.mediaWidgets.modelConstructors.media_video
* @augments wp.mediaWidgets.MediaWidgetModel
*/
VideoWidgetModel = component.MediaWidgetModel.extend({});
/**
* Video widget control.
*
* See WP_Widget_Video::enqueue_admin_scripts() for amending prototype from PHP exports.
*
* @class wp.mediaWidgets.controlConstructors.media_video
* @augments wp.mediaWidgets.MediaWidgetControl
*/
VideoWidgetControl = component.MediaWidgetControl.extend(/** @lends wp.mediaWidgets.controlConstructors.media_video.prototype */{
/**
* 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.
* @return {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.
*
* @return {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 = wp.apiRequest({
url: wp.media.view.settings.oEmbedProxyUrl,
data: {
url: control.model.get( 'url' ),
maxwidth: control.model.get( 'width' ),
maxheight: control.model.get( 'height' ),
discover: false
},
type: 'GET',
dataType: 'json',
context: control
});
control.fetchEmbedDfd.done( function( response ) {
control.oembedResponses[ url ] = response;
control.renderPreview();
});
control.fetchEmbedDfd.fail( function() {
control.oembedResponses[ url ] = null;
});
},
/**
* Whether a url is a supported external host.
*
* @deprecated since 4.9.
*
* @return {boolean} Whether url is a supported video host.
*/
isHostedVideo: function isHostedVideo() {
return true;
},
/**
* Render preview.
*
* @return {void}
*/
renderPreview: function renderPreview() {
var control = this, previewContainer, previewTemplate, attachmentId, attachmentUrl, poster, html = '', isOEmbed = false, mime, error, urlParser, matches;
attachmentId = control.model.get( 'attachment_id' );
attachmentUrl = control.model.get( 'url' );
error = control.model.get( 'error' );
if ( ! attachmentId && ! attachmentUrl ) {
return;
}
// 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';
}
} else if ( ! attachmentId ) {
urlParser = document.createElement( 'a' );
urlParser.href = attachmentUrl;
matches = urlParser.pathname.toLowerCase().match( /\.(\w+)$/ );
if ( matches ) {
if ( ! _.contains( _.keys( wp.media.view.settings.embedMimes ), matches[1] ) ) {
error = 'unsupported_file_type';
}
} else {
isOEmbed = true;
}
}
if ( isOEmbed ) {
control.fetchEmbed();
if ( control.oembedResponses[ attachmentUrl ] ) {
poster = control.oembedResponses[ attachmentUrl ].thumbnail_url;
html = control.oembedResponses[ attachmentUrl ].html.replace( /\swidth="\d+"/, ' width="100%"' ).replace( /\sheight="\d+"/, '' );
}
}
previewContainer = control.$el.find( '.media-widget-preview' );
previewTemplate = wp.template( 'wp-media-widget-video-preview' );
previewContainer.html( previewTemplate({
model: {
attachment_id: attachmentId,
html: html,
src: attachmentUrl,
poster: poster
},
is_oembed: isOEmbed,
error: error
}));
wp.mediaelement.initialize();
},
/**
* Open the media image-edit frame to modify the selected item.
*
* @return {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 );
PK �8FZ�ԯ�F �F text-widgets.jsnu �[��� /**
* @output wp-admin/js/widgets/text-widgets.js
*/
/* global tinymce, switchEditors */
/* eslint consistent-this: [ "error", "control" ] */
/**
* @namespace wp.textWidgets
*/
wp.textWidgets = ( function( $ ) {
'use strict';
var component = {
dismissedPointers: [],
idBases: [ 'text' ]
};
component.TextWidgetControl = Backbone.View.extend(/** @lends wp.textWidgets.TextWidgetControl.prototype */{
/**
* View events.
*
* @type {Object}
*/
events: {},
/**
* Text widget control.
*
* @constructs wp.textWidgets.TextWidgetControl
* @augments Backbone.View
* @abstract
*
* @param {Object} options - Options.
* @param {jQuery} options.el - Control field container element.
* @param {jQuery} options.syncContainer - Container element where fields are synced for the server.
*
* @return {void}
*/
initialize: function initialize( options ) {
var control = this;
if ( ! options.el ) {
throw new Error( 'Missing options.el' );
}
if ( ! options.syncContainer ) {
throw new Error( 'Missing options.syncContainer' );
}
Backbone.View.prototype.initialize.call( control, options );
control.syncContainer = options.syncContainer;
control.$el.addClass( 'text-widget-fields' );
control.$el.html( wp.template( 'widget-text-control-fields' ) );
control.customHtmlWidgetPointer = control.$el.find( '.wp-pointer.custom-html-widget-pointer' );
if ( control.customHtmlWidgetPointer.length ) {
control.customHtmlWidgetPointer.find( '.close' ).on( 'click', function( event ) {
event.preventDefault();
control.customHtmlWidgetPointer.hide();
$( '#' + control.fields.text.attr( 'id' ) + '-html' ).trigger( 'focus' );
control.dismissPointers( [ 'text_widget_custom_html' ] );
});
control.customHtmlWidgetPointer.find( '.add-widget' ).on( 'click', function( event ) {
event.preventDefault();
control.customHtmlWidgetPointer.hide();
control.openAvailableWidgetsPanel();
});
}
control.pasteHtmlPointer = control.$el.find( '.wp-pointer.paste-html-pointer' );
if ( control.pasteHtmlPointer.length ) {
control.pasteHtmlPointer.find( '.close' ).on( 'click', function( event ) {
event.preventDefault();
control.pasteHtmlPointer.hide();
control.editor.focus();
control.dismissPointers( [ 'text_widget_custom_html', 'text_widget_paste_html' ] );
});
}
control.fields = {
title: control.$el.find( '.title' ),
text: control.$el.find( '.text' )
};
// Sync input fields to hidden sync fields which actually get sent to the server.
_.each( control.fields, function( fieldInput, fieldName ) {
fieldInput.on( 'input change', function updateSyncField() {
var syncInput = control.syncContainer.find( '.sync-input.' + fieldName );
if ( syncInput.val() !== fieldInput.val() ) {
syncInput.val( fieldInput.val() );
syncInput.trigger( 'change' );
}
});
// Note that syncInput cannot be re-used because it will be destroyed with each widget-updated event.
fieldInput.val( control.syncContainer.find( '.sync-input.' + fieldName ).val() );
});
},
/**
* Dismiss pointers for Custom HTML widget.
*
* @since 4.8.1
*
* @param {Array} pointers Pointer IDs to dismiss.
* @return {void}
*/
dismissPointers: function dismissPointers( pointers ) {
_.each( pointers, function( pointer ) {
wp.ajax.post( 'dismiss-wp-pointer', {
pointer: pointer
});
component.dismissedPointers.push( pointer );
});
},
/**
* Open available widgets panel.
*
* @since 4.8.1
* @return {void}
*/
openAvailableWidgetsPanel: function openAvailableWidgetsPanel() {
var sidebarControl;
wp.customize.section.each( function( section ) {
if ( section.extended( wp.customize.Widgets.SidebarSection ) && section.expanded() ) {
sidebarControl = wp.customize.control( 'sidebars_widgets[' + section.params.sidebarId + ']' );
}
});
if ( ! sidebarControl ) {
return;
}
setTimeout( function() { // Timeout to prevent click event from causing panel to immediately collapse.
wp.customize.Widgets.availableWidgetsPanel.open( sidebarControl );
wp.customize.Widgets.availableWidgetsPanel.$search.val( 'HTML' ).trigger( 'keyup' );
});
},
/**
* Update input fields from the sync fields.
*
* This function is called at the widget-updated and widget-synced events.
* A field will only be updated if it is not currently focused, to avoid
* overwriting content that the user is entering.
*
* @return {void}
*/
updateFields: function updateFields() {
var control = this, syncInput;
if ( ! control.fields.title.is( document.activeElement ) ) {
syncInput = control.syncContainer.find( '.sync-input.title' );
control.fields.title.val( syncInput.val() );
}
syncInput = control.syncContainer.find( '.sync-input.text' );
if ( control.fields.text.is( ':visible' ) ) {
if ( ! control.fields.text.is( document.activeElement ) ) {
control.fields.text.val( syncInput.val() );
}
} else if ( control.editor && ! control.editorFocused && syncInput.val() !== control.fields.text.val() ) {
control.editor.setContent( wp.oldEditor.autop( syncInput.val() ) );
}
},
/**
* Initialize editor.
*
* @return {void}
*/
initializeEditor: function initializeEditor() {
var control = this, changeDebounceDelay = 1000, id, textarea, triggerChangeIfDirty, restoreTextMode = false, needsTextareaChangeTrigger = false, previousValue;
textarea = control.fields.text;
id = textarea.attr( 'id' );
previousValue = textarea.val();
/**
* Trigger change if dirty.
*
* @return {void}
*/
triggerChangeIfDirty = function() {
var updateWidgetBuffer = 300; // See wp.customize.Widgets.WidgetControl._setupUpdateUI() which uses 250ms for updateWidgetDebounced.
if ( control.editor.isDirty() ) {
/*
* Account for race condition in customizer where user clicks Save & Publish while
* focus was just previously given to the editor. Since updates to the editor
* are debounced at 1 second and since widget input changes are only synced to
* settings after 250ms, the customizer needs to be put into the processing
* state during the time between the change event is triggered and updateWidget
* logic starts. Note that the debounced update-widget request should be able
* to be removed with the removal of the update-widget request entirely once
* widgets are able to mutate their own instance props directly in JS without
* having to make server round-trips to call the respective WP_Widget::update()
* callbacks. See <https://core.trac.wordpress.org/ticket/33507>.
*/
if ( wp.customize && wp.customize.state ) {
wp.customize.state( 'processing' ).set( wp.customize.state( 'processing' ).get() + 1 );
_.delay( function() {
wp.customize.state( 'processing' ).set( wp.customize.state( 'processing' ).get() - 1 );
}, updateWidgetBuffer );
}
if ( ! control.editor.isHidden() ) {
control.editor.save();
}
}
// Trigger change on textarea when it has changed so the widget can enter a dirty state.
if ( needsTextareaChangeTrigger && previousValue !== textarea.val() ) {
textarea.trigger( 'change' );
needsTextareaChangeTrigger = false;
previousValue = textarea.val();
}
};
// Just-in-time force-update the hidden input fields.
control.syncContainer.closest( '.widget' ).find( '[name=savewidget]:first' ).on( 'click', function onClickSaveButton() {
triggerChangeIfDirty();
});
/**
* Build (or re-build) the visual editor.
*
* @return {void}
*/
function buildEditor() {
var editor, onInit, showPointerElement;
// Abort building if the textarea is gone, likely due to the widget having been deleted entirely.
if ( ! document.getElementById( id ) ) {
return;
}
// The user has disabled TinyMCE.
if ( typeof window.tinymce === 'undefined' ) {
wp.oldEditor.initialize( id, {
quicktags: true,
mediaButtons: true
});
return;
}
// Destroy any existing editor so that it can be re-initialized after a widget-updated event.
if ( tinymce.get( id ) ) {
restoreTextMode = tinymce.get( id ).isHidden();
wp.oldEditor.remove( id );
}
// Add or enable the `wpview` plugin.
$( document ).one( 'wp-before-tinymce-init.text-widget-init', function( event, init ) {
// If somebody has removed all plugins, they must have a good reason.
// Keep it that way.
if ( ! init.plugins ) {
return;
} else if ( ! /\bwpview\b/.test( init.plugins ) ) {
init.plugins += ',wpview';
}
} );
wp.oldEditor.initialize( id, {
tinymce: {
wpautop: true
},
quicktags: true,
mediaButtons: true
});
/**
* Show a pointer, focus on dismiss, and speak the contents for a11y.
*
* @param {jQuery} pointerElement Pointer element.
* @return {void}
*/
showPointerElement = function( pointerElement ) {
pointerElement.show();
pointerElement.find( '.close' ).trigger( 'focus' );
wp.a11y.speak( pointerElement.find( 'h3, p' ).map( function() {
return $( this ).text();
} ).get().join( '\n\n' ) );
};
editor = window.tinymce.get( id );
if ( ! editor ) {
throw new Error( 'Failed to initialize editor' );
}
onInit = function() {
// When a widget is moved in the DOM the dynamically-created TinyMCE iframe will be destroyed and has to be re-built.
$( editor.getWin() ).on( 'pagehide', function() {
_.defer( buildEditor );
});
// If a prior mce instance was replaced, and it was in text mode, toggle to text mode.
if ( restoreTextMode ) {
switchEditors.go( id, 'html' );
}
// Show the pointer.
$( '#' + id + '-html' ).on( 'click', function() {
control.pasteHtmlPointer.hide(); // Hide the HTML pasting pointer.
if ( -1 !== component.dismissedPointers.indexOf( 'text_widget_custom_html' ) ) {
return;
}
showPointerElement( control.customHtmlWidgetPointer );
});
// Hide the pointer when switching tabs.
$( '#' + id + '-tmce' ).on( 'click', function() {
control.customHtmlWidgetPointer.hide();
});
// Show pointer when pasting HTML.
editor.on( 'pastepreprocess', function( event ) {
var content = event.content;
if ( -1 !== component.dismissedPointers.indexOf( 'text_widget_paste_html' ) || ! content || ! /<\w+.*?>/.test( content ) ) {
return;
}
// Show the pointer after a slight delay so the user sees what they pasted.
_.delay( function() {
showPointerElement( control.pasteHtmlPointer );
}, 250 );
});
};
if ( editor.initialized ) {
onInit();
} else {
editor.on( 'init', onInit );
}
control.editorFocused = false;
editor.on( 'focus', function onEditorFocus() {
control.editorFocused = true;
});
editor.on( 'paste', function onEditorPaste() {
editor.setDirty( true ); // Because pasting doesn't currently set the dirty state.
triggerChangeIfDirty();
});
editor.on( 'NodeChange', function onNodeChange() {
needsTextareaChangeTrigger = true;
});
editor.on( 'NodeChange', _.debounce( triggerChangeIfDirty, changeDebounceDelay ) );
editor.on( 'blur hide', function onEditorBlur() {
control.editorFocused = false;
triggerChangeIfDirty();
});
control.editor = editor;
}
buildEditor();
}
});
/**
* Mapping of widget ID to instances of TextWidgetControl subclasses.
*
* @memberOf wp.textWidgets
*
* @type {Object.<string, wp.textWidgets.TextWidgetControl>}
*/
component.widgetControls = {};
/**
* Handle widget being added or initialized for the first time at the widget-added event.
*
* @memberOf wp.textWidgets
*
* @param {jQuery.Event} event - Event.
* @param {jQuery} widgetContainer - Widget container element.
*
* @return {void}
*/
component.handleWidgetAdded = function handleWidgetAdded( event, widgetContainer ) {
var widgetForm, idBase, widgetControl, widgetId, animatedCheckDelay = 50, renderWhenAnimationDone, fieldContainer, syncContainer;
widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' ); // Note: '.form' appears in the customizer, whereas 'form' on the widgets admin screen.
idBase = widgetForm.find( '> .id_base' ).val();
if ( -1 === component.idBases.indexOf( idBase ) ) {
return;
}
// Prevent initializing already-added widgets.
widgetId = widgetForm.find( '.widget-id' ).val();
if ( component.widgetControls[ widgetId ] ) {
return;
}
// Bypass using TinyMCE when widget is in legacy mode.
if ( ! widgetForm.find( '.visual' ).val() ) {
return;
}
/*
* Create a container element for the widget control fields.
* This is inserted into the DOM immediately before the .widget-content
* element because the contents of this element are essentially "managed"
* by PHP, where each widget update cause the entire element to be emptied
* and replaced with the rendered output of WP_Widget::form() which is
* sent back in Ajax request made to save/update the widget instance.
* To prevent a "flash of replaced DOM elements and re-initialized JS
* components", the JS template is rendered outside of the normal form
* container.
*/
fieldContainer = $( '<div></div>' );
syncContainer = widgetContainer.find( '.widget-content:first' );
syncContainer.before( fieldContainer );
widgetControl = new component.TextWidgetControl({
el: fieldContainer,
syncContainer: syncContainer
});
component.widgetControls[ widgetId ] = widgetControl;
/*
* Render the widget once the widget parent's container finishes animating,
* as the widget-added event fires with a slideDown of the container.
* This ensures that the textarea is visible and an iframe can be embedded
* with TinyMCE being able to set contenteditable on it.
*/
renderWhenAnimationDone = function() {
if ( ! widgetContainer.hasClass( 'open' ) ) {
setTimeout( renderWhenAnimationDone, animatedCheckDelay );
} else {
widgetControl.initializeEditor();
}
};
renderWhenAnimationDone();
};
/**
* Setup widget in accessibility mode.
*
* @memberOf wp.textWidgets
*
* @return {void}
*/
component.setupAccessibleMode = function setupAccessibleMode() {
var widgetForm, idBase, widgetControl, fieldContainer, syncContainer;
widgetForm = $( '.editwidget > form' );
if ( 0 === widgetForm.length ) {
return;
}
idBase = widgetForm.find( '.id_base' ).val();
if ( -1 === component.idBases.indexOf( idBase ) ) {
return;
}
// Bypass using TinyMCE when widget is in legacy mode.
if ( ! widgetForm.find( '.visual' ).val() ) {
return;
}
fieldContainer = $( '<div></div>' );
syncContainer = widgetForm.find( '> .widget-inside' );
syncContainer.before( fieldContainer );
widgetControl = new component.TextWidgetControl({
el: fieldContainer,
syncContainer: syncContainer
});
widgetControl.initializeEditor();
};
/**
* Sync widget instance data sanitized from server back onto widget model.
*
* This gets called via the 'widget-updated' event when saving a widget from
* the widgets admin screen and also via the 'widget-synced' event when making
* a change to a widget in the customizer.
*
* @memberOf wp.textWidgets
*
* @param {jQuery.Event} event - Event.
* @param {jQuery} widgetContainer - Widget container element.
* @return {void}
*/
component.handleWidgetUpdated = function handleWidgetUpdated( event, widgetContainer ) {
var widgetForm, widgetId, widgetControl, idBase;
widgetForm = widgetContainer.find( '> .widget-inside > .form, > .widget-inside > form' );
idBase = widgetForm.find( '> .id_base' ).val();
if ( -1 === component.idBases.indexOf( idBase ) ) {
return;
}
widgetId = widgetForm.find( '> .widget-id' ).val();
widgetControl = component.widgetControls[ widgetId ];
if ( ! widgetControl ) {
return;
}
widgetControl.updateFields();
};
/**
* Initialize functionality.
*
* This function exists to prevent the JS file from having to boot itself.
* When WordPress enqueues this script, it should have an inline script
* attached which calls wp.textWidgets.init().
*
* @memberOf wp.textWidgets
*
* @return {void}
*/
component.init = function init() {
var $document = $( document );
$document.on( 'widget-added', component.handleWidgetAdded );
$document.on( 'widget-synced widget-updated', component.handleWidgetUpdated );
/*
* Manually trigger widget-added events for media widgets on the admin
* screen once they are expanded. The widget-added event is not triggered
* for each pre-existing widget on the widgets admin screen like it is
* on the customizer. Likewise, the customizer only triggers widget-added
* when the widget is expanded to just-in-time construct the widget form
* when it is actually going to be displayed. So the following implements
* the same for the widgets admin screen, to invoke the widget-added
* handler when a pre-existing media widget is expanded.
*/
$( function initializeExistingWidgetContainers() {
var widgetContainers;
if ( 'widgets' !== window.pagenow ) {
return;
}
widgetContainers = $( '.widgets-holder-wrap:not(#available-widgets)' ).find( 'div.widget' );
widgetContainers.one( 'click.toggle-widget-expanded', function toggleWidgetExpanded() {
var widgetContainer = $( this );
component.handleWidgetAdded( new jQuery.Event( 'widget-added' ), widgetContainer );
});
// Accessibility mode.
component.setupAccessibleMode();
});
};
return component;
})( jQuery );
PK �8FZ�E�1� � media-audio-widget.jsnu �[��� /**
* @output wp-admin/js/widgets/media-audio-widget.js
*/
/* eslint consistent-this: [ "error", "control" ] */
(function( component ) {
'use strict';
var AudioWidgetModel, AudioWidgetControl, AudioDetailsMediaFrame;
/**
* Custom audio details frame that removes the replace-audio state.
*
* @class wp.mediaWidgets.controlConstructors~AudioDetailsMediaFrame
* @augments wp.media.view.MediaFrame.AudioDetails
*/
AudioDetailsMediaFrame = wp.media.view.MediaFrame.AudioDetails.extend(/** @lends wp.mediaWidgets.controlConstructors~AudioDetailsMediaFrame.prototype */{
/**
* Create the default states.
*
* @return {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 wp.mediaWidgets.modelConstructors.media_audio
* @augments wp.mediaWidgets.MediaWidgetModel
*/
AudioWidgetModel = component.MediaWidgetModel.extend({});
/**
* Audio widget control.
*
* See WP_Widget_Audio::enqueue_admin_scripts() for amending prototype from PHP exports.
*
* @class wp.mediaWidgets.controlConstructors.media_audio
* @augments wp.mediaWidgets.MediaWidgetControl
*/
AudioWidgetControl = component.MediaWidgetControl.extend(/** @lends wp.mediaWidgets.controlConstructors.media_audio.prototype */{
/**
* Show display settings.
*
* @type {boolean}
*/
showDisplaySettings: false,
/**
* Map model props to media frame props.
*
* @param {Object} modelProps - Model props.
* @return {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.
*
* @return {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.
*
* @return {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 );
PK "IFZ���$d d
style.min.cssnu �[��� :root{--wp-admin-theme-color:#007cba;--wp-admin-theme-color--rgb:0,124,186;--wp-admin-theme-color-darker-10:#006ba1;--wp-admin-theme-color-darker-10--rgb:0,107,161;--wp-admin-theme-color-darker-20:#005a87;--wp-admin-theme-color-darker-20--rgb:0,90,135;--wp-admin-border-width-focus:2px;--wp-block-synced-color:#7a00df;--wp-block-synced-color--rgb:122,0,223;--wp-bound-block-color:var(--wp-block-synced-color)}@media (min-resolution:192dpi){:root{--wp-admin-border-width-focus:1.5px}}.wp-block-legacy-widget__edit-form{background:#fff;border:1px solid #1e1e1e;border-radius:2px;max-height:calc(100vh - 2px);overflow-y:scroll;padding:11px}.wp-block-legacy-widget__edit-form:not([hidden]){display:flow-root}.wp-block-legacy-widget__edit-form .wp-block-legacy-widget__edit-form-title{color:#000;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:14px;font-weight:600;margin:0 0 12px}.wp-block-legacy-widget__edit-form .widget-inside.widget-inside{border:none;box-shadow:none;display:block;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.wp-block-legacy-widget__edit-form .widget-inside.widget-inside p{margin:8px 0}.wp-block-legacy-widget__edit-form .widget-inside.widget-inside label{font-size:13px;line-height:2.1}.wp-block-legacy-widget__edit-form .widget-inside.widget-inside a,.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input,.wp-block-legacy-widget__edit-form .widget-inside.widget-inside label{color:#000;font-family:system-ui;font-weight:400}.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=date],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=datetime-local],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=datetime],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=email],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=month],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=number],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=password],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=search],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=tel],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=text],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=time],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=url],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=week],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside select{background-color:initial;border:1px solid #757575;border-radius:3px;box-shadow:none;box-sizing:border-box;color:#000;display:block;font-family:system-ui;font-size:13px;font-weight:400;line-height:1;margin:0;min-height:30px;padding-bottom:8px;padding-left:8px;padding-top:8px;width:100%}.wp-block-legacy-widget__edit-form .widget-inside.widget-inside select{padding-left:4px}.wp-block-legacy-widget__edit-form .widget.open,.wp-block-legacy-widget__edit-form .widget.open:focus-within{z-index:0}.wp-block-legacy-widget__edit-form.wp-block-legacy-widget__edit-form,.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview{color:#000}.wp-block-legacy-widget__edit-no-preview,.wp-block-legacy-widget__edit-preview{cursor:pointer}.wp-block-legacy-widget__edit-no-preview:hover:after,.wp-block-legacy-widget__edit-preview:hover:after{border:1px solid #949494;border-radius:2px;bottom:0;content:"";left:0;position:absolute;right:0;top:0}.wp-block-legacy-widget__edit-preview.is-offscreen{left:-9999px;position:absolute;top:0;width:100%}.wp-block-legacy-widget__edit-preview-iframe{overflow:hidden;width:100%}.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview{background:#f0f0f0;padding:8px 12px}.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview,.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview h3,.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview p{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:13px}.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview h3{font-size:14px;font-weight:600;margin:4px 0}.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview p{margin:4px 0}.wp-block-legacy-widget-inspector-card{padding:0 16px 16px 52px}.interface-complementary-area .wp-block-legacy-widget-inspector-card__name{font-weight:500;margin:0 0 5px}.is-selected .wp-block-legacy-widget__container{min-height:50px;padding:8px 12px}.components-popover__content .wp-block-legacy-widget__edit-form{min-width:400px}.wp-block-widget-group.has-child-selected:after{border:1px solid var(--wp-admin-theme-color);border-radius:2px;bottom:0;content:"";left:0;position:absolute;right:0;top:0}.wp-block-widget-group .widget-title{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:18px;font-weight:600}.wp-block-widget-group__placeholder .block-editor-inserter{width:100%}.is-dark-theme .wp-block-widget-group__placeholder .block-editor-button-block-appender{box-shadow:inset 0 0 0 1px #1e1e1e;color:#1e1e1e}PK "IFZ�{�~� � style.cssnu �[��� :root{
--wp-admin-theme-color:#007cba;
--wp-admin-theme-color--rgb:0, 124, 186;
--wp-admin-theme-color-darker-10:#006ba1;
--wp-admin-theme-color-darker-10--rgb:0, 107, 161;
--wp-admin-theme-color-darker-20:#005a87;
--wp-admin-theme-color-darker-20--rgb:0, 90, 135;
--wp-admin-border-width-focus:2px;
--wp-block-synced-color:#7a00df;
--wp-block-synced-color--rgb:122, 0, 223;
--wp-bound-block-color:var(--wp-block-synced-color);
}
@media (min-resolution:192dpi){
:root{
--wp-admin-border-width-focus:1.5px;
}
}
.wp-block-legacy-widget__edit-form{
background:#fff;
border:1px solid #1e1e1e;
border-radius:2px;
max-height:calc(100vh - 2px);
overflow-y:scroll;
padding:11px;
}
.wp-block-legacy-widget__edit-form:not([hidden]){
display:flow-root;
}
.wp-block-legacy-widget__edit-form .wp-block-legacy-widget__edit-form-title{
color:#000;
font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;
font-size:14px;
font-weight:600;
margin:0 0 12px;
}
.wp-block-legacy-widget__edit-form .widget-inside.widget-inside{
border:none;
box-shadow:none;
display:block;
font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;
}
.wp-block-legacy-widget__edit-form .widget-inside.widget-inside p{
margin:8px 0;
}
.wp-block-legacy-widget__edit-form .widget-inside.widget-inside label{
font-size:13px;
line-height:2.1;
}
.wp-block-legacy-widget__edit-form .widget-inside.widget-inside a,.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input,.wp-block-legacy-widget__edit-form .widget-inside.widget-inside label{
color:#000;
font-family:system-ui;
font-weight:400;
}
.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=date],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=datetime-local],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=datetime],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=email],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=month],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=number],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=password],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=search],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=tel],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=text],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=time],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=url],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=week],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside select{
background-color:initial;
border:1px solid #757575;
border-radius:3px;
box-shadow:none;
box-sizing:border-box;
color:#000;
display:block;
font-family:system-ui;
font-size:13px;
font-weight:400;
line-height:1;
margin:0;
min-height:30px;
padding-bottom:8px;
padding-left:8px;
padding-top:8px;
width:100%;
}
.wp-block-legacy-widget__edit-form .widget-inside.widget-inside select{
padding-left:4px;
}
.wp-block-legacy-widget__edit-form .widget.open,.wp-block-legacy-widget__edit-form .widget.open:focus-within{
z-index:0;
}
.wp-block-legacy-widget__edit-form.wp-block-legacy-widget__edit-form,.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview{
color:#000;
}
.wp-block-legacy-widget__edit-no-preview,.wp-block-legacy-widget__edit-preview{
cursor:pointer;
}
.wp-block-legacy-widget__edit-no-preview:hover:after,.wp-block-legacy-widget__edit-preview:hover:after{
border:1px solid #949494;
border-radius:2px;
bottom:0;
content:"";
left:0;
position:absolute;
right:0;
top:0;
}
.wp-block-legacy-widget__edit-preview.is-offscreen{
left:-9999px;
position:absolute;
top:0;
width:100%;
}
.wp-block-legacy-widget__edit-preview-iframe{
overflow:hidden;
width:100%;
}
.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview{
background:#f0f0f0;
padding:8px 12px;
}
.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview,.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview h3,.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview p{
font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;
font-size:13px;
}
.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview h3{
font-size:14px;
font-weight:600;
margin:4px 0;
}
.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview p{
margin:4px 0;
}
.wp-block-legacy-widget-inspector-card{
padding:0 16px 16px 52px;
}
.interface-complementary-area .wp-block-legacy-widget-inspector-card__name{
font-weight:500;
margin:0 0 5px;
}
.is-selected .wp-block-legacy-widget__container{
min-height:50px;
padding:8px 12px;
}
.components-popover__content .wp-block-legacy-widget__edit-form{
min-width:400px;
}
.wp-block-widget-group.has-child-selected:after{
border:1px solid var(--wp-admin-theme-color);
border-radius:2px;
bottom:0;
content:"";
left:0;
position:absolute;
right:0;
top:0;
}
.wp-block-widget-group .widget-title{
font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;
font-size:18px;
font-weight:600;
}
.wp-block-widget-group__placeholder .block-editor-inserter{
width:100%;
}
.is-dark-theme .wp-block-widget-group__placeholder .block-editor-button-block-appender{
box-shadow:inset 0 0 0 1px #1e1e1e;
color:#1e1e1e;
}PK "IFZ֔�g g style-rtl.min.cssnu �[��� :root{--wp-admin-theme-color:#007cba;--wp-admin-theme-color--rgb:0,124,186;--wp-admin-theme-color-darker-10:#006ba1;--wp-admin-theme-color-darker-10--rgb:0,107,161;--wp-admin-theme-color-darker-20:#005a87;--wp-admin-theme-color-darker-20--rgb:0,90,135;--wp-admin-border-width-focus:2px;--wp-block-synced-color:#7a00df;--wp-block-synced-color--rgb:122,0,223;--wp-bound-block-color:var(--wp-block-synced-color)}@media (min-resolution:192dpi){:root{--wp-admin-border-width-focus:1.5px}}.wp-block-legacy-widget__edit-form{background:#fff;border:1px solid #1e1e1e;border-radius:2px;max-height:calc(100vh - 2px);overflow-y:scroll;padding:11px}.wp-block-legacy-widget__edit-form:not([hidden]){display:flow-root}.wp-block-legacy-widget__edit-form .wp-block-legacy-widget__edit-form-title{color:#000;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:14px;font-weight:600;margin:0 0 12px}.wp-block-legacy-widget__edit-form .widget-inside.widget-inside{border:none;box-shadow:none;display:block;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif}.wp-block-legacy-widget__edit-form .widget-inside.widget-inside p{margin:8px 0}.wp-block-legacy-widget__edit-form .widget-inside.widget-inside label{font-size:13px;line-height:2.1}.wp-block-legacy-widget__edit-form .widget-inside.widget-inside a,.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input,.wp-block-legacy-widget__edit-form .widget-inside.widget-inside label{color:#000;font-family:system-ui;font-weight:400}.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=date],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=datetime-local],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=datetime],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=email],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=month],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=number],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=password],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=search],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=tel],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=text],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=time],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=url],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=week],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside select{background-color:initial;border:1px solid #757575;border-radius:3px;box-shadow:none;box-sizing:border-box;color:#000;display:block;font-family:system-ui;font-size:13px;font-weight:400;line-height:1;margin:0;min-height:30px;padding-bottom:8px;padding-right:8px;padding-top:8px;width:100%}.wp-block-legacy-widget__edit-form .widget-inside.widget-inside select{padding-right:4px}.wp-block-legacy-widget__edit-form .widget.open,.wp-block-legacy-widget__edit-form .widget.open:focus-within{z-index:0}.wp-block-legacy-widget__edit-form.wp-block-legacy-widget__edit-form,.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview{color:#000}.wp-block-legacy-widget__edit-no-preview,.wp-block-legacy-widget__edit-preview{cursor:pointer}.wp-block-legacy-widget__edit-no-preview:hover:after,.wp-block-legacy-widget__edit-preview:hover:after{border:1px solid #949494;border-radius:2px;bottom:0;content:"";left:0;position:absolute;right:0;top:0}.wp-block-legacy-widget__edit-preview.is-offscreen{position:absolute;right:-9999px;top:0;width:100%}.wp-block-legacy-widget__edit-preview-iframe{overflow:hidden;width:100%}.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview{background:#f0f0f0;padding:8px 12px}.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview,.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview h3,.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview p{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:13px}.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview h3{font-size:14px;font-weight:600;margin:4px 0}.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview p{margin:4px 0}.wp-block-legacy-widget-inspector-card{padding:0 52px 16px 16px}.interface-complementary-area .wp-block-legacy-widget-inspector-card__name{font-weight:500;margin:0 0 5px}.is-selected .wp-block-legacy-widget__container{min-height:50px;padding:8px 12px}.components-popover__content .wp-block-legacy-widget__edit-form{min-width:400px}.wp-block-widget-group.has-child-selected:after{border:1px solid var(--wp-admin-theme-color);border-radius:2px;bottom:0;content:"";left:0;position:absolute;right:0;top:0}.wp-block-widget-group .widget-title{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:18px;font-weight:600}.wp-block-widget-group__placeholder .block-editor-inserter{width:100%}.is-dark-theme .wp-block-widget-group__placeholder .block-editor-button-block-appender{box-shadow:inset 0 0 0 1px #1e1e1e;color:#1e1e1e}PK "IFZ�gM� �
style-rtl.cssnu �[��� :root{
--wp-admin-theme-color:#007cba;
--wp-admin-theme-color--rgb:0, 124, 186;
--wp-admin-theme-color-darker-10:#006ba1;
--wp-admin-theme-color-darker-10--rgb:0, 107, 161;
--wp-admin-theme-color-darker-20:#005a87;
--wp-admin-theme-color-darker-20--rgb:0, 90, 135;
--wp-admin-border-width-focus:2px;
--wp-block-synced-color:#7a00df;
--wp-block-synced-color--rgb:122, 0, 223;
--wp-bound-block-color:var(--wp-block-synced-color);
}
@media (min-resolution:192dpi){
:root{
--wp-admin-border-width-focus:1.5px;
}
}
.wp-block-legacy-widget__edit-form{
background:#fff;
border:1px solid #1e1e1e;
border-radius:2px;
max-height:calc(100vh - 2px);
overflow-y:scroll;
padding:11px;
}
.wp-block-legacy-widget__edit-form:not([hidden]){
display:flow-root;
}
.wp-block-legacy-widget__edit-form .wp-block-legacy-widget__edit-form-title{
color:#000;
font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;
font-size:14px;
font-weight:600;
margin:0 0 12px;
}
.wp-block-legacy-widget__edit-form .widget-inside.widget-inside{
border:none;
box-shadow:none;
display:block;
font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;
}
.wp-block-legacy-widget__edit-form .widget-inside.widget-inside p{
margin:8px 0;
}
.wp-block-legacy-widget__edit-form .widget-inside.widget-inside label{
font-size:13px;
line-height:2.1;
}
.wp-block-legacy-widget__edit-form .widget-inside.widget-inside a,.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input,.wp-block-legacy-widget__edit-form .widget-inside.widget-inside label{
color:#000;
font-family:system-ui;
font-weight:400;
}
.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=date],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=datetime-local],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=datetime],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=email],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=month],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=number],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=password],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=search],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=tel],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=text],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=time],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=url],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside input[type=week],.wp-block-legacy-widget__edit-form .widget-inside.widget-inside select{
background-color:initial;
border:1px solid #757575;
border-radius:3px;
box-shadow:none;
box-sizing:border-box;
color:#000;
display:block;
font-family:system-ui;
font-size:13px;
font-weight:400;
line-height:1;
margin:0;
min-height:30px;
padding-bottom:8px;
padding-right:8px;
padding-top:8px;
width:100%;
}
.wp-block-legacy-widget__edit-form .widget-inside.widget-inside select{
padding-right:4px;
}
.wp-block-legacy-widget__edit-form .widget.open,.wp-block-legacy-widget__edit-form .widget.open:focus-within{
z-index:0;
}
.wp-block-legacy-widget__edit-form.wp-block-legacy-widget__edit-form,.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview{
color:#000;
}
.wp-block-legacy-widget__edit-no-preview,.wp-block-legacy-widget__edit-preview{
cursor:pointer;
}
.wp-block-legacy-widget__edit-no-preview:hover:after,.wp-block-legacy-widget__edit-preview:hover:after{
border:1px solid #949494;
border-radius:2px;
bottom:0;
content:"";
left:0;
position:absolute;
right:0;
top:0;
}
.wp-block-legacy-widget__edit-preview.is-offscreen{
position:absolute;
right:-9999px;
top:0;
width:100%;
}
.wp-block-legacy-widget__edit-preview-iframe{
overflow:hidden;
width:100%;
}
.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview{
background:#f0f0f0;
padding:8px 12px;
}
.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview,.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview h3,.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview p{
font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;
font-size:13px;
}
.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview h3{
font-size:14px;
font-weight:600;
margin:4px 0;
}
.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview.wp-block-legacy-widget__edit-no-preview p{
margin:4px 0;
}
.wp-block-legacy-widget-inspector-card{
padding:0 52px 16px 16px;
}
.interface-complementary-area .wp-block-legacy-widget-inspector-card__name{
font-weight:500;
margin:0 0 5px;
}
.is-selected .wp-block-legacy-widget__container{
min-height:50px;
padding:8px 12px;
}
.components-popover__content .wp-block-legacy-widget__edit-form{
min-width:400px;
}
.wp-block-widget-group.has-child-selected:after{
border:1px solid var(--wp-admin-theme-color);
border-radius:2px;
bottom:0;
content:"";
left:0;
position:absolute;
right:0;
top:0;
}
.wp-block-widget-group .widget-title{
font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;
font-size:18px;
font-weight:600;
}
.wp-block-widget-group__placeholder .block-editor-inserter{
width:100%;
}
.is-dark-theme .wp-block-widget-group__placeholder .block-editor-button-block-appender{
box-shadow:inset 0 0 0 1px #1e1e1e;
color:#1e1e1e;
}PK �8FZ�JIr( r( media-gallery-widget.jsnu �[��� PK �8FZ�r�
�
�( media-video-widget.min.jsnu �[��� PK �8FZ�!�� � �3 media-audio-widget.min.jsnu �[��� PK �8FZ�i��� � �9 custom-html-widgets.min.jsnu �[��� PK �8FZ|yN�� � �O media-image-widget.min.jsnu �[��� PK �8FZ���l�7 �7 �W media-widgets.min.jsnu �[��� PK �8FZ��YD� � �� text-widgets.min.jsnu �[��� PK �8FZ'��p� p� Φ media-widgets.jsnu �[��� PK �8FZ�Y� � � ~N media-gallery-widget.min.jsnu �[��� PK �8FZ8v�\ \ ] media-image-widget.jsnu �[��� PK �8FZ.�֛�= �= s custom-html-widgets.jsnu �[��� PK �8FZ���^l l � media-video-widget.jsnu �[��� PK �8FZ�ԯ�F �F �� text-widgets.jsnu �[��� PK �8FZ�E�1� � y media-audio-widget.jsnu �[��� PK "IFZ���$d d
z$ style.min.cssnu �[��� PK "IFZ�{�~� � ; style.cssnu �[��� PK "IFZ֔�g g KS style-rtl.min.cssnu �[��� PK "IFZ�gM� �
�i style-rtl.cssnu �[��� PK � *�