From 5be879f1abc7048fe8dc2d083e53dcd3ecec356a Mon Sep 17 00:00:00 2001 From: pglewis Date: Fri, 18 Jan 2019 17:49:52 -0500 Subject: [PATCH] Remove temporary workaround for #5197 --- ui/js/pods-dfv/_src/pods-dfv.js | 21 --------------------- ui/js/pods-dfv/pods-dfv.min.js | 2 +- ui/js/pods-dfv/pods-dfv.min.js.map | 2 +- 3 files changed, 2 insertions(+), 23 deletions(-) diff --git a/ui/js/pods-dfv/_src/pods-dfv.js b/ui/js/pods-dfv/_src/pods-dfv.js index ecc1c21c84..8dd362cc90 100755 --- a/ui/js/pods-dfv/_src/pods-dfv.js +++ b/ui/js/pods-dfv/_src/pods-dfv.js @@ -89,27 +89,6 @@ export default PodsDFV; document.addEventListener( 'DOMContentLoaded', () => { PodsDFV.init(); - /** - * This is temporary duct tape for WordPress 5.0 only to work around a - * Gutenberg compatibility bug - * - * See: - * https://github.com/pods-framework/pods/issues/5197 - * https://github.com/WordPress/gutenberg/issues/7176 - * - * @todo Delete this when WP 5.0.1 comes out - */ - if ( PodsDFV.isGutenbergEditorLoaded() && window.tinymce ) { - wp.data.subscribe( function() { - if ( wp.data.select( 'core/editor' ).isSavingPost() && window.tinymce.editors) { - for ( let i = 0; i < tinymce.editors.length; i++ ) { - tinymce.editors[ i ].save(); - } - } - - } ); - } - // Load the Gutenberg modal listener if we're inside a Pods modal with Gutenberg active if ( PodsDFV.isModalWindow() && PodsDFV.isGutenbergEditorLoaded()) { PodsGbModalListener.init(); diff --git a/ui/js/pods-dfv/pods-dfv.min.js b/ui/js/pods-dfv/pods-dfv.min.js index 840fbb4f6f..3efc44d035 100755 --- a/ui/js/pods-dfv/pods-dfv.min.js +++ b/ui/js/pods-dfv/pods-dfv.min.js @@ -1,2 +1,2 @@ -var PodsDFV=function(){"use strict";var o=Backbone.Model.extend({defaults:{htmlAttr:{},fieldConfig:{}}}),n=wp.data&&wp.data.select("core/editor"),e=void 0,t=function(){e=n.isCurrentPostPublished()?wp.data.subscribe(d):wp.data.subscribe(l)};function i(){var e=n.getCurrentPostAttribute("featured_media"),t="";if(!e)return t;var i=wp.data.select("core").getMedia(e);if(i){var l=wp.hooks.applyFilters("editor.PostFeaturedImage.imageSize","post-thumbnail","");t=i.media_details&&i.media_details.sizes&&i.media_details.sizes[l]?i.media_details.sizes[l].source_url:i.source_url}return t}function l(){n.isCurrentPostPublished()&&(e(),s({icon:i(),link:n.getPermalink(),edit_link:"post.php?post="+n.getCurrentPostId()+"&action=edit&pods_modal=1",selected:!0}))}function d(){d.wasSaving?n.isSavingPost()||(d.wasSaving=!1,n.didPostSaveRequestSucceed()&&(e(),s({icon:i()}))):d.wasSaving=!(!n.isSavingPost()||n.isAutosavingPost())}function s(e){var t={id:n.getCurrentPostId(),name:n.getCurrentPostAttribute("title")},i=Object.assign(t,e);window.parent.jQuery(window.parent).trigger("dfv:modal:update",i)}var a=Marionette.CollectionView.extend({childViewEventPrefix:!1,initialize:function(e){this.fieldModel=e.fieldModel,this.childViewOptions={fieldModel:e.fieldModel}}}),c=Marionette.View.extend({childViewEventPrefix:!1,serializeData:function(){var e=this.options.fieldModel,t=this.model?this.model.toJSON():{};return t.htmlAttr=e.get("htmlAttr"),t.fieldConfig=e.get("fieldConfig"),t}}),r=Marionette.View.extend({childViewEventPrefix:!1,initialize:function(e){this.fieldItemData=e.fieldItemData}}),f=Backbone.Model.extend({defaults:{id:0,icon:"",name:"",edit_link:"",link:"",download:""}}),h=Backbone.Collection.extend({model:f}),m=c.extend({childViewEventPrefix:!1,tagName:"li",template:_.template('\n\n'),className:"pods-dfv-list-item",ui:{dragHandle:".pods-dfv-list-handle",editLink:".pods-dfv-list-edit-link",viewLink:".pods-dfv-list-link",downloadLink:".pods-dfv-list-download",removeButton:".pods-dfv-list-remove",itemName:".pods-dfv-list-name"},triggers:{"click @ui.removeButton":"remove:file:click"}}),p=a.extend({childViewEventPrefix:!1,tagName:"ul",className:"pods-dfv-list",childView:m,childViewTriggers:{"remove:file:click":"childview:remove:file:click"},onAttach:function(){var e=this.options.fieldModel.get("fieldConfig"),t="y";1!=e.file_limit&&("tiles"==e.file_field_template&&(t=""),this.$el.sortable({containment:"parent",axis:t,scrollSensitivity:40,tolerance:"pointer",opacity:.6}))}}),u=c.extend({childViewEventPrefix:!1,tagName:"div",template:_.template('<%= fieldConfig.file_add_button %>'),ui:{addButton:".pods-dfv-list-add"},triggers:{"click @ui.addButton":"childview:add:file:click"}}),v=Marionette.Object.extend({constructor:function(e){this.browseButton=e.browseButton,this.uiRegion=e.uiRegion,this.fieldConfig=e.fieldConfig,Marionette.Object.call(this,e)}}),g=Backbone.Model.extend({defaults:{id:0,filename:"",progress:0,errorMsg:""}}),w=Marionette.View.extend({model:g,tagName:"li",template:_.template('\n<% if ( \'\' !== errorMsg ) { %>\n\t
<%- errorMsg %>
\n<% } %>\n'),attributes:function(){return{class:"pods-dfv-list-item",id:this.model.get("id")}},modelEvents:{change:"onModelChanged"},onModelChanged:function(){this.render()}}),C=Marionette.CollectionView.extend({tagName:"ul",className:"pods-dfv-list pods-dfv-list-queue",childView:w}),b="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},k=[v.extend({plupload:{},fileUploader:"plupload",initialize:function(){this.fieldConfig.plupload_init.browse_button=this.browseButton,this.plupload=new plupload.Uploader(this.fieldConfig.plupload_init),this.plupload.init(),this.plupload.bind("FilesAdded",this.onFilesAdded,this),this.plupload.bind("UploadProgress",this.onUploadProgress,this),this.plupload.bind("FileUploaded",this.onFileUploaded,this)},onFilesAdded:function(e,t){var i=void 0,l=void 0,n=void 0;l=new Backbone.Collection,jQuery.each(t,function(e,t){i=new g({id:t.id,filename:t.name}),l.add(i)}),(n=new C({collection:l})).render(),this.uiRegion.reset(),this.uiRegion.show(n),this.queueCollection=l,e.refresh(),e.start()},onUploadProgress:function(e,t){this.queueCollection.get(t.id).set({progress:t.percent})},onFileUploaded:function(e,t,i){var l=this.queueCollection.get(t.id),n=i.response,o=[],d=void 0;if("Error: "===i.response.substr(0,7))n=n.substr(7),window.console&&console.log(n),l.set({progress:0,errorMsg:n});else if(""===i.response.substr(0,3))n=jQuery(n).text(),window.console&&console.log(n),l.set({progress:0,errorMsg:n});else{if("object"!==(void 0===(d=null!==(d=n.match(/{.*}$/))&&0\n
\n
\n'),regions:{list:".pods-ui-file-list",uiRegion:".pods-ui-region",form:".pods-ui-form"},childViewEvents:{"childview:remove:file:click":"onChildviewRemoveFileClick","childview:add:file:click":"onChildviewAddFileClick"},uploader:{},onBeforeRender:function(){void 0===this.collection&&(this.collection=new h(this.fieldItemData))},onRender:function(){var e=new p({collection:this.collection,fieldModel:this.model}),t=new u({fieldModel:this.model});this.showChildView("list",e),this.showChildView("form",t),this.uploader=this.createUploader(),this.listenTo(this.uploader,"added:files",this.onAddedFiles)},onChildviewRemoveFileClick:function(e){this.collection.remove(e.model)},onChildviewAddFileClick:function(){"function"==typeof this.uploader.invoke&&this.uploader.invoke()},onAddedFiles:function(e){var t=+this.model.get("fieldConfig").file_limit,i=void 0,l=void 0;(i=this.collection.clone()).add(e),l=0===t?i.models:i.filter(function(e){return i.indexOf(e)>=i.length-t}),this.collection.reset(l)},createUploader:function(){var e=this.model.get("fieldConfig"),i=e.file_uploader,l=void 0;if(jQuery.each(k,function(e,t){if(i===t.prototype.fileUploader)return l=t,!1}),void 0!==l)return this.uploader=new l({browseButton:this.getRegion("form").getEl(".pods-dfv-list-add").get(),uiRegion:this.getRegion("uiRegion"),fieldConfig:e}),this.uploader;throw"Could not locate file uploader '"+i+"'"}}),x=wp.media.view.Modal.extend({close:function(e){var t=wp.media.view.Modal.prototype.close.apply(this,e);return e&&e.escape&&window.parent.jQuery(window.parent).trigger("dfv:modal:cancel"),t}}),S=wp.media.view.Frame.extend({className:"pods-modal-frame",template:_.template('
'),regions:["title","iframe"],initialize:function(){wp.media.view.Frame.prototype.initialize.apply(this,arguments),this.$el.addClass("wp-core-ui"),this.initState(),this.initModal(),this.on("iframe:create:default",this.iframeContent,this),this.iframe.mode("default"),this.on("title:create:default",this.createTitle,this),this.title.mode("default"),this.on("title:render",function(e){e.$el.append('')})},initState:function(){var e=this.options.title||PodsI18n.__("Add New Record"),t=this.options.src||"/";this.states.add([new wp.media.controller.State({id:"default",title:e,src:t})]),this.options.state="default"},initModal:function(){this.modal=new x({controller:this}),this.modal.content(this)},render:function(){return!this.state()&&this.options.state&&this.setState(this.options.state),wp.media.view.Frame.prototype.render.apply(this,arguments)},iframeContent:function(e){e.view=new wp.media.view.Iframe({controller:this})},createTitle:function(e){e.view=new wp.media.View({controller:this,tagName:"h1"})}}),P=Backbone.Model.extend({defaults:{id:0,name:"",icon:"",link:"",edit_link:"",selected:!1},toggleSelected:function(){this.set("selected",!this.get("selected"))}}),M=Backbone.Collection.extend({model:P,setSelected:function(i){this.map(function(e){var t=_.contains(i,e.get("id")+"");e.set("selected",t)})},filterBySelected:function(){var e=this.filter(function(e){return e.get("selected")});return new M(e)},filterByUnselected:function(){var e=this.filter(function(e){return!e.get("selected")});return new M(e)}}),A=Backbone.Model.extend({defaults:{view_name:"select",iframe_src:"",pick_format_type:"single",pick_show_icon:!1,pick_show_view_link:!1,pick_show_edit_link:!1}}),V=c.extend({childViewEventPrefix:!1,tagName:"li",template:_.template('
\n\t\n\t\t\t\tchecked="CHECKED"\n\t\t\t<% } %>\n\t\t\tvalue="<%- id %>" tabindex="2">\n\t\n
\n'),templateContext:function(){return{ordinal:this.model.collection.indexOf(this.model)+1}},modelChanged:function(){this.render()}}),L=a.extend({childViewEventPrefix:!1,tagName:"ul",className:"pods-radio",childView:V}),j=c.extend({childViewEventPrefix:!1,tagName:"li",template:_.template('
\n\t\n\t\tdata-name-clean="<%- htmlAttr.name_clean %>" data-label="<%- fieldConfig.label %>" id="<%- htmlAttr.id %><%= ordinal %>" class="pods-form-ui-field-type-pick" type="checkbox" tabindex="2" value="<%- id %>">\n\t\n
\n'),className:"pods-pick",ui:{checkbox:"input.pods-form-ui-field-type-pick"},triggers:{"click @ui.checkbox":"toggle:selected"},modelEvents:{change:"modelChanged"},templateContext:function(){return{ordinal:this.model.collection.indexOf(this.model)}},modelChanged:function(){this.render()}}),I=a.extend({childViewEventPrefix:!1,tagName:"ul",className:"pods-checkbox-view",childView:j,childViewEvents:{"toggle:selected":"onChildviewToggleSelected"},onAttach:function(){this.validateSelectionLimit()||this.selectionLimitOver()},onChildviewToggleSelected:function(e){e.model.toggleSelected(),this.validateSelectionLimit()?this.selectionLimitUnder():this.selectionLimitOver()},validateSelectionLimit:function(){var e,t;return e=+this.fieldModel.get("fieldConfig").pick_limit,t=this.collection.filterBySelected().length,0===e||t'),e={maximumSelectionLength:s?void 0:d,placeholder:t.limitDisable?PodsI18n.__("You can only select")+" "+sprintf(PodsI18n._n("%s item","%s items",d),d):PodsI18n.__("Search")+" "+t.label+"...",allowClear:s,disabled:t.limitDisable,tags:t.pick_taggable,escapeMarkup:function(e){return e}},n.ajax&&jQuery.extend(e,{minimumInputLength:n.minimum_input_length,ajax:{url:ajaxurl+"?pods_ajax=1",type:"POST",dataType:"json",delay:n.delay,data:function(e){return{_wpnonce:n._wpnonce,action:"pods_relationship",method:"select2",pod:n.pod,field:n.field,uri:n.uri,id:n.id,query:e.term}},processResults:function(e,t){return i.filterAjaxList(e,t)}}}),l.selectWoo(jQuery.extend(!0,e,o)),(c=l.parent().find("ul.select2-selection__rendered")).sortable({containment:"parent"}),c.on("sortstop",function(){var e=c.find(".select2-selection__choice").get().reverse();jQuery(e).each(function(){var e=jQuery(this).data("data").id,t=l.find('option[value="'+e+'"]')[0];l.prepend(t)})})}}),O=c.extend({childViewEventPrefix:!1,tagName:"li",className:"pods-dfv-list-item pods-relationship",template:_.template('\n\t\t\tname="<%- htmlAttr.name %>" id="<%- htmlAttr.id %>"\n\t\t<% } else { %>\n\t\t\tname="<%- htmlAttr.name %>[<%= ordinal %>]" id="<%- htmlAttr.id %><%= ordinal %>"\n\t\t<% } %>\n\t\tdata-name-clean="<%- htmlAttr.name_clean %>" type="hidden" value="<%- id %>">\n
    \n\t<% if ( 1 != fieldConfig.pick_limit ) { %>\n\t\t
  • <%- PodsI18n.__( \'Reorder\' ) %>
  • \n\t<% } %>\n\t<% if ( 1 == fieldConfig.pick_show_icon ) { %>\n\t\t
  • \n\t\t\t<% if ( \'\' == icon ) { %>\n\t\t\t\t<% if ( /^dashicons/.test( fieldConfig.default_icon ) ) { %>\n\t\t\t\t\t\n\t\t\t\t<% } else { %>\n\t\t\t\t\tIcon\n\t\t\t\t<% } %>\n\t\t\t<% } else { %>\n\t\t\t\t<% if ( /^dashicons/.test( icon ) ) { %>\n\t\t\t\t\t\n\t\t\t\t<% } else { %>\n\t\t\t\t\tIcon\n\t\t\t\t<% } %>\n\t\t\t<% } %>\n\t\t
  • \n\t<% } %>\n\t
  • \n\t\t<%= name %>\n\t
  • \n\t
  • <%- PodsI18n.__( \'Deselect\' ) %>
  • \n\t<% if ( 1 == fieldConfig.pick_show_view_link && \'\' != link ) { %>\n\t\t\n\t<% } %>\n\t<% if ( 1 == fieldConfig.pick_show_edit_link && \'\' != edit_link ) { %>\n\t\t
  • <%- PodsI18n.__( \'Edit\' ) %>
  • \n\t<% } %>\n
\n'),ui:{removeButton:".pods-dfv-list-remove a",editButton:".pods-dfv-list-edit a"},triggers:{"click @ui.removeButton":"remove:item:click","click @ui.editButton":"edit:item:click"},templateContext:function(){return{ordinal:this.model.collection.indexOf(this.model)}}}),U=a.extend({childViewEventPrefix:!1,tagName:"ul",className:"pods-dfv-list pods-relationship",childView:O,childViewTriggers:{"remove:item:click":"childview:remove:item:click","edit:item:click":"childview:edit:item:click"},filter:function(e,t,i){return e.attributes.selected},onAttach:function(){1!==this.options.fieldModel.get("fieldConfig").pick_limit&&this.$el.sortable({containment:"parent",axis:"y",scrollSensitivity:40,tolerance:"pointer",opacity:.6})}}),F="button-disabled",R=c.extend({childViewEventPrefix:!1,tagName:"div",className:"podsform-dfv-list-relationship-container",ui:{addButton:"a.pods-related-add-new"},template:_.template('\n\t<%- PodsI18n.__( \'Add New\' ) %>\n'),triggers:{"click @ui.addButton":"add:new:click"},disable:function(){this.getUI("addButton").addClass(F)},enable:function(){this.getUI("addButton").removeClass(F)},onAddNewClick:function(){this.getUI("addButton").hasClass(F)||this.trigger("childview:add:new",this)}}),D={checkbox:I,select:B,select2:B,radio:L,list:U},Q=void 0,$=r.extend({childViewEventPrefix:!1,template:_.template('<%if ( fieldConfig.view_name === \'list\' ) { %>\n\t
\n<% } %>\n\n
\n\n<% if ( fieldConfig.iframe_src != \'\' ) { %>\n\t
\n<% } %>'),regions:{autocomplete:".pods-ui-list-autocomplete",list:".pods-pick-values",addNew:".pods-ui-add-new"},childViewEvents:{"childview:remove:item:click":"onChildviewRemoveItemClick","childview:edit:item:click":"onChildviewEditItemClick","childview:selection:limit:over":"onChildviewSelectionLimitOver","childview:selection:limit:under":"onChildviewSelectionLimitUnder","childview:change:selected":"onChildviewChangeSelected","childview:add:new":"onChildviewAddNew"},onBeforeRender:function(){void 0===this.collection&&(this.collection=new M(this.fieldItemData))},onRender:function(){this.fieldConfig=new A(this.model.get("fieldConfig")),""!==this.fieldConfig.get("iframe_src")&&1==this.fieldConfig.get("pick_allow_add_new")&&this.showAddNew(),"list"===this.fieldConfig.get("view_name")&&this.buildAutocomplete(),this.showList()},buildAutocomplete:function(){var e,t,i=void 0,l=void 0,n=+this.fieldConfig.get("pick_limit");i={view_name:"select2",pick_format_type:"multi",selectFromExisting:!0,ajax_data:this.fieldConfig.get("ajax_data"),select2_overrides:this.fieldConfig.get("select2_overrides"),label:this.fieldConfig.get("label"),pick_limit:n},this.collection.filterBySelected().length>=n&&0!==n?(i.limitDisable=!0,this.onChildviewSelectionLimitOver()):this.onChildviewSelectionLimitUnder(),e=new o({fieldConfig:i}),t=this.collection.filterByUnselected(),(l=new B({collection:t,fieldModel:e})).filterAjaxList=this.filterAjaxList.bind(this),this.showChildView("autocomplete",l)},showList:function(){var e,t;if(e=this.fieldConfig.get("view_name"),void 0===D[e])throw new Error('Invalid view name "'+e+'"');t=new D[e]({collection:this.collection,fieldModel:this.model}),this.showChildView("list",t)},showAddNew:function(){var e=new R({fieldModel:this.model});this.showChildView("addNew",e)},filterAjaxList:function(e){var t=this.collection.filterBySelected(),i=[];return _.each(e.results,function(e){e.text=e.name,t.get(e.id)||i.push(e)}),this.collection.add(i),this.getChildView("autocomplete").setCollection(this.collection.filterByUnselected()),{results:i}},onChildviewSelectionLimitOver:function(e){var t=this.getChildView("addNew");t&&t.disable()},onChildviewSelectionLimitUnder:function(e){var t=this.getChildView("addNew");t&&t.enable()},onChildviewRemoveItemClick:function(e){e.model.toggleSelected(),this.getChildView("list").render(),"list"===this.fieldConfig.get("view_name")&&this.buildAutocomplete()},onChildviewAddNew:function(e){var t=this.model.get("fieldConfig");Q=new S({title:t.iframe_title_add,src:t.iframe_src}),this.setModalListeners(),Q.modal.open()},onChildviewEditItemClick:function(e){var t=this.model.get("fieldConfig");Q=new S({title:t.iframe_title_edit,src:e.ui.editButton.attr("href")}),this.setModalListeners(),Q.modal.open()},onChildviewChangeSelected:function(e){e.fieldConfig.selectFromExisting&&(_.defer(this.buildAutocomplete.bind(this)),this.getChildView("list").render())},setModalListeners:function(){jQuery(window).on("dfv:modal:update",this.modalSuccess.bind(this)),jQuery(window).on("dfv:modal:cancel",this.modalCancel.bind(this))},clearModalListeners:function(){jQuery(window).off("dfv:modal:update"),jQuery(window).off("dfv:modal:cancel")},modalSuccess:function(e,t){var i=this.collection.get(t.id);i?(i.set(t),this.getChildView("list").render()):this.collection.add(t),this.clearModalListeners(),Q.modal.close({})},modalCancel:function(){this.clearModalListeners()}}),z={file:y,avatar:y,pick:$},T={fields:Object.freeze({FileUpload:y,Pick:$}),models:Object.freeze({PodsDFVFieldModel:o,RelationshipModel:P,RelationshipCollection:M,FileUploadModel:f,FileUploadCollection:h}),fieldInstances:{},init:function(){var l=this;jQuery(".pods-form-ui-field").each(function(){var e=void 0,t=void 0,i={fieldType:void 0};jQuery(this).find("script.pods-dfv-field-data").each(function(){var e=jQuery.parseJSON(jQuery(this).html());jQuery(this).parents(".media-modal-content").length&&(e.fieldConfig.pick_allow_add_new=0),jQuery.extend(i,e),jQuery(this).remove()}),void 0!==i.fieldType&&void 0!==(e=z[i.fieldType])&&((t=new e({el:this,model:new o({htmlAttr:i.htmlAttr,fieldConfig:i.fieldConfig}),fieldItemData:i.fieldItemData})).render(),jQuery(this).trigger("render"),l.fieldInstances[i.htmlAttr.id]=t)})},isModalWindow:function(){return-1!==location.search.indexOf("pods_modal=")},isGutenbergEditorLoaded:function(){return void 0!==wp.data&&void 0!==wp.data.select("core/editor")}};return document.addEventListener("DOMContentLoaded",function(){T.init(),T.isGutenbergEditorLoaded()&&window.tinymce&&wp.data.subscribe(function(){if(wp.data.select("core/editor").isSavingPost()&&window.tinymce.editors)for(var e=0;e\n
    \n\t<% if ( 1 != fieldConfig.file_limit ) { %>\n\t\t
  • <%- PodsI18n.__( \'Reorder\' ) %>
  • \n\t<% } %>\n\t
  • <%- PodsI18n.__( \'Icon\' ) %>
  • \n\t
  • \n\t\t<% if ( 0 != fieldConfig.file_edit_title ) { %>\n\t\t\t\n\t\t<% } else { %>\n\t\t\t<%- name %>\n\t\t<% } %>\n\t
  • \n\t
  • \n\t\t\n\t
  • \n
\n'),className:"pods-dfv-list-item",ui:{dragHandle:".pods-dfv-list-handle",editLink:".pods-dfv-list-edit-link",viewLink:".pods-dfv-list-link",downloadLink:".pods-dfv-list-download",removeButton:".pods-dfv-list-remove",itemName:".pods-dfv-list-name"},triggers:{"click @ui.removeButton":"remove:file:click"}}),p=a.extend({childViewEventPrefix:!1,tagName:"ul",className:"pods-dfv-list",childView:m,childViewTriggers:{"remove:file:click":"childview:remove:file:click"},onAttach:function(){var e=this.options.fieldModel.get("fieldConfig"),t="y";1!=e.file_limit&&("tiles"==e.file_field_template&&(t=""),this.$el.sortable({containment:"parent",axis:t,scrollSensitivity:40,tolerance:"pointer",opacity:.6}))}}),u=c.extend({childViewEventPrefix:!1,tagName:"div",template:_.template('<%= fieldConfig.file_add_button %>'),ui:{addButton:".pods-dfv-list-add"},triggers:{"click @ui.addButton":"childview:add:file:click"}}),v=Marionette.Object.extend({constructor:function(e){this.browseButton=e.browseButton,this.uiRegion=e.uiRegion,this.fieldConfig=e.fieldConfig,Marionette.Object.call(this,e)}}),g=Backbone.Model.extend({defaults:{id:0,filename:"",progress:0,errorMsg:""}}),w=Marionette.View.extend({model:g,tagName:"li",template:_.template('
    \n\t<% if ( \'\' === errorMsg ) { %>\n\t\t
  • \n\t<% } %>\n\t
  • <%- filename %>
  • \n
\n<% if ( \'\' !== errorMsg ) { %>\n\t
<%- errorMsg %>
\n<% } %>\n'),attributes:function(){return{class:"pods-dfv-list-item",id:this.model.get("id")}},modelEvents:{change:"onModelChanged"},onModelChanged:function(){this.render()}}),C=Marionette.CollectionView.extend({tagName:"ul",className:"pods-dfv-list pods-dfv-list-queue",childView:w}),b="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},k=[v.extend({plupload:{},fileUploader:"plupload",initialize:function(){this.fieldConfig.plupload_init.browse_button=this.browseButton,this.plupload=new plupload.Uploader(this.fieldConfig.plupload_init),this.plupload.init(),this.plupload.bind("FilesAdded",this.onFilesAdded,this),this.plupload.bind("UploadProgress",this.onUploadProgress,this),this.plupload.bind("FileUploaded",this.onFileUploaded,this)},onFilesAdded:function(e,t){var i=void 0,l=void 0,n=void 0;l=new Backbone.Collection,jQuery.each(t,function(e,t){i=new g({id:t.id,filename:t.name}),l.add(i)}),(n=new C({collection:l})).render(),this.uiRegion.reset(),this.uiRegion.show(n),this.queueCollection=l,e.refresh(),e.start()},onUploadProgress:function(e,t){this.queueCollection.get(t.id).set({progress:t.percent})},onFileUploaded:function(e,t,i){var l=this.queueCollection.get(t.id),n=i.response,o=[],d=void 0;if("Error: "===i.response.substr(0,7))n=n.substr(7),window.console&&console.log(n),l.set({progress:0,errorMsg:n});else if(""===i.response.substr(0,3))n=jQuery(n).text(),window.console&&console.log(n),l.set({progress:0,errorMsg:n});else{if("object"!==(void 0===(d=null!==(d=n.match(/{.*}$/))&&0
\n
\n
\n'),regions:{list:".pods-ui-file-list",uiRegion:".pods-ui-region",form:".pods-ui-form"},childViewEvents:{"childview:remove:file:click":"onChildviewRemoveFileClick","childview:add:file:click":"onChildviewAddFileClick"},uploader:{},onBeforeRender:function(){void 0===this.collection&&(this.collection=new h(this.fieldItemData))},onRender:function(){var e=new p({collection:this.collection,fieldModel:this.model}),t=new u({fieldModel:this.model});this.showChildView("list",e),this.showChildView("form",t),this.uploader=this.createUploader(),this.listenTo(this.uploader,"added:files",this.onAddedFiles)},onChildviewRemoveFileClick:function(e){this.collection.remove(e.model)},onChildviewAddFileClick:function(){"function"==typeof this.uploader.invoke&&this.uploader.invoke()},onAddedFiles:function(e){var t=+this.model.get("fieldConfig").file_limit,i=void 0,l=void 0;(i=this.collection.clone()).add(e),l=0===t?i.models:i.filter(function(e){return i.indexOf(e)>=i.length-t}),this.collection.reset(l)},createUploader:function(){var e=this.model.get("fieldConfig"),i=e.file_uploader,l=void 0;if(jQuery.each(k,function(e,t){if(i===t.prototype.fileUploader)return l=t,!1}),void 0!==l)return this.uploader=new l({browseButton:this.getRegion("form").getEl(".pods-dfv-list-add").get(),uiRegion:this.getRegion("uiRegion"),fieldConfig:e}),this.uploader;throw"Could not locate file uploader '"+i+"'"}}),x=wp.media.view.Modal.extend({close:function(e){var t=wp.media.view.Modal.prototype.close.apply(this,e);return e&&e.escape&&window.parent.jQuery(window.parent).trigger("dfv:modal:cancel"),t}}),S=wp.media.view.Frame.extend({className:"pods-modal-frame",template:_.template('
'),regions:["title","iframe"],initialize:function(){wp.media.view.Frame.prototype.initialize.apply(this,arguments),this.$el.addClass("wp-core-ui"),this.initState(),this.initModal(),this.on("iframe:create:default",this.iframeContent,this),this.iframe.mode("default"),this.on("title:create:default",this.createTitle,this),this.title.mode("default"),this.on("title:render",function(e){e.$el.append('')})},initState:function(){var e=this.options.title||PodsI18n.__("Add New Record"),t=this.options.src||"/";this.states.add([new wp.media.controller.State({id:"default",title:e,src:t})]),this.options.state="default"},initModal:function(){this.modal=new x({controller:this}),this.modal.content(this)},render:function(){return!this.state()&&this.options.state&&this.setState(this.options.state),wp.media.view.Frame.prototype.render.apply(this,arguments)},iframeContent:function(e){e.view=new wp.media.view.Iframe({controller:this})},createTitle:function(e){e.view=new wp.media.View({controller:this,tagName:"h1"})}}),P=Backbone.Model.extend({defaults:{id:0,name:"",icon:"",link:"",edit_link:"",selected:!1},toggleSelected:function(){this.set("selected",!this.get("selected"))}}),M=Backbone.Collection.extend({model:P,setSelected:function(i){this.map(function(e){var t=_.contains(i,e.get("id")+"");e.set("selected",t)})},filterBySelected:function(){var e=this.filter(function(e){return e.get("selected")});return new M(e)},filterByUnselected:function(){var e=this.filter(function(e){return!e.get("selected")});return new M(e)}}),A=Backbone.Model.extend({defaults:{view_name:"select",iframe_src:"",pick_format_type:"single",pick_show_icon:!1,pick_show_view_link:!1,pick_show_edit_link:!1}}),V=c.extend({childViewEventPrefix:!1,tagName:"li",template:_.template('
\n\t\n\t\t\t\tchecked="CHECKED"\n\t\t\t<% } %>\n\t\t\tvalue="<%- id %>" tabindex="2">\n\t\n
\n'),templateContext:function(){return{ordinal:this.model.collection.indexOf(this.model)+1}},modelChanged:function(){this.render()}}),j=a.extend({childViewEventPrefix:!1,tagName:"ul",className:"pods-radio",childView:V}),I=c.extend({childViewEventPrefix:!1,tagName:"li",template:_.template('
\n\t\n\t\tdata-name-clean="<%- htmlAttr.name_clean %>" data-label="<%- fieldConfig.label %>" id="<%- htmlAttr.id %><%= ordinal %>" class="pods-form-ui-field-type-pick" type="checkbox" tabindex="2" value="<%- id %>">\n\t\n
\n'),className:"pods-pick",ui:{checkbox:"input.pods-form-ui-field-type-pick"},triggers:{"click @ui.checkbox":"toggle:selected"},modelEvents:{change:"modelChanged"},templateContext:function(){return{ordinal:this.model.collection.indexOf(this.model)}},modelChanged:function(){this.render()}}),L=a.extend({childViewEventPrefix:!1,tagName:"ul",className:"pods-checkbox-view",childView:I,childViewEvents:{"toggle:selected":"onChildviewToggleSelected"},onAttach:function(){this.validateSelectionLimit()||this.selectionLimitOver()},onChildviewToggleSelected:function(e){e.model.toggleSelected(),this.validateSelectionLimit()?this.selectionLimitUnder():this.selectionLimitOver()},validateSelectionLimit:function(){var e,t;return e=+this.fieldModel.get("fieldConfig").pick_limit,t=this.collection.filterBySelected().length,0===e||t'),e={maximumSelectionLength:s?void 0:d,placeholder:t.limitDisable?PodsI18n.__("You can only select")+" "+sprintf(PodsI18n._n("%s item","%s items",d),d):PodsI18n.__("Search")+" "+t.label+"...",allowClear:s,disabled:t.limitDisable,tags:t.pick_taggable,escapeMarkup:function(e){return e}},n.ajax&&jQuery.extend(e,{minimumInputLength:n.minimum_input_length,ajax:{url:ajaxurl+"?pods_ajax=1",type:"POST",dataType:"json",delay:n.delay,data:function(e){return{_wpnonce:n._wpnonce,action:"pods_relationship",method:"select2",pod:n.pod,field:n.field,uri:n.uri,id:n.id,query:e.term}},processResults:function(e,t){return i.filterAjaxList(e,t)}}}),l.selectWoo(jQuery.extend(!0,e,o)),(c=l.parent().find("ul.select2-selection__rendered")).sortable({containment:"parent"}),c.on("sortstop",function(){var e=c.find(".select2-selection__choice").get().reverse();jQuery(e).each(function(){var e=jQuery(this).data("data").id,t=l.find('option[value="'+e+'"]')[0];l.prepend(t)})})}}),O=c.extend({childViewEventPrefix:!1,tagName:"li",className:"pods-dfv-list-item pods-relationship",template:_.template('\n\t\t\tname="<%- htmlAttr.name %>" id="<%- htmlAttr.id %>"\n\t\t<% } else { %>\n\t\t\tname="<%- htmlAttr.name %>[<%= ordinal %>]" id="<%- htmlAttr.id %><%= ordinal %>"\n\t\t<% } %>\n\t\tdata-name-clean="<%- htmlAttr.name_clean %>" type="hidden" value="<%- id %>">\n
    \n\t<% if ( 1 != fieldConfig.pick_limit ) { %>\n\t\t
  • <%- PodsI18n.__( \'Reorder\' ) %>
  • \n\t<% } %>\n\t<% if ( 1 == fieldConfig.pick_show_icon ) { %>\n\t\t
  • \n\t\t\t<% if ( \'\' == icon ) { %>\n\t\t\t\t<% if ( /^dashicons/.test( fieldConfig.default_icon ) ) { %>\n\t\t\t\t\t\n\t\t\t\t<% } else { %>\n\t\t\t\t\tIcon\n\t\t\t\t<% } %>\n\t\t\t<% } else { %>\n\t\t\t\t<% if ( /^dashicons/.test( icon ) ) { %>\n\t\t\t\t\t\n\t\t\t\t<% } else { %>\n\t\t\t\t\tIcon\n\t\t\t\t<% } %>\n\t\t\t<% } %>\n\t\t
  • \n\t<% } %>\n\t
  • \n\t\t<%= name %>\n\t
  • \n\t
  • <%- PodsI18n.__( \'Deselect\' ) %>
  • \n\t<% if ( 1 == fieldConfig.pick_show_view_link && \'\' != link ) { %>\n\t\t\n\t<% } %>\n\t<% if ( 1 == fieldConfig.pick_show_edit_link && \'\' != edit_link ) { %>\n\t\t
  • <%- PodsI18n.__( \'Edit\' ) %>
  • \n\t<% } %>\n
\n'),ui:{removeButton:".pods-dfv-list-remove a",editButton:".pods-dfv-list-edit a"},triggers:{"click @ui.removeButton":"remove:item:click","click @ui.editButton":"edit:item:click"},templateContext:function(){return{ordinal:this.model.collection.indexOf(this.model)}}}),U=a.extend({childViewEventPrefix:!1,tagName:"ul",className:"pods-dfv-list pods-relationship",childView:O,childViewTriggers:{"remove:item:click":"childview:remove:item:click","edit:item:click":"childview:edit:item:click"},filter:function(e,t,i){return e.attributes.selected},onAttach:function(){1!==this.options.fieldModel.get("fieldConfig").pick_limit&&this.$el.sortable({containment:"parent",axis:"y",scrollSensitivity:40,tolerance:"pointer",opacity:.6})}}),F="button-disabled",R=c.extend({childViewEventPrefix:!1,tagName:"div",className:"podsform-dfv-list-relationship-container",ui:{addButton:"a.pods-related-add-new"},template:_.template('\n\t<%- PodsI18n.__( \'Add New\' ) %>\n'),triggers:{"click @ui.addButton":"add:new:click"},disable:function(){this.getUI("addButton").addClass(F)},enable:function(){this.getUI("addButton").removeClass(F)},onAddNewClick:function(){this.getUI("addButton").hasClass(F)||this.trigger("childview:add:new",this)}}),D={checkbox:L,select:B,select2:B,radio:j,list:U},Q=void 0,$=r.extend({childViewEventPrefix:!1,template:_.template('<%if ( fieldConfig.view_name === \'list\' ) { %>\n\t
\n<% } %>\n\n
\n\n<% if ( fieldConfig.iframe_src != \'\' ) { %>\n\t
\n<% } %>'),regions:{autocomplete:".pods-ui-list-autocomplete",list:".pods-pick-values",addNew:".pods-ui-add-new"},childViewEvents:{"childview:remove:item:click":"onChildviewRemoveItemClick","childview:edit:item:click":"onChildviewEditItemClick","childview:selection:limit:over":"onChildviewSelectionLimitOver","childview:selection:limit:under":"onChildviewSelectionLimitUnder","childview:change:selected":"onChildviewChangeSelected","childview:add:new":"onChildviewAddNew"},onBeforeRender:function(){void 0===this.collection&&(this.collection=new M(this.fieldItemData))},onRender:function(){this.fieldConfig=new A(this.model.get("fieldConfig")),""!==this.fieldConfig.get("iframe_src")&&1==this.fieldConfig.get("pick_allow_add_new")&&this.showAddNew(),"list"===this.fieldConfig.get("view_name")&&this.buildAutocomplete(),this.showList()},buildAutocomplete:function(){var e,t,i=void 0,l=void 0,n=+this.fieldConfig.get("pick_limit");i={view_name:"select2",pick_format_type:"multi",selectFromExisting:!0,ajax_data:this.fieldConfig.get("ajax_data"),select2_overrides:this.fieldConfig.get("select2_overrides"),label:this.fieldConfig.get("label"),pick_limit:n},this.collection.filterBySelected().length>=n&&0!==n?(i.limitDisable=!0,this.onChildviewSelectionLimitOver()):this.onChildviewSelectionLimitUnder(),e=new o({fieldConfig:i}),t=this.collection.filterByUnselected(),(l=new B({collection:t,fieldModel:e})).filterAjaxList=this.filterAjaxList.bind(this),this.showChildView("autocomplete",l)},showList:function(){var e,t;if(e=this.fieldConfig.get("view_name"),void 0===D[e])throw new Error('Invalid view name "'+e+'"');t=new D[e]({collection:this.collection,fieldModel:this.model}),this.showChildView("list",t)},showAddNew:function(){var e=new R({fieldModel:this.model});this.showChildView("addNew",e)},filterAjaxList:function(e){var t=this.collection.filterBySelected(),i=[];return _.each(e.results,function(e){e.text=e.name,t.get(e.id)||i.push(e)}),this.collection.add(i),this.getChildView("autocomplete").setCollection(this.collection.filterByUnselected()),{results:i}},onChildviewSelectionLimitOver:function(e){var t=this.getChildView("addNew");t&&t.disable()},onChildviewSelectionLimitUnder:function(e){var t=this.getChildView("addNew");t&&t.enable()},onChildviewRemoveItemClick:function(e){e.model.toggleSelected(),this.getChildView("list").render(),"list"===this.fieldConfig.get("view_name")&&this.buildAutocomplete()},onChildviewAddNew:function(e){var t=this.model.get("fieldConfig");Q=new S({title:t.iframe_title_add,src:t.iframe_src}),this.setModalListeners(),Q.modal.open()},onChildviewEditItemClick:function(e){var t=this.model.get("fieldConfig");Q=new S({title:t.iframe_title_edit,src:e.ui.editButton.attr("href")}),this.setModalListeners(),Q.modal.open()},onChildviewChangeSelected:function(e){e.fieldConfig.selectFromExisting&&(_.defer(this.buildAutocomplete.bind(this)),this.getChildView("list").render())},setModalListeners:function(){jQuery(window).on("dfv:modal:update",this.modalSuccess.bind(this)),jQuery(window).on("dfv:modal:cancel",this.modalCancel.bind(this))},clearModalListeners:function(){jQuery(window).off("dfv:modal:update"),jQuery(window).off("dfv:modal:cancel")},modalSuccess:function(e,t){var i=this.collection.get(t.id);i?(i.set(t),this.getChildView("list").render()):this.collection.add(t),this.clearModalListeners(),Q.modal.close({})},modalCancel:function(){this.clearModalListeners()}}),z={file:y,avatar:y,pick:$},T={fields:Object.freeze({FileUpload:y,Pick:$}),models:Object.freeze({PodsDFVFieldModel:o,RelationshipModel:P,RelationshipCollection:M,FileUploadModel:f,FileUploadCollection:h}),fieldInstances:{},init:function(){var l=this;jQuery(".pods-form-ui-field").each(function(){var e=void 0,t=void 0,i={fieldType:void 0};jQuery(this).find("script.pods-dfv-field-data").each(function(){var e=jQuery.parseJSON(jQuery(this).html());jQuery(this).parents(".media-modal-content").length&&(e.fieldConfig.pick_allow_add_new=0),jQuery.extend(i,e),jQuery(this).remove()}),void 0!==i.fieldType&&void 0!==(e=z[i.fieldType])&&((t=new e({el:this,model:new o({htmlAttr:i.htmlAttr,fieldConfig:i.fieldConfig}),fieldItemData:i.fieldItemData})).render(),jQuery(this).trigger("render"),l.fieldInstances[i.htmlAttr.id]=t)})},isModalWindow:function(){return-1!==location.search.indexOf("pods_modal=")},isGutenbergEditorLoaded:function(){return void 0!==wp.data&&void 0!==wp.data.select("core/editor")}};return document.addEventListener("DOMContentLoaded",function(){T.init(),T.isModalWindow()&&T.isGutenbergEditorLoaded()&&t()}),T}(); //# sourceMappingURL=pods-dfv.min.js.map diff --git a/ui/js/pods-dfv/pods-dfv.min.js.map b/ui/js/pods-dfv/pods-dfv.min.js.map index 1edefc56d5..80614f2040 100755 --- a/ui/js/pods-dfv/pods-dfv.min.js.map +++ b/ui/js/pods-dfv/pods-dfv.min.js.map @@ -1 +1 @@ -{"version":3,"file":"pods-dfv.min.js","sources":["_src/core/pods-field-model.js","_src/core/gb-modal-listener.js","_src/core/pods-field-views.js","_src/file-upload/file-upload-model.js","_src/file-upload/views/file-upload-list.js","_src/file-upload/views/file-upload-form.js","_src/file-upload/uploaders/pods-file-uploader.js","_src/file-upload/views/file-upload-queue.js","_src/file-upload/file-upload.js","_src/file-upload/uploaders/plupload.js","_src/file-upload/uploaders/media-modal.js","_src/core/dfv-modal.js","_src/core/iframe-frame.js","_src/pick/relationship-model.js","_src/pick/pick-field-model.js","_src/pick/views/radio-view.js","_src/pick/views/checkbox-view.js","_src/pick/views/select-view.js","_src/pick/views/list-view.js","_src/pick/views/add-new.js","_src/pick/pick.js","_src/pods-dfv.js"],"sourcesContent":["/*global jQuery, _, Backbone, Marionette */\nexport const PodsDFVFieldModel = Backbone.Model.extend( {\n\tdefaults: {\n\t\thtmlAttr: {},\n\t\tfieldConfig: {}\n\t}\n} );\n","/**\n * Note: No checking is done here to make sure we're in a modal and that\n * Gutenberg is actually loaded. Consuming code must make sure the implicit\n * Gutenberg dependencies exist (primarily wp.data) before calling through\n * to init().\n */\n\n// The guard in front is to ensure wp.data exists before accessing select\nconst editorData = wp.data && wp.data.select( 'core/editor' );\nlet unSubscribe;\n\n/**\n * init() is the only exposed interface\n */\nexport const PodsGbModalListener = {\n\tinit: function () {\n\t\tif ( editorData.isCurrentPostPublished() ) {\n\t\t\t// Post is published, this is an edit\n\t\t\tunSubscribe = wp.data.subscribe( saveListener );\n\t\t} else {\n\t\t\t// Unpublished post, this is an \"add new\" modal\n\t\t\tunSubscribe = wp.data.subscribe( publishListener );\n\t\t}\n\t}\n};\n\n//-------------------------------------------\n// Helper functions, not externally exposed\n//-------------------------------------------\n\n/**\n *\n * @return string\n */\nfunction getFeaturedImageURL () {\n\tconst featuredImageId = editorData.getCurrentPostAttribute( 'featured_media' );\n\tlet url = '';\n\n\t// Early exit if nothing was set\n\tif ( !featuredImageId ) {\n\t\treturn url;\n\t}\n\n\tconst media = wp.data.select( 'core' ).getMedia( featuredImageId );\n\n\tif ( media ) {\n\t\tconst mediaSize = wp.hooks.applyFilters( 'editor.PostFeaturedImage.imageSize', 'post-thumbnail', '' );\n\t\tif ( media.media_details && media.media_details.sizes && media.media_details.sizes[ mediaSize ] ) {\n\t\t\turl = media.media_details.sizes[ mediaSize ].source_url;\n\t\t} else {\n\t\t\turl = media.source_url;\n\t\t}\n\t}\n\n\treturn url;\n}\n\n/**\n * Handles \"add new\" modals\n */\nfunction publishListener () {\n\n\tif ( editorData.isCurrentPostPublished() ) {\n\t\tunSubscribe();\n\n\t\ttriggerUpdateEvent( {\n\t\t\t'icon': getFeaturedImageURL(),\n\t\t\t'link': editorData.getPermalink(),\n\t\t\t'edit_link': `post.php?post=${editorData.getCurrentPostId()}&action=edit&pods_modal=1`,\n\t\t\t'selected': true // Automatically select add new records\n\t\t} );\n\t}\n}\n\n/**\n * Handles \"edit existing\" modals\n */\nfunction saveListener () {\n\n\tif ( saveListener.wasSaving ) {\n\n\t\t// The wasSaving flag already ignores autosave so we only need to\n\t\t// check isSavingPost()\n\t\tif ( !editorData.isSavingPost() ) {\n\n\t\t\t// Currently on save failure we'll remain subscribed and try\n\t\t\t// listening for the next save attempt\n\t\t\tsaveListener.wasSaving = false;\n\n\t\t\tif ( editorData.didPostSaveRequestSucceed() ) {\n\t\t\t\tunSubscribe();\n\t\t\t\ttriggerUpdateEvent( {\n\t\t\t\t\t'icon': getFeaturedImageURL()\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t} else {\n\t\tsaveListener.wasSaving = isUserSaving();\n\t}\n}\n\n/**\n * Whether or not an active save is in progress due to user action (ignore autosaves)\n *\n * @return boolean\n */\nfunction isUserSaving () {\n\treturn !!( editorData.isSavingPost() && !editorData.isAutosavingPost() );\n}\n\n/**\n * The event listener in the parent window will take care of closing the modal\n */\nfunction triggerUpdateEvent ( optionalData ) {\n\tconst defaultData = {\n\t\t'id': editorData.getCurrentPostId(),\n\t\t'name': editorData.getCurrentPostAttribute( 'title' )\n\t};\n\tconst postData = Object.assign( defaultData, optionalData );\n\n\twindow.parent.jQuery( window.parent ).trigger( 'dfv:modal:update', postData );\n}\n","/*global jQuery, _, Backbone, Marionette */\n\n/**\n *\n */\nexport const PodsFieldListView = Marionette.CollectionView.extend( {\n\tchildViewEventPrefix: false, // Disable implicit event listeners in favor of explicit childViewTriggers and childViewEvents\n\n\tinitialize: function ( options ) {\n\t\tthis.fieldModel = options.fieldModel;\n\t\tthis.childViewOptions = { fieldModel: options.fieldModel };\n\t}\n} );\n\n/**\n * @extends Backbone.View\n */\nexport const PodsFieldView = Marionette.View.extend( {\n\tchildViewEventPrefix: false, // Disable implicit event listeners in favor of explicit childViewTriggers and childViewEvents\n\n\tserializeData: function () {\n\t\tconst fieldModel = this.options.fieldModel;\n\t\tlet data = this.model ? this.model.toJSON() : {};\n\n\t\tdata.htmlAttr = fieldModel.get( 'htmlAttr' );\n\t\tdata.fieldConfig = fieldModel.get( 'fieldConfig' );\n\n\t\treturn data;\n\t}\n} );\n\n/**\n * Top-level \"main field container\"\n */\nexport const PodsDFVFieldLayout = Marionette.View.extend( {\n\tchildViewEventPrefix: false, // Disable implicit event listeners in favor of explicit childViewTriggers and childViewEvents\n\n\tinitialize: function ( options ) {\n\t\tthis.fieldItemData = options.fieldItemData;\n\t}\n} );\n","/*global jQuery, _, Backbone, Marionette */\n/**\n *\n */\nexport const FileUploadModel = Backbone.Model.extend( {\n\tdefaults: {\n\t\t'id': 0,\n\t\t'icon': '',\n\t\t'name': '',\n\t\t'edit_link': '',\n\t\t'link': '',\n\t\t'download': ''\n\t}\n} );\n\n/**\n *\n */\nexport const FileUploadCollection = Backbone.Collection.extend( {\n\tmodel: FileUploadModel\n} );\n","/*global jQuery, _, Backbone, Marionette, wp */\nimport template from 'pods-dfv/_src/file-upload/views/file-upload-item.html';\n\nimport { PodsFieldListView, PodsFieldView } from 'pods-dfv/_src/core/pods-field-views';\n\n/**\n * Individual list items, representing a single file\n */\nexport const FileUploadItem = PodsFieldView.extend( {\n\tchildViewEventPrefix: false, // Disable implicit event listeners in favor of explicit childViewTriggers and childViewEvents\n\n\ttagName: 'li',\n\n\ttemplate: _.template( template ),\n\n\tclassName: 'pods-dfv-list-item',\n\n\tui: {\n\t\tdragHandle: '.pods-dfv-list-handle',\n\t\teditLink: '.pods-dfv-list-edit-link',\n\t\tviewLink: '.pods-dfv-list-link',\n\t\tdownloadLink: '.pods-dfv-list-download',\n\t\tremoveButton: '.pods-dfv-list-remove',\n\t\titemName: '.pods-dfv-list-name'\n\t},\n\n\ttriggers: {\n\t\t'click @ui.removeButton': 'remove:file:click'\n\t}\n} );\n\n/**\n * The file list container\n */\nexport const FileUploadList = PodsFieldListView.extend( {\n\tchildViewEventPrefix: false, // Disable implicit event listeners in favor of explicit childViewTriggers and childViewEvents\n\n\ttagName: 'ul',\n\n\tclassName: 'pods-dfv-list',\n\n\tchildView: FileUploadItem,\n\n\tchildViewTriggers: {\n\t\t'remove:file:click': 'childview:remove:file:click'\n\t},\n\n\tonAttach: function () {\n\t\tconst fieldConfig = this.options.fieldModel.get( 'fieldConfig' );\n\t\tlet sort_axis = 'y';\n\n\t\t// @todo\n\t\t// http://stackoverflow.com/questions/1735372/jquery-sortable-list-scroll-bar-jumps-up-when-sorting/4187833#4187833\n\n\t\tif ( 1 != fieldConfig[ 'file_limit' ] ) {\n\n\t\t\tif ( 'tiles' == fieldConfig[ 'file_field_template' ] ) {\n\t\t\t\tsort_axis = '';\n\t\t\t}\n\n\t\t\t// init sortable\n\t\t\tthis.$el.sortable( {\n\t\t\t\tcontainment: 'parent',\n\t\t\t\taxis: sort_axis,\n\t\t\t\tscrollSensitivity: 40,\n\t\t\t\ttolerance: 'pointer',\n\t\t\t\topacity: 0.6\n\t\t\t} );\n\t\t}\n\t}\n} );\n\n","/*global jQuery, _, Backbone, Marionette, wp */\nimport template from 'pods-dfv/_src/file-upload/views/file-upload-form.html';\n\nimport { PodsFieldView } from 'pods-dfv/_src/core/pods-field-views';\n\nexport const FileUploadForm = PodsFieldView.extend( {\n\tchildViewEventPrefix: false, // Disable implicit event listeners in favor of explicit childViewTriggers and childViewEvents\n\n\ttagName: 'div',\n\n\ttemplate: _.template( template ),\n\n\tui: {\n\t\taddButton: '.pods-dfv-list-add'\n\t},\n\n\ttriggers: {\n\t\t'click @ui.addButton': 'childview:add:file:click'\n\t}\n} );\n","/*global jQuery, _, Backbone, Marionette */\n/**\n *\n * @param {Object} options\n *\n * @param {Object} options.browseButton Existing and attached DOM node\n * @param {Object} options.uiRegion Marionette.Region object\n * @param {Object} options.fieldConfig\n *\n * @param {string} options.fieldConfig.file_modal_title\n * @param {string} options.fieldConfig.file_modal_add_button\n * @param {string} options.fieldConfig.file_limit\n * @param {string} options.fieldConfig.limit_extensions\n * @param {string} options.fieldConfig.limit_types\n * @param {string} options.fieldConfig.file_attachment_tab\n *\n * @param {Object} options.fieldConfig.plupload_init\n * @param {Object} options.fieldConfig.plupload_init.browse_button\n *\n * @class\n */\nexport const PodsFileUploader = Marionette.Object.extend( {\n\n\tconstructor: function ( options ) {\n\t\t// Magically set the object properties we need, they'll just \"be there\" for the concrete instance\n\t\tthis.browseButton = options.browseButton;\n\t\tthis.uiRegion = options.uiRegion;\n\t\tthis.fieldConfig = options.fieldConfig;\n\n\t\tMarionette.Object.call( this, options );\n\t}\n\n} );\n\n","/*global jQuery, _, Backbone, Marionette, wp */\nimport template from 'pods-dfv/_src/file-upload/views/file-upload-queue.html';\n\nexport const FileUploadQueueModel = Backbone.Model.extend( {\n\tdefaults: {\n\t\tid: 0,\n\t\tfilename: '',\n\t\tprogress: 0,\n\t\terrorMsg: ''\n\t}\n} );\n\n/**\n *\n */\nexport const FileUploadQueueItem = Marionette.View.extend( {\n\tmodel: FileUploadQueueModel,\n\n\ttagName: 'li',\n\n\ttemplate: _.template( template ),\n\n\tattributes: function () {\n\t\treturn {\n\t\t\tclass: 'pods-dfv-list-item',\n\t\t\tid: this.model.get( 'id' )\n\t\t};\n\t},\n\n\tmodelEvents: {\n\t\t'change': 'onModelChanged'\n\t},\n\n\tonModelChanged: function () {\n\t\tthis.render();\n\t}\n\n} );\n\n/**\n *\n */\nexport const FileUploadQueue = Marionette.CollectionView.extend( {\n\ttagName: 'ul',\n\n\tclassName: 'pods-dfv-list pods-dfv-list-queue',\n\n\tchildView: FileUploadQueueItem\n} );\n","/*global jQuery, _, Backbone, Marionette */\nimport template from 'pods-dfv/_src/file-upload/file-upload-layout.html';\n\nimport { PodsDFVFieldLayout } from 'pods-dfv/_src/core/pods-field-views';\n\nimport { FileUploadCollection } from 'pods-dfv/_src/file-upload/file-upload-model';\n\nimport { FileUploadList } from 'pods-dfv/_src/file-upload/views/file-upload-list';\nimport { FileUploadForm } from 'pods-dfv/_src/file-upload/views/file-upload-form';\n\nimport { Plupload } from 'pods-dfv/_src/file-upload/uploaders/plupload';\nimport { MediaModal } from 'pods-dfv/_src/file-upload/uploaders/media-modal';\n\nconst Uploaders = [\n\tPlupload,\n\tMediaModal\n];\n\nconst UNLIMITED_FILES = 0;\n\n/**\n * @extends Backbone.View\n */\nexport const FileUpload = PodsDFVFieldLayout.extend( {\n\tchildViewEventPrefix: false, // Disable implicit event listeners in favor of explicit childViewTriggers and childViewEvents\n\n\ttemplate: _.template( template ),\n\n\tregions: {\n\t\tlist: '.pods-ui-file-list',\n\t\tuiRegion: '.pods-ui-region', // \"Utility\" container for uploaders to use\n\t\tform: '.pods-ui-form'\n\t},\n\n\tchildViewEvents: {\n\t\t'childview:remove:file:click': 'onChildviewRemoveFileClick',\n\t\t'childview:add:file:click': 'onChildviewAddFileClick'\n\t},\n\n\tuploader: {},\n\n\t/**\n\t *\n\t */\n\tonBeforeRender: function () {\n\t\tif ( this.collection === undefined ) {\n\t\t\tthis.collection = new FileUploadCollection( this.fieldItemData );\n\t\t}\n\t},\n\n\tonRender: function () {\n\t\tconst listView = new FileUploadList( { collection: this.collection, fieldModel: this.model } );\n\t\tconst formView = new FileUploadForm( { fieldModel: this.model } );\n\n\t\tthis.showChildView( 'list', listView );\n\t\tthis.showChildView( 'form', formView );\n\n\t\t// Setup the uploader and listen for a response event\n\t\tthis.uploader = this.createUploader();\n\t\tthis.listenTo( this.uploader, 'added:files', this.onAddedFiles );\n\t},\n\n\t/**\n\t * Fired by a remove:file:click trigger in any child view\n\t *\n\t * @param childView View that was the source of the event\n\t */\n\tonChildviewRemoveFileClick: function ( childView ) {\n\t\tthis.collection.remove( childView.model );\n\t},\n\n\t/**\n\t * Fired by a add:file:click trigger in any child view\n\t *\n\t * plupload fields should never generate this event, it places a shim over our button and handles the\n\t * event internally. But this event does still come through with plupload fields in some browser\n\t * environments for reasons we've been unable to determine.\n\t */\n\tonChildviewAddFileClick: function () {\n\n\t\t// Invoke the uploader\n\t\tif ( 'function' === typeof this.uploader.invoke ) {\n\t\t\tthis.uploader.invoke();\n\t\t}\n\t},\n\n\t/**\n\t * Concrete uploader implementations simply need to: this.trigger( 'added:files', newFiles )\n\t *\n\t * @param {Object[]} data An array of model objects to be added\n\t */\n\tonAddedFiles: function ( data ) {\n\t\tconst fieldConfig = this.model.get( 'fieldConfig' );\n\t\tconst fileLimit = +fieldConfig[ 'file_limit' ]; // Unary plus to force to number\n\t\tlet newCollection, filteredModels;\n\n\t\t// Get a copy of the existing collection with the new files added\n\t\tnewCollection = this.collection.clone();\n\t\tnewCollection.add( data );\n\n\t\t// Enforce the file limit option if one is set\n\t\tif ( UNLIMITED_FILES === fileLimit ) {\n\t\t\tfilteredModels = newCollection.models;\n\t\t} else {\n\t\t\t// Number of uploads is limited: keep the last N models, FIFO/queue style\n\t\t\tfilteredModels = newCollection.filter( function ( model ) {\n\t\t\t\treturn ( newCollection.indexOf( model ) >= newCollection.length - fileLimit );\n\t\t\t} );\n\t\t}\n\n\t\tthis.collection.reset( filteredModels );\n\t},\n\n\tcreateUploader: function () {\n\t\tconst fieldConfig = this.model.get( 'fieldConfig' );\n\t\tconst targetUploader = fieldConfig[ 'file_uploader' ];\n\t\tlet Uploader;\n\n\t\tjQuery.each( Uploaders, function ( index, thisUploader ) {\n\t\t\tif ( targetUploader === thisUploader.prototype.fileUploader ) {\n\t\t\t\tUploader = thisUploader;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} );\n\n\t\tif ( Uploader !== undefined ) {\n\t\t\tthis.uploader = new Uploader( {\n\t\t\t\t// We provide regular DOM element for the button\n\t\t\t\tbrowseButton: this.getRegion( 'form' ).getEl( '.pods-dfv-list-add' ).get(),\n\t\t\t\tuiRegion: this.getRegion( 'uiRegion' ),\n\t\t\t\tfieldConfig: fieldConfig\n\t\t\t} );\n\t\t\treturn this.uploader;\n\t\t} else {\n\t\t\t// @todo sprintf type with PodsI18n.__()\n\t\t\tthrow `Could not locate file uploader '${targetUploader}'`;\n\t\t}\n\t}\n} );\n","/* eslint-disable camelcase */\n/*global jQuery, _, Backbone, Marionette, wp, plupload, PodsI18n */\nimport { PodsFileUploader } from 'pods-dfv/_src/file-upload/uploaders/pods-file-uploader';\nimport { FileUploadQueueModel, FileUploadQueue } from 'pods-dfv/_src/file-upload/views/file-upload-queue';\n\nexport const Plupload = PodsFileUploader.extend( {\n\tplupload: {},\n\n\tfileUploader: 'plupload',\n\n\tinitialize: function () {\n\t\t// Set the browse button argument for plupload... it's required\n\t\tthis.fieldConfig[ 'plupload_init' ][ 'browse_button' ] = this.browseButton;\n\n\t\tthis.plupload = new plupload.Uploader( this.fieldConfig[ 'plupload_init' ] );\n\t\tthis.plupload.init();\n\n\t\t// Setup all callbacks: ( event_name, callback, context )\n\t\tthis.plupload.bind( 'FilesAdded', this.onFilesAdded, this );\n\t\tthis.plupload.bind( 'UploadProgress', this.onUploadProgress, this );\n\t\tthis.plupload.bind( 'FileUploaded', this.onFileUploaded, this );\n\t},\n\n\t/**\n\t * Fired after files have been selected from the dialog\n\t *\n\t * @param up\n\t * @param files\n\t */\n\tonFilesAdded: function ( up, files ) {\n\t\tlet model,\n\t\t\tcollection,\n\t\t\tview;\n\n\t\t// Assemble the collection data for the file queue\n\t\tcollection = new Backbone.Collection();\n\t\tjQuery.each( files, function ( index, file ) {\n\t\t\tmodel = new FileUploadQueueModel( {\n\t\t\t\tid: file.id,\n\t\t\t\tfilename: file.name\n\t\t\t} );\n\n\t\t\tcollection.add( model );\n\t\t} );\n\n\t\t// Create a new view based on the collection\n\t\tview = new FileUploadQueue( { collection: collection } );\n\t\tview.render(); // Generate the HTML, not attached to the DOM yet\n\n\t\t// Reset the region in case any error messages are hanging around from a previous upload\n\t\t// and show the new file upload queue\n\t\tthis.uiRegion.reset();\n\t\tthis.uiRegion.show( view );\n\n\t\t// Stash references\n\t\tthis.queueCollection = collection;\n\n\t\tup.refresh();\n\t\tup.start();\n\t},\n\n\t/**\n\t *\n\t * @param up\n\t * @param file\n\t */\n\tonUploadProgress: function ( up, file ) {\n\t\tconst model = this.queueCollection.get( file.id );\n\t\tmodel.set( { progress: file.percent } );\n\t},\n\n\t/**\n\t *\n\t * @param up\n\t * @param file\n\t * @param resp\n\t */\n\tonFileUploaded: function ( up, file, resp ) {\n\t\tconst model = this.queueCollection.get( file.id );\n\t\tlet response = resp.response;\n\t\tlet newFile = [];\n\t\tlet json;\n\n\t\t// Error condition 1\n\t\tif ( 'Error: ' === resp.response.substr( 0, 7 ) ) {\n\t\t\tresponse = response.substr( 7 );\n\t\t\tif ( window.console ) {\n\t\t\t\tconsole.log( response );\n\t\t\t}\n\n\t\t\tmodel.set( {\n\t\t\t\tprogress: 0,\n\t\t\t\terrorMsg: response\n\t\t\t} );\n\n\t\t\t// Error condition 2\n\t\t} else if ( '' === resp.response.substr( 0, 3 ) ) {\n\t\t\tresponse = jQuery( response ).text(); // Strip tags, text only\n\t\t\tif ( window.console ) {\n\t\t\t\tconsole.log( response );\n\t\t\t}\n\n\t\t\tmodel.set( {\n\t\t\t\tprogress: 0,\n\t\t\t\terrorMsg: response\n\t\t\t} );\n\t\t} else {\n\t\t\tjson = response.match( /{.*}$/ );\n\n\t\t\tif ( null !== json && 0 < json.length ) {\n\t\t\t\tjson = jQuery.parseJSON( json[ 0 ] );\n\t\t\t} else {\n\t\t\t\tjson = {};\n\t\t\t}\n\n\t\t\tif ( 'object' !== typeof json || jQuery.isEmptyObject( json ) ) {\n\t\t\t\tif ( window.console ) {\n\t\t\t\t\tconsole.log( response );\n\t\t\t\t}\n\t\t\t\tif ( window.console ) {\n\t\t\t\t\tconsole.log( json );\n\t\t\t\t}\n\n\t\t\t\tmodel.set( {\n\t\t\t\t\tprogress: 0,\n\t\t\t\t\terrorMsg: PodsI18n.__( 'Error uploading file: ' ) + file.name\n\t\t\t\t} );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tnewFile = {\n\t\t\t\tid: json.ID,\n\t\t\t\ticon: json.thumbnail,\n\t\t\t\tname: json.post_title,\n\t\t\t\tedit_link: json.edit_link,\n\t\t\t\tlink: json.link,\n\t\t\t\tdownload: json.download\n\t\t\t};\n\n\t\t\t// Remove the file from the upload queue model and trigger an event for the hosting container\n\t\t\tmodel.trigger( 'destroy', model );\n\t\t\tthis.trigger( 'added:files', newFile );\n\t\t}\n\t}\n\n} );\n\n","/* eslint-disable camelcase */\n/*global jQuery, _, Backbone, Marionette, wp, PodsI18n */\nimport { PodsFileUploader } from 'pods-dfv/_src/file-upload/uploaders/pods-file-uploader';\n\nexport const MediaModal = PodsFileUploader.extend( {\n\tmediaObject: {},\n\n\tfileUploader: 'attachment',\n\n\tinvoke: function () {\n\n\t\tif ( wp.Uploader.defaults.filters.mime_types === undefined ) {\n\t\t\twp.Uploader.defaults.filters.mime_types = [ {\n\t\t\t\ttitle: PodsI18n.__( 'Allowed Files' ),\n\t\t\t\textensions: '*'\n\t\t\t} ];\n\t\t}\n\n\t\tlet defaultExt = wp.Uploader.defaults.filters.mime_types[ 0 ].extensions;\n\n\t\twp.Uploader.defaults.filters.mime_types[ 0 ].extensions = this.fieldConfig[ 'limit_extensions' ];\n\n\t\t// set our settings\n\t\t// noinspection EqualityComparisonWithCoercionJS (\"1\" is every bit as valid to us as 1)\n\t\tthis.mediaObject = wp.media( {\n\t\t\ttitle: this.fieldConfig[ 'file_modal_title' ],\n\t\t\tmultiple: ( 1 != this.fieldConfig[ 'file_limit' ] ),\n\t\t\tlibrary: {\n\t\t\t\ttype: this.fieldConfig[ 'limit_types' ]\n\t\t\t},\n\t\t\t// Customize the submit button.\n\t\t\tbutton: {\n\t\t\t\t// Set the text of the button.\n\t\t\t\ttext: this.fieldConfig[ 'file_modal_add_button' ]\n\t\t\t}\n\t\t} );\n\n\t\t// One-shot callback ( event, callback, context )\n\t\tthis.mediaObject.once( 'select', this.onMediaSelect, this );\n\n\t\t// open the frame\n\t\tthis.mediaObject.open();\n\t\tthis.mediaObject.content.mode( this.fieldConfig[ 'file_attachment_tab' ] );\n\n\t\t// Reset the allowed file extensions\n\t\twp.Uploader.defaults.filters.mime_types[ 0 ].extensions = defaultExt;\n\t},\n\n\tonMediaSelect: function () {\n\t\tconst selection = this.mediaObject.state().get( 'selection' );\n\t\tlet newFiles = [];\n\n\t\tif ( !selection ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// loop through the selected files\n\t\tselection.each( function ( attachment ) {\n\t\t\tconst sizes = attachment.attributes.sizes;\n\t\t\tlet attachmentThumbnail;\n\n\t\t\t// by default use the generic icon\n\t\t\tattachmentThumbnail = attachment.attributes.icon;\n\n\t\t\t// only thumbnails have sizes which is what we're on the hunt for\n\t\t\tif ( sizes !== undefined ) {\n\t\t\t\t// Get thumbnail if it exists\n\t\t\t\tif ( sizes.thumbnail !== undefined && sizes.thumbnail.url !== undefined ) {\n\t\t\t\t\tattachmentThumbnail = sizes.thumbnail.url;\n\t\t\t\t} else if ( sizes.full !== undefined && sizes.full.url !== undefined ) {\n\t\t\t\t\t// If thumbnail doesn't exist, get full because this is a small image\n\t\t\t\t\tattachmentThumbnail = sizes.full.url;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tnewFiles.push( {\n\t\t\t\tid: attachment.attributes.id,\n\t\t\t\ticon: attachmentThumbnail,\n\t\t\t\tname: attachment.attributes.title,\n\t\t\t\tedit_link: attachment.attributes.editLink,\n\t\t\t\tlink: attachment.attributes.link,\n\t\t\t\tdownload: attachment.attributes.url\n\t\t\t} );\n\t\t} );\n\n\t\t// Fire an event with an array of models to be added\n\t\tthis.trigger( 'added:files', newFiles );\n\t}\n\n} );\n","/*global jQuery, _, Backbone, Marionette, wp, PodsI18n */\n\n/**\n * A frame for displaying a modal popup with iframe content\n *\n * @augments wp.media.view.Frame\n */\nexport const PodsDFVModal = wp.media.view.Modal.extend( {\n\n\t/**\n\t * @param {Object} options\n\t * @returns {wp.media.view.Modal} Returns itself to allow chaining\n\t */\n\tclose: function ( options ) {\n\t\tconst retVal = wp.media.view.Modal.prototype.close.apply( this, options );\n\n\t\t// Alert the listening control when we've been cancelled\n\t\tif ( options && options.escape ) {\n\t\t\twindow.parent.jQuery( window.parent ).trigger( 'dfv:modal:cancel' );\n\t\t}\n\n\t\treturn retVal;\n\t}\n\n} );\n","/*global jQuery, _, Backbone, Marionette, wp, PodsI18n */\n\nimport { PodsDFVModal } from 'pods-dfv/_src/core/dfv-modal';\n\n/**\n * A frame for displaying a modal popup with iframe content\n *\n * @augments wp.media.view.Frame\n */\nexport const IframeFrame = wp.media.view.Frame.extend( {\n\tclassName: 'pods-modal-frame',\n\n\ttemplate: _.template( '
' ),\n\n\tregions: [ 'title', 'iframe' ],\n\n\tinitialize: function () {\n\t\twp.media.view.Frame.prototype.initialize.apply( this, arguments );\n\n\t\t// Ensure core UI is enabled.\n\t\tthis.$el.addClass( 'wp-core-ui' );\n\n\t\tthis.initState();\n\t\tthis.initModal();\n\n\t\tthis.on( 'iframe:create:default', this.iframeContent, this );\n\t\tthis.iframe.mode( 'default' );\n\n\t\tthis.on( 'title:create:default', this.createTitle, this );\n\t\tthis.title.mode( 'default' );\n\t\tthis.on( 'title:render', function ( view ) {\n\t\t\tview.$el.append( '' );\n\t\t} );\n\t},\n\n\tinitState: function () {\n\t\tconst title = this.options.title || PodsI18n.__( 'Add New Record' );\n\t\tconst src = this.options.src || '/';\n\n\t\tthis.states.add( [\n\t\t\tnew wp.media.controller.State( {\n\t\t\t\tid: 'default',\n\t\t\t\ttitle: title,\n\t\t\t\tsrc: src\n\t\t\t} )\n\t\t] );\n\n\t\tthis.options.state = 'default';\n\t},\n\n\tinitModal: function () {\n\t\tthis.modal = new PodsDFVModal( {\n\t\t\tcontroller: this\n\t\t} );\n\n\t\tthis.modal.content( this );\n\t},\n\n\trender: function () {\n\t\t// Activate the default state if no active state exists.\n\t\tif ( !this.state() && this.options.state ) {\n\t\t\tthis.setState( this.options.state );\n\t\t}\n\n\t\t/**\n\t\t * call 'render' directly on the parent class\n\t\t */\n\t\treturn wp.media.view.Frame.prototype.render.apply( this, arguments );\n\t},\n\n\t/**\n\t * @param {Object} content\n\t * @this wp.media.controller.Region\n\t */\n\tiframeContent: function ( content ) {\n\t\tcontent.view = new wp.media.view.Iframe( {\n\t\t\tcontroller: this\n\t\t} );\n\t},\n\n\tcreateTitle: function ( title ) {\n\t\ttitle.view = new wp.media.View( {\n\t\t\tcontroller: this,\n\t\t\ttagName: 'h1'\n\t\t} );\n\t}\n} );\n","/*global jQuery, _, Backbone, Marionette */\n\n/**\n *\n */\nexport const RelationshipModel = Backbone.Model.extend( {\n\tdefaults: {\n\t\t'id': 0,\n\t\t'name': '',\n\t\t'icon': '',\n\t\t'link': '',\n\t\t'edit_link': '',\n\t\t'selected': false\n\t},\n\n\ttoggleSelected: function () {\n\t\tthis.set( 'selected', !this.get( 'selected' ) );\n\t}\n} );\n\n/**\n *\n */\nexport const RelationshipCollection = Backbone.Collection.extend( {\n\tmodel: RelationshipModel,\n\n\t/**\n\t *\n\t * @param { ?string[] } ids\n\t */\n\tsetSelected: function ( ids ) {\n\t\tthis.map( function ( thisModel ) {\n\t\t\tconst selected = _.contains( ids, thisModel.get( 'id' ) + '' );\n\t\t\tthisModel.set( 'selected', selected );\n\t\t} );\n\t},\n\n\t/**\n\t * Return a new collection containing just the selected items in this one\n\t *\n\t * @returns {*}\n\t */\n\tfilterBySelected: function () {\n\n\t\t// Get an array with only the selected items\n\t\tconst filtered = this.filter( function ( itemModel ) {\n\t\t\treturn ( itemModel.get( 'selected' ) );\n\t\t} );\n\n\t\t// this.filter is going to return an array, so create a collection out of it\n\t\treturn new RelationshipCollection( filtered );\n\t},\n\n\t/**\n\t * Return a new collection containing just the unselected items in this one\n\t *\n\t * @returns {*}\n\t */\n\tfilterByUnselected: function () {\n\n\t\t// Get an array with only the unselected items\n\t\tconst filtered = this.filter( function ( itemModel ) {\n\t\t\treturn !( itemModel.get( 'selected' ) );\n\t\t} );\n\n\t\t// this.filter is going to return an array, so create a collection out of it\n\t\treturn new RelationshipCollection( filtered );\n\t}\n\n} );\n\n","/*global jQuery, _, Backbone, Marionette */\n\nexport const PickFieldModel = Backbone.Model.extend( {\n\tdefaults: {\n\t\t'view_name': 'select',\n\t\t'iframe_src': '',\n\t\t'pick_format_type': 'single',\n\t\t'pick_show_icon': false,\n\t\t'pick_show_view_link': false,\n\t\t'pick_show_edit_link': false\n\t}\n} );\n","/*global jQuery, _, Backbone, Marionette, wp */\nimport template from 'pods-dfv/_src/pick/views/radio-item.html';\n\nimport { PodsFieldListView, PodsFieldView } from 'pods-dfv/_src/core/pods-field-views';\n\n/**\n *\n */\nexport const RadioItem = PodsFieldView.extend( {\n\tchildViewEventPrefix: false, // Disable implicit event listeners in favor of explicit childViewTriggers and childViewEvents\n\n\ttagName: 'li',\n\n\ttemplate: _.template( template ),\n\n\ttemplateContext: function () {\n\t\treturn {\n\t\t\tordinal: this.model.collection.indexOf( this.model ) + 1 // One based indexing unlike checkboxes\n\t\t};\n\t},\n\n\tmodelChanged: function () {\n\t\tthis.render();\n\t}\n\n} );\n\n/**\n *\n */\nexport const RadioView = PodsFieldListView.extend( {\n\tchildViewEventPrefix: false, // Disable implicit event listeners in favor of explicit childViewTriggers and childViewEvents\n\n\ttagName: 'ul',\n\n\tclassName: 'pods-radio',\n\n\tchildView: RadioItem\n} );\n","/*global jQuery, _, Backbone, Marionette, wp */\nimport template from 'pods-dfv/_src/pick/views/checkbox-item.html';\n\nimport { PodsFieldListView, PodsFieldView } from 'pods-dfv/_src/core/pods-field-views';\n\n/**\n *\n */\nexport const CheckboxItem = PodsFieldView.extend( {\n\tchildViewEventPrefix: false, // Disable implicit event listeners in favor of explicit childViewTriggers and childViewEvents\n\n\ttagName: 'li',\n\n\ttemplate: _.template( template ),\n\n\tclassName: 'pods-pick',\n\n\tui: {\n\t\tcheckbox: 'input.pods-form-ui-field-type-pick'\n\t},\n\n\ttriggers: {\n\t\t'click @ui.checkbox': 'toggle:selected'\n\t},\n\n\tmodelEvents: {\n\t\t'change': 'modelChanged'\n\t},\n\n\ttemplateContext: function () {\n\t\treturn {\n\t\t\tordinal: this.model.collection.indexOf( this.model )\n\t\t};\n\t},\n\n\tmodelChanged: function () {\n\t\tthis.render();\n\t}\n} );\n\n/**\n *\n */\nexport const CheckboxView = PodsFieldListView.extend( {\n\tchildViewEventPrefix: false, // Disable implicit event listeners in favor of explicit childViewTriggers and childViewEvents\n\n\ttagName: 'ul',\n\n\tclassName: 'pods-checkbox-view',\n\n\tchildView: CheckboxItem,\n\n\tchildViewEvents: {\n\t\t'toggle:selected': 'onChildviewToggleSelected'\n\t},\n\n\t/**\n\t *\n\t */\n\tonAttach: function () {\n\n\t\t// Check initial selection limit status and enforce it if needed\n\t\tif ( !this.validateSelectionLimit() ) {\n\t\t\tthis.selectionLimitOver();\n\t\t}\n\t},\n\n\t/**\n\t *\n\t * @param childView\n\t */\n\tonChildviewToggleSelected: function ( childView ) {\n\n\t\tchildView.model.toggleSelected();\n\n\t\t// Dynamically enforce selection limit\n\t\tif ( this.validateSelectionLimit() ) {\n\t\t\tthis.selectionLimitUnder();\n\t\t} else {\n\t\t\tthis.selectionLimitOver();\n\t\t}\n\t},\n\n\t/**\n\t * @returns {boolean} true if unlimited selections are allowed or we're below the selection limit\n\t */\n\tvalidateSelectionLimit: function () {\n\t\tconst fieldConfig = this.fieldModel.get( 'fieldConfig' );\n\t\tlet limit, numSelected;\n\n\t\tlimit = +fieldConfig.pick_limit; // Unary plus will implicitly cast to number\n\t\tnumSelected = this.collection.filterBySelected().length;\n\n\t\treturn 0 === limit || numSelected < limit;\n\t},\n\n\t/**\n\t *\n\t */\n\tselectionLimitOver: function () {\n\t\tthis.$el.find( 'input:checkbox:not(:checked)' ).prop( 'disabled', true );\n\t\tthis.trigger( 'selection:limit:over', this );\n\t},\n\n\t/**\n\t *\n\t */\n\tselectionLimitUnder: function () {\n\t\tthis.$el.find( 'input:checkbox' ).prop( 'disabled', false );\n\t\tthis.trigger( 'selection:limit:under', this );\n\t}\n\n} );\n","/*global jQuery, _, Backbone, Marionette, select2, sprintf, wp, ajaxurl, PodsI18n */\n\n// Note: this is a template-less view\nimport { PodsFieldListView, PodsFieldView } from 'pods-dfv/_src/core/pods-field-views';\nimport { RelationshipCollection } from 'pods-dfv/_src/pick/relationship-model';\n\nconst SELECT2_UL_TARGET = 'ul.select2-selection__rendered';\nconst SELECT2_SELECTED_TARGET = '.select2-selection__choice';\n\n/**\n * option\n *\n * @extends Backbone.View\n */\nexport const SelectItem = PodsFieldView.extend( {\n\tchildViewEventPrefix: false, // Disable implicit event listeners in favor of explicit childViewTriggers and childViewEvents\n\n\ttagName: 'option',\n\n\ttemplate: false,\n\n\tinitialize: function ( options ) {\n\t\tthis.$el.val( this.model.get( 'id' ) );\n\n\t\tthis.$el.html( this.model.get( 'name' ) );\n\n\t\tif ( this.model.get( 'selected' ) ) {\n\t\t\tthis.$el.prop( 'selected', 'selected' );\n\t\t}\n\t}\n} );\n\n/**\n * optgroup\n *\n * @extends Backbone.View\n */\nexport const Optgroup = PodsFieldListView.extend( {\n\tchildViewEventPrefix: false, // Disable implicit event listeners in favor of explicit childViewTriggers and childViewEvents\n\n\ttagName: 'optgroup',\n\n\tchildView: SelectItem,\n\n\tattributes: function () {\n\t\treturn {\n\t\t\tlabel: this.model.get( 'label' )\n\t\t};\n\t}\n} );\n\n/**\n * select\n *\n * @extends Backbone.View\n */\nexport const SelectView = Marionette.CollectionView.extend( {\n\tchildViewEventPrefix: false, // Disable implicit event listeners in favor of explicit childViewTriggers and childViewEvents\n\n\ttagName: 'select',\n\n\ttriggers: {\n\t\t'change': {\n\t\t\tevent: 'change:selected',\n\t\t\tstopPropagation: false\n\t\t}\n\t},\n\n\tmultiLastValidSelection: [],\n\n\t/**\n\t *\n\t * @param newCollection\n\t */\n\tsetCollection: function ( newCollection ) {\n\t\tthis.collection = newCollection;\n\t},\n\n\t/**\n\t *\n\t * @param options\n\t */\n\tinitialize: function ( options ) {\n\t\tthis.fieldModel = options.fieldModel;\n\t\tthis.fieldConfig = this.fieldModel.get( 'fieldConfig' );\n\t},\n\n\t/**\n\t * Set the proper child view (optgroups or no)\n\t *\n\t * @param item\n\t * @returns {*}\n\t */\n\tchildView: function ( item ) {\n\t\tif ( this.fieldConfig.optgroup ) {\n\t\t\treturn Optgroup;\n\t\t} else {\n\t\t\treturn SelectItem;\n\t\t}\n\t},\n\n\t/**\n\t * todo: We're bypassing the PodsFieldListView functionality, need to explicitly include it for now\n\t *\n\t * @param model\n\t * @param index\n\t * @returns {{fieldModel: *}}\n\t */\n\tchildViewOptions: function ( model, index ) {\n\t\tlet returnOptions = { fieldModel: this.fieldModel };\n\n\t\tif ( this.fieldConfig.optgroup ) {\n\t\t\treturnOptions.collection = new RelationshipCollection( model.get( 'collection' ) );\n\t\t}\n\n\t\treturn returnOptions;\n\t},\n\n\t/**\n\t * todo: We're bypassing the PodsFieldListView functionality, need to explicitly include it for now\n\t *\n\t * @returns {{}}\n\t */\n\tserializeData: function () {\n\t\tconst fieldModel = this.options.fieldModel;\n\t\tlet data = this.model ? this.model.toJSON() : {};\n\n\t\tdata.htmlAttr = fieldModel.get( 'attributes' );\n\t\tdata.fieldConfig = fieldModel.get( 'fieldConfig' );\n\n\t\treturn data;\n\t},\n\n\t/**\n\t *\n\t */\n\tattributes: function () {\n\n\t\t/**\n\t\t * @param {string} htmlAttr.name\n\t\t * @param {string} htmlAttr.class\n\t\t * @param {string} htmlAttr.name_clean\n\t\t * @param {string} htmlAttr.id\n\t\t *\n\t\t * @param {string} fieldConfig.pick_format_type 'single' or 'multi'\n\t\t */\n\t\tconst fieldModel = this.options.fieldModel;\n\t\tconst htmlAttr = fieldModel.get( 'htmlAttr' );\n\t\tconst fieldConfig = fieldModel.get( 'fieldConfig' );\n\n\t\tlet name = htmlAttr.name;\n\t\tif ( 'multi' === fieldConfig.pick_format_type ) {\n\t\t\tname = name + '[]';\n\t\t}\n\t\treturn {\n\t\t\t'name': name,\n\t\t\t'class': htmlAttr.class,\n\t\t\t'data-name-clean': htmlAttr.name_clean,\n\t\t\t'id': htmlAttr.id,\n\t\t\t'tabindex': '2',\n\t\t\t'multiple': ( 'multi' === fieldConfig.pick_format_type )\n\t\t};\n\t},\n\n\t/**\n\t * Setup to be done once attached to the DOM. Select2 has some setup needs.\n\t *\n\t * @var {RelationshipCollection} this.collection\n\t */\n\tonAttach: function () {\n\t\tconst view_name = this.fieldConfig.view_name;\n\t\tconst format_type = this.fieldConfig.pick_format_type;\n\n\t\t// Initialize select2 fields\n\t\tif ( 'select2' === view_name ) {\n\t\t\tthis.setupSelect2();\n\t\t}\n\n\t\t// Check initial selection limit status for regular multiselect and enforce it if needed\n\t\tif ( 'select' === view_name && 'multi' === format_type ) {\n\n\t\t\t// Store initial selection in case we need to revert back from an invalid state\n\t\t\tthis.multiLastValidSelection = this.$el.val();\n\t\t}\n\n\t\t// If we're at the limit: disable all unselected items so no selections can be added\n\t\tif ( !this.validateSelectionLimit() ) {\n\t\t\tthis.selectionLimitOver();\n\t\t}\n\t},\n\n\t/**\n\t * @var {RelationshipCollection} this.collection\n\t */\n\tonChangeSelected: function () {\n\t\tconst limit = +this.fieldConfig.pick_limit; // Unary plus will implicitly cast to number\n\t\tconst view_name = this.fieldConfig.view_name;\n\t\tconst format_type = this.fieldConfig.pick_format_type;\n\n\t\t// Regular multiselect may need to reject the selection change\n\t\tif ( 'select' === view_name && 'multi' === format_type ) {\n\n\t\t\t// Has the selection gone OVER the limit? Can occur with consecutive item selection.\n\t\t\tif ( null !== this.$el.val() && 0 !== limit && limit < this.$el.val().length ) {\n\n\t\t\t\t// Revert to the last valid selection and punt on what they attempted\n\t\t\t\tthis.$el.val( this.multiLastValidSelection );\n\t\t\t\twindow.alert( `${PodsI18n.__( 'You can only select' )} ${sprintf( PodsI18n._n( '%s item', '%s items', limit ), limit )}` );\n\t\t\t\tthis.trigger( 'childview:change:selected', this );\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\t// Update the collection and last valid selection based on the new selections\n\t\tthis.collection.setSelected( this.$el.val() );\n\t\tthis.multiLastValidSelection = this.$el.val();\n\n\t\t// Dynamically enforce selection limits\n\t\tif ( this.validateSelectionLimit() ) {\n\t\t\tthis.selectionLimitUnder();\n\t\t} else {\n\t\t\tthis.selectionLimitOver();\n\t\t}\n\n\t\tthis.trigger( 'childview:change:selected', this );\n\t},\n\n\tonBeforeDetach: function() {\n\t\tthis.$el.selectWoo( 'destroy' );\n\t},\n\n\t/**\n\t * @var {RelationshipCollection} this.collection\n\t *\n\t * @returns {boolean} true if unlimited selections are allowed or we're below the selection limit\n\t */\n\tvalidateSelectionLimit: function () {\n\t\tlet limit, numSelected;\n\n\t\tlimit = +this.fieldConfig.pick_limit; // Unary plus will implicitly cast to number\n\t\tnumSelected = this.collection.filterBySelected().length;\n\n\t\treturn 0 === limit || numSelected < limit;\n\t},\n\n\t/**\n\t *\n\t */\n\tselectionLimitOver: function () {\n\t\tconst viewName = this.fieldConfig.view_name;\n\t\tconst formatType = this.fieldConfig.pick_format_type;\n\n\t\tif ( 'select' === viewName && 'multi' === formatType ) {\n\t\t\t// At the limit: disable all unselected items so no further selections can be added\n\t\t\tthis.$el.find( 'option:not(:selected)' ).prop( 'disabled', true );\n\t\t}\n\n\t\tthis.trigger( 'childview:selection:limit:over', this );\n\t},\n\n\t/**\n\t *\n\t */\n\tselectionLimitUnder: function () {\n\t\tconst viewName = this.fieldConfig.view_name;\n\t\tconst formatType = this.fieldConfig.pick_format_type;\n\n\t\tif ( 'select' === viewName && 'multi' === formatType ) {\n\t\t\t// Not at limit, make sure all items are enabled\n\t\t\tthis.$el.find( 'option' ).prop( 'disabled', false );\n\t\t}\n\n\t\tthis.trigger( 'childview:selection:limit:under', this );\n\t},\n\n\t/**\n\t * No filtering, by default. Consuming views can override this function to provide custom filtering\n\t * (e.g. List View needs to filter items already selected for its select from existing list)\n\t *\n\t * @param data\n\t */\n\tfilterAjaxList: function ( data ) {\n\t\tconst selectedItems = this.collection.filterBySelected();\n\t\tconst returnList = [];\n\n\t\t_.each( data.results, function ( element ) {\n\t\t\telement.text = element.name; // Select2 needs the \"text\" key but our model uses \"name\"\n\n\t\t\t// Only keep choices that haven't been selected yet, we don't want selected items in the autocomplete portion\n\t\t\tif ( !selectedItems.get( element.id ) ) {\n\t\t\t\treturnList.push( element );\n\t\t\t}\n\t\t} );\n\n\t\treturn { 'results': returnList };\n\t},\n\n\t/**\n\t * Initialize Select2, setup drag-drop reordering\n\t */\n\tsetupSelect2: function () {\n\t\tconst self = this;\n\t\tconst $select2 = this.$el;\n\t\tconst fieldConfig = this.options.fieldModel.get( 'fieldConfig' );\n\t\tconst ajaxData = fieldConfig.ajax_data;\n\t\tconst select2Overrides = fieldConfig.select2_overrides;\n\t\tconst limit = fieldConfig.pick_limit;\n\t\tconst isSingle = ( 'single' === fieldConfig.pick_format_type );\n\t\tconst selectedCount = this.collection.filterBySelected().length;\n\t\tlet $ulContainer, select2Options, placeholder;\n\n\t\t// 'placeholder' for single select requires an empty option. None of the examples set selected but\n\t\t// it did not work for me in testing with just an empty option like the examples.\n\t\t//\n\t\t// https://select2.org/placeholders#single-select-placeholders\n\t\t// https://github.com/select2/select2/issues/3553\n\t\tif ( 0 === selectedCount && isSingle ) {\n\t\t\t$select2.prepend( '