���� JFIF    �� �        "" $(4,$&1'-=-157:::#+?D?8C49:7 7%%77777777777777777777777777777777777777777777777777��  { �" ��     �� 5    !1AQa"q�2��BR��#b�������  ��  ��   ? ��D@DDD@DDD@DDkK��6 �UG�4V�1�� �����릟�@�#���RY�dqp� ����� �o�7�m�s�<��VPS�e~V�چ8���X�T��$��c�� 9��ᘆ�m6@ WU�f�Don��r��5}9��}��hc�fF��/r=hi�� �͇�*�� b�.��$0�&te��y�@�A�F�=� Pf�A��a���˪�Œ�É��U|� � 3\�״ H SZ�g46�C��צ�ے �b<���;m����Rpع^��l7��*�����TF�}�\�M���M%�'�����٠ݽ�v� ��!-�����?�N!La��A+[`#���M����'�~oR�?��v^)��=��h����A��X�.���˃����^Ə��ܯsO"B�c>; �e�4��5�k��/CB��.  �J?��;�҈�������������������~�<�VZ�ꭼ2/)Í”jC���ע�V�G�!���!�F������\�� Kj�R�oc�h���:Þ I��1"2�q×°8��Р@ז���_C0�ր��A��lQ��@纼�!7��F�� �]�sZ B�62r�v�z~�K�7�c��5�.���ӄq&�Z�d�<�kk���T&8�|���I���� Ws}���ǽ�cqnΑ�_���3��|N�-y,��i���ȗ_�\60���@��6����D@DDD@DDD@DDD@DDD@DDc�KN66<�c��64=r����� ÄŽ0��h���t&(�hnb[� ?��^��\��â|�,�/h�\��R��5�? �0�!צ܉-����G����٬��Q�zA���1�����V��� �:R���`�$��ik��H����D4�����#dk����� h�}����7���w%�������*o8wG�LycuT�.���ܯ7��I��u^���)��/c�,s�Nq�ۺ�;�ך�YH2���.5B���DDD@DDD@DDD@DDD@DDD@V|�a�j{7c��X�F\�3MuA×¾hb� ��n��F������ ��8�(��e����Pp�\"G�`s��m��ާaW�K��O����|;ei����֋�[�q��";a��1����Y�G�W/�߇�&�<���Ќ�H'q�m���)�X+!���=�m�ۚ丷~6a^X�)���,�>#&6G���Y��{����"" """ """ """ """ ""��at\/�a�8 �yp%�lhl�n����)���i�t��B�������������?��modskinlienminh.com - WSOX ENC media-views.min.js000064400000330031147573120640010107 0ustar00/*! This file is auto-generated */ (()=>{var i={7145:e=>{var s=wp.media.model.Selection,o=wp.media.controller.Library,t=o.extend({defaults:_.defaults({multiple:"add",filterable:"uploaded",priority:100,syncSelection:!1},o.prototype.defaults),initialize:function(){var e=this.get("collectionType");"video"===this.get("type")&&(e="video-"+e),this.set("id",e+"-library"),this.set("toolbar",e+"-add"),this.set("menu",e),this.get("library")||this.set("library",wp.media.query({type:this.get("type")})),o.prototype.initialize.apply(this,arguments)},activate:function(){var e=this.get("library"),t=this.get("editLibrary"),i=this.frame.state(this.get("collectionType")+"-edit").get("library");t&&t!==i&&e.unobserve(t),e.validator=function(e){return!!this.mirroring.get(e.cid)&&!i.get(e.cid)&&s.prototype.validator.apply(this,arguments)},e.reset(e.mirroring.models,{silent:!0}),e.observe(i),this.set("editLibrary",i),o.prototype.activate.apply(this,arguments)}});e.exports=t},8612:e=>{var t=wp.media.controller.Library,n=wp.media.view.l10n,r=jQuery,i=t.extend({defaults:{multiple:!1,sortable:!0,date:!1,searchable:!1,content:"browse",describe:!0,dragInfo:!0,idealColumnWidth:170,editing:!1,priority:60,SettingsView:!1,syncSelection:!1},initialize:function(){var e=this.get("collectionType");"video"===this.get("type")&&(e="video-"+e),this.set("id",e+"-edit"),this.set("toolbar",e+"-edit"),this.get("library")||this.set("library",new wp.media.model.Selection),this.get("AttachmentView")||this.set("AttachmentView",wp.media.view.Attachment.EditLibrary),t.prototype.initialize.apply(this,arguments)},activate:function(){this.get("library").props.set("type",this.get("type")),this.get("library").observe(wp.Uploader.queue),this.frame.on("content:render:browse",this.renderSettings,this),t.prototype.activate.apply(this,arguments)},deactivate:function(){this.get("library").unobserve(wp.Uploader.queue),this.frame.off("content:render:browse",this.renderSettings,this),t.prototype.deactivate.apply(this,arguments)},renderSettings:function(e){var t=this.get("library"),i=this.get("collectionType"),s=this.get("dragInfoText"),o=this.get("SettingsView"),a={};t&&e&&(t[i]=t[i]||new Backbone.Model,a[i]=new o({controller:this,model:t[i],priority:40}),e.sidebar.set(a),s&&e.toolbar.set("dragInfo",new wp.media.View({el:r('
'+s+"
")[0],priority:-40})),e.toolbar.set("reverse",{text:n.reverseOrder,priority:80,click:function(){t.reset(t.toArray().reverse())}}))}});e.exports=i},5422:e=>{var a=wp.media.view.l10n,t=wp.media.controller.State.extend({defaults:{id:"cropper",title:a.cropImage,toolbar:"crop",content:"crop",router:!1,canSkipCrop:!1,doCropArgs:{}},activate:function(){this.frame.on("content:create:crop",this.createCropContent,this),this.frame.on("close",this.removeCropper,this),this.set("selection",new Backbone.Collection(this.frame._selection.single))},deactivate:function(){this.frame.toolbar.mode("browse")},createCropContent:function(){this.cropperView=new wp.media.view.Cropper({controller:this,attachment:this.get("selection").first()}),this.cropperView.on("image-loaded",this.createCropToolbar,this),this.frame.content.set(this.cropperView)},removeCropper:function(){this.imgSelect.cancelSelection(),this.imgSelect.setOptions({remove:!0}),this.imgSelect.update(),this.cropperView.remove()},createCropToolbar:function(){var i=this.get("suggestedCropSize"),s=this.get("hasRequiredAspectRatio"),o=this.get("canSkipCrop")||!1,e={controller:this.frame,items:{insert:{style:"primary",text:a.cropImage,priority:80,requires:{library:!1,selection:!1},click:function(){var t=this.controller,e=t.state().get("selection").first();e.set({cropDetails:t.state().imgSelect.getSelection()}),this.$el.text(a.cropping),this.$el.attr("disabled",!0),t.state().doCrop(e).done(function(e){t.trigger("cropped",e),t.close()}).fail(function(){t.trigger("content:error:crop")})}}}};(o||s)&&_.extend(e.items,{skip:{style:"secondary",text:a.skipCropping,priority:70,requires:{library:!1,selection:!1},click:function(){var t=this.controller,e=t.state().get("selection").first();t.state().cropperView.remove(),s&&!o?(e.set({cropDetails:i}),t.state().doCrop(e).done(function(e){t.trigger("cropped",e),t.close()}).fail(function(){t.trigger("content:error:crop")})):(t.trigger("skippedcrop",e),t.close())}}}),this.frame.toolbar.set(new wp.media.view.Toolbar(e))},doCrop:function(e){return wp.ajax.post("custom-header-crop",_.extend({},this.defaults.doCropArgs,{nonce:e.get("nonces").edit,id:e.get("id"),cropDetails:e.get("cropDetails")}))}});e.exports=t},9660:e=>{var t=wp.media.controller.Cropper.extend({doCrop:function(e){var t=e.get("cropDetails"),i=this.get("control"),s=t.width/t.height;return i.params.flex_width&&i.params.flex_height?(t.dst_width=t.width,t.dst_height=t.height):(t.dst_width=i.params.flex_width?i.params.height*s:i.params.width,t.dst_height=i.params.flex_height?i.params.width/s:i.params.height),wp.ajax.post("crop-image",{wp_customize:"on",nonce:e.get("nonces").edit,id:e.get("id"),context:i.id,cropDetails:t})}});e.exports=t},5663:e=>{var s=wp.media.view.l10n,t=wp.media.controller.State.extend({defaults:{id:"edit-image",title:s.editImage,menu:!1,toolbar:"edit-image",content:"edit-image",url:""},activate:function(){this.frame.on("toolbar:render:edit-image",_.bind(this.toolbar,this))},deactivate:function(){this.frame.off("toolbar:render:edit-image")},toolbar:function(){var e=this.frame,t=e.lastState(),i=t&&t.id;e.toolbar.set(new wp.media.view.Toolbar({controller:e,items:{back:{style:"primary",text:s.back,priority:20,click:function(){i?e.setState(i):e.close()}}}}))}});e.exports=t},4910:e=>{var t=wp.media.view.l10n,n=Backbone.$,t=wp.media.controller.State.extend({defaults:{id:"embed",title:t.insertFromUrlTitle,content:"embed",menu:"default",toolbar:"main-embed",priority:120,type:"link",url:"",metadata:{}},sensitivity:400,initialize:function(e){this.metadata=e.metadata,this.debouncedScan=_.debounce(_.bind(this.scan,this),this.sensitivity),this.props=new Backbone.Model(this.metadata||{url:""}),this.props.on("change:url",this.debouncedScan,this),this.props.on("change:url",this.refresh,this),this.on("scan",this.scanImage,this)},scan:function(){var e,t=this,i={type:"link",scanners:[]};this.props.get("url")&&this.trigger("scan",i),i.scanners.length?(e=i.scanners=n.when.apply(n,i.scanners)).always(function(){t.get("scanners")===e&&t.set("loading",!1)}):i.scanners=null,i.loading=!!i.scanners,this.set(i)},scanImage:function(e){var t=this.frame,i=this,s=this.props.get("url"),o=new Image,a=n.Deferred();e.scanners.push(a.promise()),o.onload=function(){a.resolve(),i===t.state()&&s===i.props.get("url")&&(i.set({type:"image"}),i.props.set({width:o.width,height:o.height}))},o.onerror=a.reject,o.src=s},refresh:function(){this.frame.toolbar.get().refresh()},reset:function(){this.props.clear().set({url:""}),this.active&&this.refresh()}});e.exports=t},1169:e=>{var s=wp.media.model.Attachment,t=wp.media.controller.Library,i=wp.media.view.l10n,i=t.extend({defaults:_.defaults({id:"featured-image",title:i.setFeaturedImageTitle,multiple:!1,filterable:"uploaded",toolbar:"featured-image",priority:60,syncSelection:!0},t.prototype.defaults),initialize:function(){var e,o;this.get("library")||this.set("library",wp.media.query({type:"image"})),t.prototype.initialize.apply(this,arguments),e=this.get("library"),o=e.comparator,e.comparator=function(e,t){var i=!!this.mirroring.get(e.cid),s=!!this.mirroring.get(t.cid);return!i&&s?-1:i&&!s?1:o.apply(this,arguments)},e.observe(this.get("selection"))},activate:function(){this.frame.on("open",this.updateSelection,this),t.prototype.activate.apply(this,arguments)},deactivate:function(){this.frame.off("open",this.updateSelection,this),t.prototype.deactivate.apply(this,arguments)},updateSelection:function(){var e,t=this.get("selection"),i=wp.media.view.settings.post.featuredImageId;""!==i&&-1!==i&&(e=s.get(i)).fetch(),t.reset(e?[e]:[])}});e.exports=i},7127:e=>{var i=wp.media.model.Selection,s=wp.media.controller.Library,t=wp.media.view.l10n,t=s.extend({defaults:_.defaults({id:"gallery-library",title:t.addToGalleryTitle,multiple:"add",filterable:"uploaded",menu:"gallery",toolbar:"gallery-add",priority:100,syncSelection:!1},s.prototype.defaults),initialize:function(){this.get("library")||this.set("library",wp.media.query({type:"image"})),s.prototype.initialize.apply(this,arguments)},activate:function(){var e=this.get("library"),t=this.frame.state("gallery-edit").get("library");this.editLibrary&&this.editLibrary!==t&&e.unobserve(this.editLibrary),e.validator=function(e){return!!this.mirroring.get(e.cid)&&!t.get(e.cid)&&i.prototype.validator.apply(this,arguments)},e.reset(e.mirroring.models,{silent:!0}),e.observe(t),this.editLibrary=t,s.prototype.activate.apply(this,arguments)}});e.exports=t},2038:e=>{var t=wp.media.controller.Library,i=wp.media.view.l10n,s=t.extend({defaults:{id:"gallery-edit",title:i.editGalleryTitle,multiple:!1,searchable:!1,sortable:!0,date:!1,display:!1,content:"browse",toolbar:"gallery-edit",describe:!0,displaySettings:!0,dragInfo:!0,idealColumnWidth:170,editing:!1,priority:60,syncSelection:!1},initialize:function(){this.get("library")||this.set("library",new wp.media.model.Selection),this.get("AttachmentView")||this.set("AttachmentView",wp.media.view.Attachment.EditLibrary),t.prototype.initialize.apply(this,arguments)},activate:function(){this.get("library").props.set("type","image"),this.get("library").observe(wp.Uploader.queue),this.frame.on("content:render:browse",this.gallerySettings,this),t.prototype.activate.apply(this,arguments)},deactivate:function(){this.get("library").unobserve(wp.Uploader.queue),this.frame.off("content:render:browse",this.gallerySettings,this),t.prototype.deactivate.apply(this,arguments)},gallerySettings:function(e){var t;this.get("displaySettings")&&(t=this.get("library"))&&e&&(t.gallery=t.gallery||new Backbone.Model,e.sidebar.set({gallery:new wp.media.view.Settings.Gallery({controller:this,model:t.gallery,priority:40})}),e.toolbar.set("reverse",{text:i.reverseOrder,priority:80,click:function(){t.reset(t.toArray().reverse())}}))}});e.exports=s},705:e=>{var t=wp.media.controller.State,i=wp.media.controller.Library,s=wp.media.view.l10n,s=t.extend({defaults:_.defaults({id:"image-details",title:s.imageDetailsTitle,content:"image-details",menu:!1,router:!1,toolbar:"image-details",editing:!1,priority:60},i.prototype.defaults),initialize:function(e){this.image=e.image,t.prototype.initialize.apply(this,arguments)},activate:function(){this.frame.modal.$el.addClass("image-details")}});e.exports=s},472:e=>{var t=wp.media.view.l10n,i=window.getUserSetting,s=window.setUserSetting,t=wp.media.controller.State.extend({defaults:{id:"library",title:t.mediaLibraryTitle,multiple:!1,content:"upload",menu:"default",router:"browse",toolbar:"select",searchable:!0,filterable:!1,sortable:!0,autoSelect:!0,describe:!1,contentUserSetting:!0,syncSelection:!0},initialize:function(){var e=this.get("selection");this.get("library")||this.set("library",wp.media.query()),e instanceof wp.media.model.Selection||((e=e)||(e=this.get("library").props.toJSON(),e=_.omit(e,"orderby","query")),this.set("selection",new wp.media.model.Selection(null,{multiple:this.get("multiple"),props:e}))),this.resetDisplays()},activate:function(){this.syncSelection(),wp.Uploader.queue.on("add",this.uploading,this),this.get("selection").on("add remove reset",this.refreshContent,this),this.get("router")&&this.get("contentUserSetting")&&(this.frame.on("content:activate",this.saveContentMode,this),this.set("content",i("libraryContent",this.get("content"))))},deactivate:function(){this.recordSelection(),this.frame.off("content:activate",this.saveContentMode,this),this.get("selection").off(null,null,this),wp.Uploader.queue.off(null,null,this)},reset:function(){this.get("selection").reset(),this.resetDisplays(),this.refreshContent()},resetDisplays:function(){var e=wp.media.view.settings.defaultProps;this._displays=[],this._defaultDisplaySettings={align:i("align",e.align)||"none",size:i("imgsize",e.size)||"medium",link:i("urlbutton",e.link)||"none"}},display:function(e){var t=this._displays;return t[e.cid]||(t[e.cid]=new Backbone.Model(this.defaultDisplaySettings(e))),t[e.cid]},defaultDisplaySettings:function(e){var t=_.clone(this._defaultDisplaySettings);return t.canEmbed=this.canEmbed(e),t.canEmbed?t.link="embed":this.isImageAttachment(e)||"none"!==t.link||(t.link="file"),t},isImageAttachment:function(e){return e.get("uploading")?/\.(jpe?g|png|gif|webp|avif|heic|heif)$/i.test(e.get("filename")):"image"===e.get("type")},canEmbed:function(e){if(!e.get("uploading")){var t=e.get("type");if("audio"!==t&&"video"!==t)return!1}return _.contains(wp.media.view.settings.embedExts,e.get("filename").split(".").pop())},refreshContent:function(){var e=this.get("selection"),t=this.frame,i=t.router.get(),t=t.content.mode();this.active&&!e.length&&i&&!i.get(t)&&this.frame.content.render(this.get("content"))},uploading:function(e){"upload"===this.frame.content.mode()&&this.frame.content.mode("browse"),this.get("autoSelect")&&(this.get("selection").add(e),this.frame.trigger("library:selection:add"))},saveContentMode:function(){var e,t;"browse"===this.get("router")&&(e=this.frame.content.mode(),t=this.frame.router.get())&&t.get(e)&&s("libraryContent",e)}});_.extend(t.prototype,wp.media.selectionSync),e.exports=t},8065:e=>{var t=wp.media.controller.Library,i=t.extend({defaults:_.defaults({filterable:"uploaded",displaySettings:!1,priority:80,syncSelection:!1},t.prototype.defaults),initialize:function(e){this.media=e.media,this.type=e.type,this.set("library",wp.media.query({type:this.type})),t.prototype.initialize.apply(this,arguments)},activate:function(){wp.media.frame.lastMime&&(this.set("library",wp.media.query({type:wp.media.frame.lastMime})),delete wp.media.frame.lastMime),t.prototype.activate.apply(this,arguments)}});e.exports=i},9875:e=>{function t(e){_.extend(this,_.pick(e||{},"id","view","selector"))}t.extend=Backbone.Model.extend,_.extend(t.prototype,{mode:function(e){return e?(e!==this._mode&&(this.trigger("deactivate"),this._mode=e,this.render(e),this.trigger("activate")),this):this._mode},render:function(e){return e&&e!==this._mode?this.mode(e):(this.trigger("create",e={view:null}),this.trigger("render",e=e.view),e&&this.set(e),this)},get:function(){return this.view.views.first(this.selector)},set:function(e,t){return t&&(t.add=!1),this.view.views.set(this.selector,e,t)},trigger:function(e){var t,i;if(this._mode)return i=_.toArray(arguments),t=this.id+":"+e,i[0]=t+":"+this._mode,this.view.trigger.apply(this.view,i),i[0]=t,this.view.trigger.apply(this.view,i),this}}),e.exports=t},2275:e=>{var i=wp.media.controller.Library,t=wp.media.view.l10n,t=i.extend({defaults:_.defaults({id:"replace-image",title:t.replaceImageTitle,multiple:!1,filterable:"uploaded",toolbar:"replace",menu:!1,priority:60,syncSelection:!0},i.prototype.defaults),initialize:function(e){var t,o;this.image=e.image,this.get("library")||this.set("library",wp.media.query({type:"image"})),i.prototype.initialize.apply(this,arguments),t=this.get("library"),o=t.comparator,t.comparator=function(e,t){var i=!!this.mirroring.get(e.cid),s=!!this.mirroring.get(t.cid);return!i&&s?-1:i&&!s?1:o.apply(this,arguments)},t.observe(this.get("selection"))},activate:function(){this.frame.on("content:render:browse",this.updateSelection,this),i.prototype.activate.apply(this,arguments)},deactivate:function(){this.frame.off("content:render:browse",this.updateSelection,this),i.prototype.deactivate.apply(this,arguments)},updateSelection:function(){var e=this.get("selection"),t=this.image.attachment;e.reset(t?[t]:[])}});e.exports=t},6172:e=>{var t=wp.media.controller.Cropper.extend({activate:function(){this.frame.on("content:create:crop",this.createCropContent,this),this.frame.on("close",this.removeCropper,this),this.set("selection",new Backbone.Collection(this.frame._selection.single))},createCropContent:function(){this.cropperView=new wp.media.view.SiteIconCropper({controller:this,attachment:this.get("selection").first()}),this.cropperView.on("image-loaded",this.createCropToolbar,this),this.frame.content.set(this.cropperView)},doCrop:function(e){var t=e.get("cropDetails"),i=this.get("control");return t.dst_width=i.params.width,t.dst_height=i.params.height,wp.ajax.post("crop-image",{nonce:e.get("nonces").edit,id:e.get("id"),context:"site-icon",cropDetails:t})}});e.exports=t},6150:e=>{function t(){return{extend:Backbone.Model.extend}}_.extend(t.prototype,Backbone.Events,{state:function(e){return this.states=this.states||new Backbone.Collection,(e=e||this._state)&&!this.states.get(e)&&this.states.add({id:e}),this.states.get(e)},setState:function(e){var t=this.state();return t&&e===t.id||!this.states||!this.states.get(e)||(t&&(t.trigger("deactivate"),this._lastState=t.id),this._state=e,this.state().trigger("activate")),this},lastState:function(){if(this._lastState)return this.state(this._lastState)}}),_.each(["on","off","trigger"],function(e){t.prototype[e]=function(){return this.states=this.states||new Backbone.Collection,this.states[e].apply(this.states,arguments),this}}),e.exports=t},5694:e=>{var i=Backbone.Model.extend({constructor:function(){this.on("activate",this._preActivate,this),this.on("activate",this.activate,this),this.on("activate",this._postActivate,this),this.on("deactivate",this._deactivate,this),this.on("deactivate",this.deactivate,this),this.on("reset",this.reset,this),this.on("ready",this._ready,this),this.on("ready",this.ready,this),Backbone.Model.apply(this,arguments),this.on("change:menu",this._updateMenu,this)},ready:function(){},activate:function(){},deactivate:function(){},reset:function(){},_ready:function(){this._updateMenu()},_preActivate:function(){this.active=!0},_postActivate:function(){this.on("change:menu",this._menu,this),this.on("change:titleMode",this._title,this),this.on("change:content",this._content,this),this.on("change:toolbar",this._toolbar,this),this.frame.on("title:render:default",this._renderTitle,this),this._title(),this._menu(),this._toolbar(),this._content(),this._router()},_deactivate:function(){this.active=!1,this.frame.off("title:render:default",this._renderTitle,this),this.off("change:menu",this._menu,this),this.off("change:titleMode",this._title,this),this.off("change:content",this._content,this),this.off("change:toolbar",this._toolbar,this)},_title:function(){this.frame.title.render(this.get("titleMode")||"default")},_renderTitle:function(e){e.$el.text(this.get("title")||"")},_router:function(){var e=this.frame.router,t=this.get("router");this.frame.$el.toggleClass("hide-router",!t),t&&(this.frame.router.render(t),t=e.get())&&t.select&&t.select(this.frame.content.mode())},_menu:function(){var e,t=this.frame.menu,i=this.get("menu");this.frame.menu&&(e=(e=this.frame.menu.get("views"))?e.views.get().length:0,this.frame.$el.toggleClass("hide-menu",!i||e<2)),i&&(t.mode(i),e=t.get())&&e.select&&e.select(this.id)},_updateMenu:function(){var e=this.previous("menu"),t=this.get("menu");e&&this.frame.off("menu:render:"+e,this._renderMenu,this),t&&this.frame.on("menu:render:"+t,this._renderMenu,this)},_renderMenu:function(e){var t=this.get("menuItem"),i=this.get("title"),s=this.get("priority");!t&&i&&(t={text:i},s)&&(t.priority=s),t&&e.set(this.id,t)}});_.each(["toolbar","content"],function(t){i.prototype["_"+t]=function(){var e=this.get(t);e&&this.frame[t].render(e)}}),e.exports=i},4181:e=>{e.exports={syncSelection:function(){var e=this.get("selection"),t=this.frame._selection;this.get("syncSelection")&&t&&e&&(e.multiple&&(e.reset([],{silent:!0}),e.validateAll(t.attachments),t.difference=_.difference(t.attachments.models,e.models)),e.single(t.single))},recordSelection:function(){var e=this.get("selection"),t=this.frame._selection;this.get("syncSelection")&&t&&e&&(e.multiple?(t.attachments.reset(e.toArray().concat(t.difference)),t.difference=[]):t.attachments.add(e.toArray()),t.single=e._single)}}},2982:e=>{var t=wp.media.View,i=t.extend({tagName:"form",className:"compat-item",events:{submit:"preventDefault","change input":"save","change select":"save","change textarea":"save"},initialize:function(){this.listenTo(this.model,"add",this.render)},dispose:function(){return this.$(":focus").length&&this.save(),t.prototype.dispose.apply(this,arguments)},render:function(){var e=this.model.get("compat");if(e&&e.item)return this.views.detach(),this.$el.html(e.item),this.views.render(),this},preventDefault:function(e){e.preventDefault()},save:function(e){var t={};e&&e.preventDefault(),_.each(this.$el.serializeArray(),function(e){t[e.name]=e.value}),this.controller.trigger("attachment:compat:waiting",["waiting"]),this.model.saveCompat(t).always(_.bind(this.postSave,this))},postSave:function(){this.controller.trigger("attachment:compat:ready",["ready"])}});e.exports=i},7709:e=>{var i=jQuery,t=wp.media.View.extend({tagName:"select",className:"attachment-filters",id:"media-attachment-filters",events:{change:"change"},keys:[],initialize:function(){this.createFilters(),_.extend(this.filters,this.options.filters),this.$el.html(_.chain(this.filters).map(function(e,t){return{el:i("").val(t).html(e.text)[0],priority:e.priority||50}},this).sortBy("priority").pluck("el").value()),this.listenTo(this.model,"change",this.select),this.select()},createFilters:function(){this.filters={}},change:function(){var e=this.filters[this.el.value];e&&this.model.set(e.props)},select:function(){var e=this.model,i="all",s=e.toJSON();_.find(this.filters,function(e,t){if(_.all(e.props,function(e,t){return e===(_.isUndefined(s[t])?null:s[t])}))return i=t}),this.$el.val(i)}});e.exports=t},7349:e=>{var t=wp.media.view.l10n,i=wp.media.view.AttachmentFilters.extend({createFilters:function(){var i={},e=window.userSettings?parseInt(window.userSettings.uid,10):0;_.each(wp.media.view.settings.mimeTypes||{},function(e,t){i[t]={text:e,props:{status:null,type:t,uploadedTo:null,orderby:"date",order:"DESC",author:null}}}),i.all={text:t.allMediaItems,props:{status:null,type:null,uploadedTo:null,orderby:"date",order:"DESC",author:null},priority:10},wp.media.view.settings.post.id&&(i.uploaded={text:t.uploadedToThisPost,props:{status:null,type:null,uploadedTo:wp.media.view.settings.post.id,orderby:"menuOrder",order:"ASC",author:null},priority:20}),i.unattached={text:t.unattached,props:{status:null,uploadedTo:0,type:null,orderby:"menuOrder",order:"ASC",author:null},priority:50},e&&(i.mine={text:t.mine,props:{status:null,type:null,uploadedTo:null,orderby:"date",order:"DESC",author:e},priority:50}),wp.media.view.settings.mediaTrash&&this.controller.isModeActive("grid")&&(i.trash={text:t.trash,props:{uploadedTo:null,status:"trash",type:null,orderby:"date",order:"DESC",author:null},priority:50}),this.filters=i}});e.exports=i},6472:e=>{var t=wp.media.view.l10n,i=wp.media.view.AttachmentFilters.extend({id:"media-attachment-date-filters",createFilters:function(){var i={};_.each(wp.media.view.settings.months||{},function(e,t){i[t]={text:e.text,props:{year:e.year,monthnum:e.month}}}),i.all={text:t.allDates,props:{monthnum:!1,year:!1},priority:10},this.filters=i}});e.exports=i},1368:e=>{var o=wp.media.view.l10n,t=wp.media.view.AttachmentFilters.extend({createFilters:function(){var e,t=this.model.get("type"),i=wp.media.view.settings.mimeTypes,s=window.userSettings?parseInt(window.userSettings.uid,10):0;i&&t&&(e=i[t]),this.filters={all:{text:e||o.allMediaItems,props:{uploadedTo:null,orderby:"date",order:"DESC",author:null},priority:10},uploaded:{text:o.uploadedToThisPost,props:{uploadedTo:wp.media.view.settings.post.id,orderby:"menuOrder",order:"ASC",author:null},priority:20},unattached:{text:o.unattached,props:{uploadedTo:0,orderby:"menuOrder",order:"ASC",author:null},priority:50}},s&&(this.filters.mine={text:o.mine,props:{orderby:"date",order:"DESC",author:s},priority:50})}});e.exports=t},4075:e=>{var t=wp.media.View,o=jQuery,i=t.extend({tagName:"li",className:"attachment",template:wp.template("attachment"),attributes:function(){return{tabIndex:0,role:"checkbox","aria-label":this.model.get("title"),"aria-checked":!1,"data-id":this.model.get("id")}},events:{click:"toggleSelectionHandler","change [data-setting]":"updateSetting","change [data-setting] input":"updateSetting","change [data-setting] select":"updateSetting","change [data-setting] textarea":"updateSetting","click .attachment-close":"removeFromLibrary","click .check":"checkClickHandler",keydown:"toggleSelectionHandler"},buttons:{},initialize:function(){var e=this.options.selection;_.defaults(this.options,{rerenderOnModelChange:!0}).rerenderOnModelChange?this.listenTo(this.model,"change",this.render):this.listenTo(this.model,"change:percent",this.progress),this.listenTo(this.model,"change:title",this._syncTitle),this.listenTo(this.model,"change:caption",this._syncCaption),this.listenTo(this.model,"change:artist",this._syncArtist),this.listenTo(this.model,"change:album",this._syncAlbum),this.listenTo(this.model,"add",this.select),this.listenTo(this.model,"remove",this.deselect),e&&(e.on("reset",this.updateSelect,this),this.listenTo(this.model,"selection:single selection:unsingle",this.details),this.details(this.model,this.controller.state().get("selection"))),this.listenTo(this.controller.states,"attachment:compat:waiting attachment:compat:ready",this.updateSave)},dispose:function(){var e=this.options.selection;return this.updateAll(),e&&e.off(null,null,this),t.prototype.dispose.apply(this,arguments),this},render:function(){var e=_.defaults(this.model.toJSON(),{orientation:"landscape",uploading:!1,type:"",subtype:"",icon:"",filename:"",caption:"",title:"",dateFormatted:"",width:"",height:"",compat:!1,alt:"",description:""},this.options);return e.buttons=this.buttons,e.describe=this.controller.state().get("describe"),"image"===e.type&&(e.size=this.imageSize()),e.can={},e.nonces&&(e.can.remove=!!e.nonces.delete,e.can.save=!!e.nonces.update),this.controller.state().get("allowLocalEdits")&&!e.uploading&&(e.allowLocalEdits=!0),e.uploading&&!e.percent&&(e.percent=0),this.views.detach(),this.$el.html(this.template(e)),this.$el.toggleClass("uploading",e.uploading),e.uploading?this.$bar=this.$(".media-progress-bar div"):delete this.$bar,this.updateSelect(),this.updateSave(),this.views.render(),this},progress:function(){this.$bar&&this.$bar.length&&this.$bar.width(this.model.get("percent")+"%")},toggleSelectionHandler:function(e){var t;if("INPUT"!==e.target.nodeName&&"BUTTON"!==e.target.nodeName)if(37===e.keyCode||38===e.keyCode||39===e.keyCode||40===e.keyCode)this.controller.trigger("attachment:keydown:arrow",e);else if("keydown"!==e.type||13===e.keyCode||32===e.keyCode){if(e.preventDefault(),this.controller.isModeActive("grid")){if(this.controller.isModeActive("edit"))return void this.controller.trigger("edit:attachment",this.model,e.currentTarget);this.controller.isModeActive("select")&&(t="toggle")}e.shiftKey?t="between":(e.ctrlKey||e.metaKey)&&(t="toggle"),(!e.metaKey&&!e.ctrlKey||13!==e.keyCode&&10!==e.keyCode)&&(this.toggleSelection({method:t}),this.controller.trigger("selection:toggle"))}},toggleSelection:function(e){var t,i,s,o=this.collection,a=this.options.selection,n=this.model,e=e&&e.method;if(a){if(t=a.single(),"between"===(e=_.isUndefined(e)?a.multiple:e)&&t&&a.multiple)return t===n?void 0:(o=(i=o.indexOf(t))<(s=o.indexOf(this.model))?o.models.slice(i,s+1):o.models.slice(s,i+1),a.add(o),void a.single(n));"toggle"===e?(a[this.selected()?"remove":"add"](n),a.single(n)):"add"===e?(a.add(n),a.single(n)):("add"!==(e=e||"add")&&(e="reset"),this.selected()?a[t===n?"remove":"single"](n):(a[e](n),a.single(n)))}},updateSelect:function(){this[this.selected()?"select":"deselect"]()},selected:function(){var e=this.options.selection;if(e)return!!e.get(this.model.cid)},select:function(e,t){var i=this.options.selection,s=this.controller;!i||t&&t!==i||this.$el.hasClass("selected")||(this.$el.addClass("selected").attr("aria-checked",!0),s.isModeActive("grid")&&s.isModeActive("select"))||this.$(".check").attr("tabindex","0")},deselect:function(e,t){var i=this.options.selection;!i||t&&t!==i||this.$el.removeClass("selected").attr("aria-checked",!1).find(".check").attr("tabindex","-1")},details:function(e,t){var i=this.options.selection;i===t&&(t=i.single(),this.$el.toggleClass("details",t===this.model))},imageSize:function(e){var t=this.model.get("sizes"),i=!1;return e=e||"medium",t&&(t[e]?i=t[e]:t.large?i=t.large:t.thumbnail?i=t.thumbnail:t.full&&(i=t.full),i)?_.clone(i):{url:this.model.get("url"),width:this.model.get("width"),height:this.model.get("height"),orientation:this.model.get("orientation")}},updateSetting:function(e){var t=o(e.target).closest("[data-setting]");t.length&&(t=t.data("setting"),e=e.target.value,this.model.get(t)!==e)&&this.save(t,e)},save:function(){var e=this,t=this._save=this._save||{status:"ready"},i=this.model.save.apply(this.model,arguments),s=t.requests?o.when(i,t.requests):i;t.savedTimer&&clearTimeout(t.savedTimer),this.updateSave("waiting"),(t.requests=s).always(function(){t.requests===s&&(e.updateSave("resolved"===s.state()?"complete":"error"),t.savedTimer=setTimeout(function(){e.updateSave("ready"),delete t.savedTimer},2e3))})},updateSave:function(e){var t=this._save=this._save||{status:"ready"};return e&&e!==t.status&&(this.$el.removeClass("save-"+t.status),t.status=e),this.$el.addClass("save-"+t.status),this},updateAll:function(){var e=this.$("[data-setting]"),i=this.model,e=_.chain(e).map(function(e){var t=o("input, textarea, select, [value]",e);if(t.length)return e=o(e).data("setting"),t=t.val(),i.get(e)!==t?[e,t]:void 0}).compact().object().value();_.isEmpty(e)||i.save(e)},removeFromLibrary:function(e){"keydown"===e.type&&13!==e.keyCode&&32!==e.keyCode||(e.stopPropagation(),this.collection.remove(this.model))},checkClickHandler:function(e){var t=this.options.selection;t&&(e.stopPropagation(),t.where({id:this.model.get("id")}).length?(t.remove(this.model),this.$el.focus()):t.add(this.model),this.controller.trigger("selection:toggle"))}});_.each({caption:"_syncCaption",title:"_syncTitle",artist:"_syncArtist",album:"_syncAlbum"},function(e,s){i.prototype[e]=function(e,t){var i=this.$('[data-setting="'+s+'"]');return!i.length||t===i.find("input, textarea, select, [value]").val()?this:this.render()}}),e.exports=i},6090:e=>{var t=wp.media.view.Attachment,i=wp.media.view.l10n,o=jQuery,a=wp.i18n.__,s=t.extend({tagName:"div",className:"attachment-details",template:wp.template("attachment-details"),attributes:{},events:{"change [data-setting]":"updateSetting","change [data-setting] input":"updateSetting","change [data-setting] select":"updateSetting","change [data-setting] textarea":"updateSetting","click .delete-attachment":"deleteAttachment","click .trash-attachment":"trashAttachment","click .untrash-attachment":"untrashAttachment","click .edit-attachment":"editAttachment",keydown:"toggleSelectionHandler"},copyAttachmentDetailsURLClipboard:function(){var s;new ClipboardJS(".copy-attachment-url").on("success",function(e){var t=o(e.trigger),i=o(".success",t.closest(".copy-to-clipboard-container"));e.clearSelection(),clearTimeout(s),i.removeClass("hidden"),s=setTimeout(function(){i.addClass("hidden")},3e3),wp.a11y.speak(a("The file URL has been copied to your clipboard"))})},initialize:function(){this.options=_.defaults(this.options,{rerenderOnModelChange:!1}),t.prototype.initialize.apply(this,arguments),this.copyAttachmentDetailsURLClipboard()},getFocusableElements:function(){var e=o('li[data-id="'+this.model.id+'"]');this.previousAttachment=e.prev(),this.nextAttachment=e.next()},moveFocus:function(){this.previousAttachment.length?this.previousAttachment.trigger("focus"):this.nextAttachment.length?this.nextAttachment.trigger("focus"):this.controller.uploader&&this.controller.uploader.$browser?this.controller.uploader.$browser.trigger("focus"):this.moveFocusToLastFallback()},moveFocusToLastFallback:function(){o(".media-frame").attr("tabindex","-1").trigger("focus")},deleteAttachment:function(e){e.preventDefault(),this.getFocusableElements(),window.confirm(i.warnDelete)&&(this.model.destroy({wait:!0,error:function(){window.alert(i.errorDeleting)}}),this.moveFocus())},trashAttachment:function(e){var t=this.controller.library,i=this;e.preventDefault(),this.getFocusableElements(),wp.media.view.settings.mediaTrash&&"edit-metadata"===this.controller.content.mode()?(this.model.set("status","trash"),this.model.save().done(function(){t._requery(!0),i.moveFocusToLastFallback()})):(this.model.destroy(),this.moveFocus())},untrashAttachment:function(e){var t=this.controller.library;e.preventDefault(),this.model.set("status","inherit"),this.model.save().done(function(){t._requery(!0)})},editAttachment:function(e){var t=this.controller.states.get("edit-image");window.imageEdit&&t?(e.preventDefault(),t.set("image",this.model),this.controller.setState("edit-image")):this.$el.addClass("needs-refresh")},toggleSelectionHandler:function(e){if("keydown"===e.type&&9===e.keyCode&&e.shiftKey&&e.target===this.$(":tabbable").get(0))return this.controller.trigger("attachment:details:shift-tab",e),!1},render:function(){t.prototype.render.apply(this,arguments),wp.media.mixin.removeAllPlayers(),this.$("audio, video").each(function(e,t){t=wp.media.view.MediaDetails.prepareSrc(t);new window.MediaElementPlayer(t,wp.media.mixin.mejsSettings)})}});e.exports=s},5232:e=>{var t=wp.media.view.Attachment.extend({buttons:{close:!0}});e.exports=t},4593:e=>{var t=wp.media.view.Attachment.Selection.extend({buttons:{close:!0}});e.exports=t},3443:e=>{var t=wp.media.view.Attachment.extend({buttons:{check:!0}});e.exports=t},3962:e=>{var t=wp.media.view.Attachment.extend({className:"attachment selection",toggleSelection:function(){this.options.selection.single(this.model)}});e.exports=t},8142:e=>{var t=wp.media.View,a=jQuery,i=wp.media.view.settings.infiniteScrolling,s=t.extend({tagName:"ul",className:"attachments",attributes:{tabIndex:-1},initialize:function(){this.el.id=_.uniqueId("__attachments-view-"),_.defaults(this.options,{infiniteScrolling:i||!1,refreshSensitivity:wp.media.isTouchDevice?300:200,refreshThreshold:3,AttachmentView:wp.media.view.Attachment,sortable:!1,resize:!0,idealColumnWidth:a(window).width()<640?135:150}),this._viewsByCid={},this.$window=a(window),this.resizeEvent="resize.media-modal-columns",this.collection.on("add",function(e){this.views.add(this.createAttachmentView(e),{at:this.collection.indexOf(e)})},this),this.collection.on("remove",function(e){var t=this._viewsByCid[e.cid];delete this._viewsByCid[e.cid],t&&t.remove()},this),this.collection.on("reset",this.render,this),this.controller.on("library:selection:add",this.attachmentFocus,this),this.options.infiniteScrolling&&(this.scroll=_.chain(this.scroll).bind(this).throttle(this.options.refreshSensitivity).value(),this.options.scrollElement=this.options.scrollElement||this.el,a(this.options.scrollElement).on("scroll",this.scroll)),this.initSortable(),_.bindAll(this,"setColumns"),this.options.resize&&(this.on("ready",this.bindEvents),this.controller.on("open",this.setColumns),_.defer(this.setColumns,this))},bindEvents:function(){this.$window.off(this.resizeEvent).on(this.resizeEvent,_.debounce(this.setColumns,50))},attachmentFocus:function(){this.columns&&this.$el.focus()},restoreFocus:function(){this.$("li.selected:first").focus()},arrowEvent:function(e){var t=this.$el.children("li"),i=this.columns,s=t.filter(":focus").index(),o=s+1<=i?1:Math.ceil((s+1)/i);if(-1!==s){if(37===e.keyCode){if(0===s)return;t.eq(s-1).focus()}if(38===e.keyCode){if(1===o)return;t.eq(s-i).focus()}if(39===e.keyCode){if(t.length===s)return;t.eq(s+1).focus()}40===e.keyCode&&Math.ceil(t.length/i)!==o&&t.eq(s+i).focus()}},dispose:function(){this.collection.props.off(null,null,this),this.options.resize&&this.$window.off(this.resizeEvent),t.prototype.dispose.apply(this,arguments)},setColumns:function(){var e=this.columns,t=this.$el.width();t&&(this.columns=Math.min(Math.round(t/this.options.idealColumnWidth),12)||1,e&&e===this.columns||this.$el.closest(".media-frame-content").attr("data-columns",this.columns))},initSortable:function(){var o=this.collection;this.options.sortable&&a.fn.sortable&&(this.$el.sortable(_.extend({disabled:!!o.comparator,tolerance:"pointer",start:function(e,t){t.item.data("sortableIndexStart",t.item.index())},update:function(e,t){var i=o.at(t.item.data("sortableIndexStart")),s=o.comparator;delete o.comparator,o.remove(i,{silent:!0}),o.add(i,{silent:!0,at:t.item.index()}),o.comparator=s,o.trigger("reset",o),o.saveMenuOrder()}},this.options.sortable)),o.props.on("change:orderby",function(){this.$el.sortable("option","disabled",!!o.comparator)},this),this.collection.props.on("change:orderby",this.refreshSortable,this),this.refreshSortable())},refreshSortable:function(){var e;this.options.sortable&&a.fn.sortable&&(e="menuOrder"===(e=this.collection).props.get("orderby")||!e.comparator,this.$el.sortable("option","disabled",!e))},createAttachmentView:function(e){var t=new this.options.AttachmentView({controller:this.controller,model:e,collection:this.collection,selection:this.options.selection});return this._viewsByCid[e.cid]=t},prepare:function(){this.collection.length?this.views.set(this.collection.map(this.createAttachmentView,this)):(this.views.unset(),this.options.infiniteScrolling&&this.collection.more().done(this.scroll))},ready:function(){this.options.infiniteScrolling&&this.scroll()},scroll:function(){var e,t=this,i=this.options.scrollElement,s=i.scrollTop;i===document&&(i=document.body,s=a(document).scrollTop()),a(i).is(":visible")&&this.collection.hasMore()&&(e=this.views.parent.toolbar,i.scrollHeight-(s+i.clientHeight){var s=wp.media.View,o=wp.media.view.settings.mediaTrash,a=wp.media.view.l10n,n=jQuery,i=wp.media.view.settings.infiniteScrolling,r=wp.i18n.__,t=wp.i18n.sprintf,l=s.extend({tagName:"div",className:"attachments-browser",initialize:function(){_.defaults(this.options,{filters:!1,search:!0,date:!0,display:!1,sidebar:!0,AttachmentView:wp.media.view.Attachment.Library}),this.controller.on("toggle:upload:attachment",this.toggleUploader,this),this.controller.on("edit:selection",this.editSelection),this.options.sidebar&&"errors"===this.options.sidebar&&this.createSidebar(),this.controller.isModeActive("grid")?(this.createUploader(),this.createToolbar()):(this.createToolbar(),this.createUploader()),this.createAttachmentsHeading(),this.createAttachmentsWrapperView(),i||(this.$el.addClass("has-load-more"),this.createLoadMoreView()),this.options.sidebar&&"errors"!==this.options.sidebar&&this.createSidebar(),this.updateContent(),i||this.updateLoadMoreView(),this.options.sidebar&&"errors"!==this.options.sidebar||(this.$el.addClass("hide-sidebar"),"errors"===this.options.sidebar&&this.$el.addClass("sidebar-for-errors")),this.collection.on("add remove reset",this.updateContent,this),i||this.collection.on("add remove reset",this.updateLoadMoreView,this),this.collection.on("attachments:received",this.announceSearchResults,this)},announceSearchResults:_.debounce(function(){var e,t=r("Number of media items displayed: %d. Click load more for more results.");i&&(t=r("Number of media items displayed: %d. Scroll the page for more results.")),this.collection.mirroring&&this.collection.mirroring.args.s&&(0===(e=this.collection.length)?wp.a11y.speak(a.noMediaTryNewSearch):this.collection.hasMore()?wp.a11y.speak(t.replace("%d",e)):wp.a11y.speak(a.mediaFound.replace("%d",e)))},200),editSelection:function(e){e.$(".media-button-backToLibrary").focus()},dispose:function(){return this.options.selection.off(null,null,this),s.prototype.dispose.apply(this,arguments),this},createToolbar:function(){var e,t=-1!==n.inArray(this.options.filters,["uploaded","all"]),i={controller:this.controller};this.controller.isModeActive("grid")&&(i.className="media-toolbar wp-filter"),this.toolbar=new wp.media.view.Toolbar(i),this.views.add(this.toolbar),this.toolbar.set("spinner",new wp.media.view.Spinner({priority:-20})),(t||this.options.date)&&this.toolbar.set("filters-heading",new wp.media.view.Heading({priority:-100,text:a.filterAttachments,level:"h2",className:"media-attachments-filter-heading"}).render()),t&&(this.toolbar.set("filtersLabel",new wp.media.view.Label({value:a.filterByType,attributes:{for:"media-attachment-filters"},priority:-80}).render()),"uploaded"===this.options.filters?this.toolbar.set("filters",new wp.media.view.AttachmentFilters.Uploaded({controller:this.controller,model:this.collection.props,priority:-80}).render()):(e=new wp.media.view.AttachmentFilters.All({controller:this.controller,model:this.collection.props,priority:-80}),this.toolbar.set("filters",e.render()))),this.controller.isModeActive("grid")?(i=s.extend({className:"view-switch media-grid-view-switch",template:wp.template("media-library-view-switcher")}),this.toolbar.set("libraryViewSwitcher",new i({controller:this.controller,priority:-90}).render()),this.toolbar.set("dateFilterLabel",new wp.media.view.Label({value:a.filterByDate,attributes:{for:"media-attachment-date-filters"},priority:-75}).render()),this.toolbar.set("dateFilter",new wp.media.view.DateFilter({controller:this.controller,model:this.collection.props,priority:-75}).render()),this.toolbar.set("selectModeToggleButton",new wp.media.view.SelectModeToggleButton({text:a.bulkSelect,controller:this.controller,priority:-70}).render()),this.toolbar.set("deleteSelectedButton",new wp.media.view.DeleteSelectedButton({filters:e,style:"primary",disabled:!0,text:o?a.trashSelected:a.deletePermanently,controller:this.controller,priority:-80,click:function(){var t=[],i=[],e=this.controller.state().get("selection"),s=this.controller.state().get("library");!e.length||!o&&!window.confirm(a.warnBulkDelete)||o&&"trash"!==e.at(0).get("status")&&!window.confirm(a.warnBulkTrash)||(e.each(function(e){e.get("nonces").delete?o&&"trash"===e.get("status")?(e.set("status","inherit"),t.push(e.save()),i.push(e)):o?(e.set("status","trash"),t.push(e.save()),i.push(e)):e.destroy({wait:!0}):i.push(e)}),t.length?(e.remove(i),n.when.apply(null,t).then(_.bind(function(){s._requery(!0),this.controller.trigger("selection:action:done")},this))):this.controller.trigger("selection:action:done"))}}).render()),o&&this.toolbar.set("deleteSelectedPermanentlyButton",new wp.media.view.DeleteSelectedPermanentlyButton({filters:e,style:"link button-link-delete",disabled:!0,text:a.deletePermanently,controller:this.controller,priority:-55,click:function(){var t=[],i=[],e=this.controller.state().get("selection");e.length&&window.confirm(a.warnBulkDelete)&&(e.each(function(e){(e.get("nonces").delete?i:t).push(e)}),t.length&&e.remove(t),i.length)&&n.when.apply(null,i.map(function(e){return e.destroy()})).then(_.bind(function(){this.controller.trigger("selection:action:done")},this))}}).render())):this.options.date&&(this.toolbar.set("dateFilterLabel",new wp.media.view.Label({value:a.filterByDate,attributes:{for:"media-attachment-date-filters"},priority:-75}).render()),this.toolbar.set("dateFilter",new wp.media.view.DateFilter({controller:this.controller,model:this.collection.props,priority:-75}).render())),this.options.search&&(this.toolbar.set("searchLabel",new wp.media.view.Label({value:a.searchLabel,className:"media-search-input-label",attributes:{for:"media-search-input"},priority:60}).render()),this.toolbar.set("search",new wp.media.view.Search({controller:this.controller,model:this.collection.props,priority:60}).render())),this.options.dragInfo&&this.toolbar.set("dragInfo",new s({el:n('
'+a.dragInfo+"
")[0],priority:-40})),this.options.suggestedWidth&&this.options.suggestedHeight&&this.toolbar.set("suggestedDimensions",new s({el:n('
'+a.suggestedDimensions.replace("%1$s",this.options.suggestedWidth).replace("%2$s",this.options.suggestedHeight)+"
")[0],priority:-40}))},updateContent:function(){var e=this,t=this.controller.isModeActive("grid")?e.attachmentsNoResults:e.uploader;this.collection.length?(t.$el.addClass("hidden"),e.toolbar.get("spinner").hide(),this.toolbar.$(".media-bg-overlay").hide()):(this.toolbar.get("spinner").show(),this.toolbar.$(".media-bg-overlay").show(),this.dfd=this.collection.more().done(function(){e.collection.length?t.$el.addClass("hidden"):t.$el.removeClass("hidden"),e.toolbar.get("spinner").hide(),e.toolbar.$(".media-bg-overlay").hide()}))},createUploader:function(){this.uploader=new wp.media.view.UploaderInline({controller:this.controller,status:!1,message:this.controller.isModeActive("grid")?"":a.noItemsFound,canClose:this.controller.isModeActive("grid")}),this.uploader.$el.addClass("hidden"),this.views.add(this.uploader)},toggleUploader:function(){this.uploader.$el.hasClass("hidden")?this.uploader.show():this.uploader.hide()},createAttachmentsWrapperView:function(){this.attachmentsWrapper=new wp.media.View({className:"attachments-wrapper"}),this.views.add(this.attachmentsWrapper),this.createAttachments()},createAttachments:function(){this.attachments=new wp.media.view.Attachments({controller:this.controller,collection:this.collection,selection:this.options.selection,model:this.model,sortable:this.options.sortable,scrollElement:this.options.scrollElement,idealColumnWidth:this.options.idealColumnWidth,AttachmentView:this.options.AttachmentView}),this.controller.on("attachment:keydown:arrow",_.bind(this.attachments.arrowEvent,this.attachments)),this.controller.on("attachment:details:shift-tab",_.bind(this.attachments.restoreFocus,this.attachments)),this.views.add(".attachments-wrapper",this.attachments),this.controller.isModeActive("grid")&&(this.attachmentsNoResults=new s({controller:this.controller,tagName:"p"}),this.attachmentsNoResults.$el.addClass("hidden no-media"),this.attachmentsNoResults.$el.html(a.noMedia),this.views.add(this.attachmentsNoResults))},createLoadMoreView:function(){var e=this;this.loadMoreWrapper=new s({controller:this.controller,className:"load-more-wrapper"}),this.loadMoreCount=new s({controller:this.controller,tagName:"p",className:"load-more-count hidden"}),this.loadMoreButton=new wp.media.view.Button({text:r("Load more"),className:"load-more hidden",style:"primary",size:"",click:function(){e.loadMoreAttachments()}}),this.loadMoreSpinner=new wp.media.view.Spinner,this.loadMoreJumpToFirst=new wp.media.view.Button({text:r("Jump to first loaded item"),className:"load-more-jump hidden",size:"",click:function(){e.jumpToFirstAddedItem()}}),this.views.add(".attachments-wrapper",this.loadMoreWrapper),this.views.add(".load-more-wrapper",this.loadMoreSpinner),this.views.add(".load-more-wrapper",this.loadMoreCount),this.views.add(".load-more-wrapper",this.loadMoreButton),this.views.add(".load-more-wrapper",this.loadMoreJumpToFirst)},updateLoadMoreView:_.debounce(function(){this.loadMoreButton.$el.addClass("hidden"),this.loadMoreCount.$el.addClass("hidden"),this.loadMoreJumpToFirst.$el.addClass("hidden").prop("disabled",!0),this.collection.getTotalAttachments()&&(this.collection.length&&(this.loadMoreCount.$el.text(t(r("Showing %1$s of %2$s media items"),this.collection.length,this.collection.getTotalAttachments())),this.loadMoreCount.$el.removeClass("hidden")),this.collection.hasMore()&&this.loadMoreButton.$el.removeClass("hidden"),this.firstAddedMediaItem=this.$el.find(".attachment").eq(this.firstAddedMediaItemIndex),this.firstAddedMediaItem.length&&(this.firstAddedMediaItem.addClass("new-media"),this.loadMoreJumpToFirst.$el.removeClass("hidden").prop("disabled",!1)),this.firstAddedMediaItem.length)&&!this.collection.hasMore()&&this.loadMoreJumpToFirst.$el.trigger("focus")},10),loadMoreAttachments:function(){var e=this;this.collection.hasMore()&&(this.firstAddedMediaItemIndex=this.collection.length,this.$el.addClass("more-loaded"),this.collection.each(function(e){e=e.attributes.id;n('[data-id="'+e+'"]').addClass("found-media")}),e.loadMoreSpinner.show(),this.collection.once("attachments:received",function(){e.loadMoreSpinner.hide()}),this.collection.more())},jumpToFirstAddedItem:function(){this.firstAddedMediaItem.focus()},createAttachmentsHeading:function(){this.attachmentsHeading=new wp.media.view.Heading({text:a.attachmentsList,level:"h2",className:"media-views-heading screen-reader-text"}),this.views.add(this.attachmentsHeading)},createSidebar:function(){var e=this.options.selection,t=this.sidebar=new wp.media.view.Sidebar({controller:this.controller});this.views.add(t),this.controller.uploader&&t.set("uploads",new wp.media.view.UploaderStatus({controller:this.controller,priority:40})),e.on("selection:single",this.createSingle,this),e.on("selection:unsingle",this.disposeSingle,this),e.single()&&this.createSingle()},createSingle:function(){var e=this.sidebar,t=this.options.selection.single();e.set("details",new wp.media.view.Attachment.Details({controller:this.controller,model:t,priority:80})),e.set("compat",new wp.media.view.AttachmentCompat({controller:this.controller,model:t,priority:120})),this.options.display&&e.set("display",new wp.media.view.Settings.AttachmentDisplay({controller:this.controller,model:this.model.display(t),attachment:t,priority:160,userSettings:this.model.get("displayUserSettings")})),"insert"===this.model.id&&e.$el.addClass("visible")},disposeSingle:function(){var e=this.sidebar;e.unset("details"),e.unset("compat"),e.unset("display"),e.$el.removeClass("visible")}});e.exports=l},3479:e=>{var t=wp.media.view.Attachments,i=t.extend({events:{},initialize:function(){return _.defaults(this.options,{sortable:!1,resize:!1,AttachmentView:wp.media.view.Attachment.Selection}),t.prototype.initialize.apply(this,arguments)}});e.exports=i},168:e=>{var t=Backbone.$,i=wp.media.View.extend({tagName:"div",className:"button-group button-large media-button-group",initialize:function(){this.buttons=_.map(this.options.buttons||[],function(e){return e instanceof Backbone.View?e:new wp.media.view.Button(e).render()}),delete this.options.buttons,this.options.classes&&this.$el.addClass(this.options.classes)},render:function(){return this.$el.html(t(_.pluck(this.buttons,"el")).detach()),this}});e.exports=i},846:e=>{var t=wp.media.View.extend({tagName:"button",className:"media-button",attributes:{type:"button"},events:{click:"click"},defaults:{text:"",style:"",size:"large",disabled:!1},initialize:function(){this.model=new Backbone.Model(this.defaults),_.each(this.defaults,function(e,t){var i=this.options[t];_.isUndefined(i)||(this.model.set(t,i),delete this.options[t])},this),this.listenTo(this.model,"change",this.render)},render:function(){var e=["button",this.className],t=this.model.toJSON();return t.style&&e.push("button-"+t.style),t.size&&e.push("button-"+t.size),e=_.uniq(e.concat(this.options.classes)),this.el.className=e.join(" "),this.$el.attr("disabled",t.disabled),this.$el.text(this.model.get("text")),this},click:function(e){"#"===this.attributes.href&&e.preventDefault(),this.options.click&&!this.model.get("disabled")&&this.options.click.apply(this,arguments)}});e.exports=t},7637:e=>{var t=wp.media.View,i=wp.media.view.UploaderStatus,s=wp.media.view.l10n,o=jQuery,a=t.extend({className:"crop-content",template:wp.template("crop-content"),initialize:function(){_.bindAll(this,"onImageLoad")},ready:function(){this.controller.frame.on("content:error:crop",this.onError,this),this.$image=this.$el.find(".crop-image"),this.$image.on("load",this.onImageLoad),o(window).on("resize.cropper",_.debounce(this.onImageLoad,250))},remove:function(){o(window).off("resize.cropper"),this.$el.remove(),this.$el.off(),t.prototype.remove.apply(this,arguments)},prepare:function(){return{title:s.cropYourImage,url:this.options.attachment.get("url")}},onImageLoad:function(){var i,e=this.controller.get("imgSelectOptions");"function"==typeof e&&(e=e(this.options.attachment,this.controller)),e=_.extend(e,{parent:this.$el,onInit:function(){var t=i.getOptions().aspectRatio;this.parent.children().on("mousedown touchstart",function(e){!t&&e.shiftKey&&i.setOptions({aspectRatio:"1:1"})}),this.parent.children().on("mouseup touchend",function(){i.setOptions({aspectRatio:t||!1})})}}),this.trigger("image-loaded"),i=this.controller.imgSelect=this.$image.imgAreaSelect(e)},onError:function(){var e=this.options.attachment.get("filename");this.views.add(".upload-errors",new wp.media.view.UploaderStatusError({filename:i.prototype.filename(e),message:window._wpMediaViewsL10n.cropError}),{at:0})}});e.exports=a},6126:e=>{var t=wp.media.View,i=t.extend({className:"image-editor",template:wp.template("image-editor"),initialize:function(e){this.editor=window.imageEdit,this.controller=e.controller,t.prototype.initialize.apply(this,arguments)},prepare:function(){return this.model.toJSON()},loadEditor:function(){this.editor.open(this.model.get("id"),this.model.get("nonces").edit,this)},back:function(){var e=this.controller.lastState();this.controller.setState(e)},refresh:function(){this.model.fetch()},save:function(){var e=this.controller.lastState();this.model.fetch().done(_.bind(function(){this.controller.setState(e)},this))}});e.exports=i},5741:e=>{var t=wp.media.View.extend({className:"media-embed",initialize:function(){this.url=new wp.media.view.EmbedUrl({controller:this.controller,model:this.model.props}).render(),this.views.set([this.url]),this.refresh(),this.listenTo(this.model,"change:type",this.refresh),this.listenTo(this.model,"change:loading",this.loading)},settings:function(e){this._settings&&this._settings.remove(),this._settings=e,this.views.add(e)},refresh:function(){var e,t=this.model.get("type");if("image"===t)e=wp.media.view.EmbedImage;else{if("link"!==t)return;e=wp.media.view.EmbedLink}this.settings(new e({controller:this.controller,model:this.model.props,priority:40}))},loading:function(){this.$el.toggleClass("embed-loading",this.model.get("loading"))}});e.exports=t},2395:e=>{var t=wp.media.view.Settings.AttachmentDisplay,i=t.extend({className:"embed-media-settings",template:wp.template("embed-image-settings"),initialize:function(){t.prototype.initialize.apply(this,arguments),this.listenTo(this.model,"change:url",this.updateImage)},updateImage:function(){this.$("img").attr("src",this.model.get("url"))}});e.exports=i},8232:e=>{var i=jQuery,t=wp.media.view.Settings.extend({className:"embed-link-settings",template:wp.template("embed-link-settings"),initialize:function(){this.listenTo(this.model,"change:url",this.updateoEmbed)},updateoEmbed:_.debounce(function(){var e=this.model.get("url");this.$(".embed-container").hide().find(".embed-preview").empty(),this.$(".setting").hide(),e&&(e.length<11||!e.match(/^http(s)?:\/\//))||this.fetch()},wp.media.controller.Embed.sensitivity),fetch:function(){var e,t=this.model.get("url");i("#embed-url-field").val()===t&&(this.dfd&&"pending"===this.dfd.state()&&this.dfd.abort(),(e=/https?:\/\/www\.youtube\.com\/embed\/([^/]+)/.exec(t))&&(t="https://www.youtube.com/watch?v="+e[1]),this.dfd=wp.apiRequest({url:wp.media.view.settings.oEmbedProxyUrl,data:{url:t,maxwidth:this.model.get("width"),maxheight:this.model.get("height")},type:"GET",dataType:"json",context:this}).done(function(e){this.renderoEmbed({data:{body:e.html||""}})}).fail(this.renderFail))},renderFail:function(e,t){"abort"!==t&&this.$(".link-text").show()},renderoEmbed:function(e){e=e&&e.data&&e.data.body||"";e?this.$(".embed-container").show().find(".embed-preview").html(e):this.renderFail()}});e.exports=t},7327:e=>{var t=wp.media.View,i=jQuery,s=wp.media.view.l10n,o=t.extend({tagName:"span",className:"embed-url",events:{input:"url"},initialize:function(){this.$input=i('').attr("aria-label",s.insertFromUrlTitle).val(this.model.get("url")),this.input=this.$input[0],this.spinner=i('')[0],this.$el.append([this.input,this.spinner]),this.listenTo(this.model,"change:url",this.render),this.model.get("url")&&_.delay(_.bind(function(){this.model.trigger("change:url")},this),500)},render:function(){var e=this.$input;if(!e.is(":focus"))return this.model.get("url")?this.input.value=this.model.get("url"):this.input.setAttribute("placeholder","https://"),t.prototype.render.apply(this,arguments),this},url:function(e){e=e.target.value||"";this.model.set("url",e.trim())}});e.exports=o},718:e=>{var o=jQuery,t=wp.media.View.extend({events:{keydown:"focusManagementMode"},initialize:function(e){this.mode=e.mode||"constrainTabbing",this.tabsAutomaticActivation=e.tabsAutomaticActivation||!1},focusManagementMode:function(e){"constrainTabbing"===this.mode&&this.constrainTabbing(e),"tabsNavigation"===this.mode&&this.tabsNavigation(e)},getTabbables:function(){return this.$(":tabbable").not('.moxie-shim input[type="file"]')},focus:function(){this.$(".media-modal").trigger("focus")},constrainTabbing:function(e){var t;if(9===e.keyCode)return(t=this.getTabbables()).last()[0]!==e.target||e.shiftKey?t.first()[0]===e.target&&e.shiftKey?(t.last().focus(),!1):void 0:(t.first().focus(),!1)},setAriaHiddenOnBodyChildren:function(t){var e,i=this;this.isBodyAriaHidden||(e=document.body.children,_.each(e,function(e){e!==t[0]&&i.elementShouldBeHidden(e)&&(e.setAttribute("aria-hidden","true"),i.ariaHiddenElements.push(e))}),this.isBodyAriaHidden=!0)},removeAriaHiddenFromBodyChildren:function(){_.each(this.ariaHiddenElements,function(e){e.removeAttribute("aria-hidden")}),this.ariaHiddenElements=[],this.isBodyAriaHidden=!1},elementShouldBeHidden:function(e){var t=e.getAttribute("role");return!("SCRIPT"===e.tagName||e.hasAttribute("aria-hidden")||e.hasAttribute("aria-live")||-1!==["alert","status","log","marquee","timer"].indexOf(t))},isBodyAriaHidden:!1,ariaHiddenElements:[],tabs:o(),setupAriaTabs:function(){this.tabs=this.$('[role="tab"]'),this.tabs.attr({"aria-selected":"false",tabIndex:"-1"}),this.tabs.filter(".active").removeAttr("tabindex").attr("aria-selected","true")},tabsNavigation:function(e){var t="horizontal";-1===[32,35,36,37,38,39,40].indexOf(e.which)||"horizontal"===(t="vertical"===this.$el.attr("aria-orientation")?"vertical":t)&&-1!==[38,40].indexOf(e.which)||"vertical"===t&&-1!==[37,39].indexOf(e.which)||this.switchTabs(e,this.tabs)},switchTabs:function(e){var t,i=e.which,s=this.tabs.index(o(e.target));switch(i){case 32:this.activateTab(this.tabs[s]);break;case 35:e.preventDefault(),this.activateTab(this.tabs[this.tabs.length-1]);break;case 36:e.preventDefault(),this.activateTab(this.tabs[0]);break;case 37:case 38:e.preventDefault(),t=s-1<0?this.tabs.length-1:s-1,this.activateTab(this.tabs[t]);break;case 39:case 40:e.preventDefault(),t=s+1===this.tabs.length?0:s+1,this.activateTab(this.tabs[t])}},activateTab:function(e){e&&(e.focus(),this.tabsAutomaticActivation?(e.removeAttribute("tabindex"),e.setAttribute("aria-selected","true"),e.click()):o(e).on("click",function(){e.removeAttribute("tabindex"),e.setAttribute("aria-selected","true")}))}});e.exports=t},1061:e=>{var t=wp.media.View.extend({initialize:function(){_.defaults(this.options,{mode:["select"]}),this._createRegions(),this._createStates(),this._createModes()},_createRegions:function(){this.regions=this.regions?this.regions.slice():[],_.each(this.regions,function(e){this[e]=new wp.media.controller.Region({view:this,id:e,selector:".media-frame-"+e})},this)},_createStates:function(){this.states=new Backbone.Collection(null,{model:wp.media.controller.State}),this.states.on("add",function(e){e.frame=this,e.trigger("ready")},this),this.options.states&&this.states.add(this.options.states)},_createModes:function(){this.activeModes=new Backbone.Collection,this.activeModes.on("add remove reset",_.bind(this.triggerModeEvents,this)),_.each(this.options.mode,function(e){this.activateMode(e)},this)},reset:function(){return this.states.invoke("trigger","reset"),this},triggerModeEvents:function(e,t,i){var s,o={add:"activate",remove:"deactivate"};_.each(i,function(e,t){e&&(s=t)}),_.has(o,s)&&(i=e.get("id")+":"+o[s],this.trigger(i))},activateMode:function(e){if(!this.isModeActive(e))return this.activeModes.add([{id:e}]),this.$el.addClass("mode-"+e),this},deactivateMode:function(e){return this.isModeActive(e)&&(this.activeModes.remove(this.activeModes.where({id:e})),this.$el.removeClass("mode-"+e),this.trigger(e+":deactivate")),this},isModeActive:function(e){return Boolean(this.activeModes.where({id:e}).length)}});_.extend(t.prototype,wp.media.controller.StateMachine.prototype),e.exports=t},5424:e=>{var t=wp.media.view.MediaFrame.Select,s=wp.media.view.l10n,i=t.extend({defaults:{id:"image",url:"",menu:"image-details",content:"image-details",toolbar:"image-details",type:"link",title:s.imageDetailsTitle,priority:120},initialize:function(e){this.image=new wp.media.model.PostImage(e.metadata),this.options.selection=new wp.media.model.Selection(this.image.attachment,{multiple:!1}),t.prototype.initialize.apply(this,arguments)},bindHandlers:function(){t.prototype.bindHandlers.apply(this,arguments),this.on("menu:create:image-details",this.createMenu,this),this.on("content:create:image-details",this.imageDetailsContent,this),this.on("content:render:edit-image",this.editImageContent,this),this.on("toolbar:render:image-details",this.renderImageDetailsToolbar,this),this.on("toolbar:render:replace",this.renderReplaceImageToolbar,this)},createStates:function(){this.states.add([new wp.media.controller.ImageDetails({image:this.image,editable:!1}),new wp.media.controller.ReplaceImage({id:"replace-image",library:wp.media.query({type:"image"}),image:this.image,multiple:!1,title:s.imageReplaceTitle,toolbar:"replace",priority:80,displaySettings:!0}),new wp.media.controller.EditImage({image:this.image,selection:this.options.selection})])},imageDetailsContent:function(e){e.view=new wp.media.view.ImageDetails({controller:this,model:this.state().image,attachment:this.state().image.attachment})},editImageContent:function(){var e=this.state().get("image");e&&(e=new wp.media.view.EditImage({model:e,controller:this}).render(),this.content.set(e),e.loadEditor())},renderImageDetailsToolbar:function(){this.toolbar.set(new wp.media.view.Toolbar({controller:this,items:{select:{style:"primary",text:s.update,priority:80,click:function(){var e=this.controller,t=e.state();e.close(),t.trigger("update",e.image.toJSON()),e.setState(e.options.state),e.reset()}}}}))},renderReplaceImageToolbar:function(){var e=this,t=e.lastState(),i=t&&t.id;this.toolbar.set(new wp.media.view.Toolbar({controller:this,items:{back:{text:s.back,priority:80,click:function(){i?e.setState(i):e.close()}},replace:{style:"primary",text:s.replace,priority:20,requires:{selection:!0},click:function(){var e=this.controller,t=e.state(),i=t.get("selection").single();e.close(),e.image.changeAttachment(i,t.display(i)),t.trigger("replace",e.image.toJSON()),e.setState(e.options.state),e.reset()}}}}))}});e.exports=i},4274:e=>{var t=wp.media.view.MediaFrame.Select,i=wp.media.controller.Library,o=wp.media.view.l10n,s=t.extend({initialize:function(){this.counts={audio:{count:wp.media.view.settings.attachmentCounts.audio,state:"playlist"},video:{count:wp.media.view.settings.attachmentCounts.video,state:"video-playlist"}},_.defaults(this.options,{multiple:!0,editing:!1,state:"insert",metadata:{}}),t.prototype.initialize.apply(this,arguments),this.createIframeStates()},createStates:function(){var e=this.options;this.states.add([new i({id:"insert",title:o.insertMediaTitle,priority:20,toolbar:"main-insert",filterable:"all",library:wp.media.query(e.library),multiple:!!e.multiple&&"reset",editable:!0,allowLocalEdits:!0,displaySettings:!0,displayUserSettings:!0}),new i({id:"gallery",title:o.createGalleryTitle,priority:40,toolbar:"main-gallery",filterable:"uploaded",multiple:"add",editable:!1,library:wp.media.query(_.defaults({type:"image"},e.library))}),new wp.media.controller.Embed({metadata:e.metadata}),new wp.media.controller.EditImage({model:e.editImage}),new wp.media.controller.GalleryEdit({library:e.selection,editing:e.editing,menu:"gallery"}),new wp.media.controller.GalleryAdd,new i({id:"playlist",title:o.createPlaylistTitle,priority:60,toolbar:"main-playlist",filterable:"uploaded",multiple:"add",editable:!1,library:wp.media.query(_.defaults({type:"audio"},e.library))}),new wp.media.controller.CollectionEdit({type:"audio",collectionType:"playlist",title:o.editPlaylistTitle,SettingsView:wp.media.view.Settings.Playlist,library:e.selection,editing:e.editing,menu:"playlist",dragInfoText:o.playlistDragInfo,dragInfo:!1}),new wp.media.controller.CollectionAdd({type:"audio",collectionType:"playlist",title:o.addToPlaylistTitle}),new i({id:"video-playlist",title:o.createVideoPlaylistTitle,priority:60,toolbar:"main-video-playlist",filterable:"uploaded",multiple:"add",editable:!1,library:wp.media.query(_.defaults({type:"video"},e.library))}),new wp.media.controller.CollectionEdit({type:"video",collectionType:"playlist",title:o.editVideoPlaylistTitle,SettingsView:wp.media.view.Settings.Playlist,library:e.selection,editing:e.editing,menu:"video-playlist",dragInfoText:o.videoPlaylistDragInfo,dragInfo:!1}),new wp.media.controller.CollectionAdd({type:"video",collectionType:"playlist",title:o.addToVideoPlaylistTitle})]),wp.media.view.settings.post.featuredImageId&&this.states.add(new wp.media.controller.FeaturedImage)},bindHandlers:function(){t.prototype.bindHandlers.apply(this,arguments),this.on("activate",this.activate,this),void 0!==_.find(this.counts,function(e){return 0===e.count})&&this.listenTo(wp.media.model.Attachments.all,"change:type",this.mediaTypeCounts),this.on("menu:create:gallery",this.createMenu,this),this.on("menu:create:playlist",this.createMenu,this),this.on("menu:create:video-playlist",this.createMenu,this),this.on("toolbar:create:main-insert",this.createToolbar,this),this.on("toolbar:create:main-gallery",this.createToolbar,this),this.on("toolbar:create:main-playlist",this.createToolbar,this),this.on("toolbar:create:main-video-playlist",this.createToolbar,this),this.on("toolbar:create:featured-image",this.featuredImageToolbar,this),this.on("toolbar:create:main-embed",this.mainEmbedToolbar,this),_.each({menu:{default:"mainMenu",gallery:"galleryMenu",playlist:"playlistMenu","video-playlist":"videoPlaylistMenu"},content:{embed:"embedContent","edit-image":"editImageContent","edit-selection":"editSelectionContent"},toolbar:{"main-insert":"mainInsertToolbar","main-gallery":"mainGalleryToolbar","gallery-edit":"galleryEditToolbar","gallery-add":"galleryAddToolbar","main-playlist":"mainPlaylistToolbar","playlist-edit":"playlistEditToolbar","playlist-add":"playlistAddToolbar","main-video-playlist":"mainVideoPlaylistToolbar","video-playlist-edit":"videoPlaylistEditToolbar","video-playlist-add":"videoPlaylistAddToolbar"}},function(e,i){_.each(e,function(e,t){this.on(i+":render:"+t,this[e],this)},this)},this)},activate:function(){_.each(this.counts,function(e){e.count<1&&this.menuItemVisibility(e.state,"hide")},this)},mediaTypeCounts:function(e,t){void 0!==this.counts[t]&&this.counts[t].count<1&&(this.counts[t].count++,this.menuItemVisibility(this.counts[t].state,"show"))},mainMenu:function(e){e.set({"library-separator":new wp.media.View({className:"separator",priority:100,attributes:{role:"presentation"}})})},menuItemVisibility:function(e,t){var i=this.menu.get();"hide"===t?i.hide(e):"show"===t&&i.show(e)},galleryMenu:function(e){var t=this.lastState(),i=t&&t.id,s=this;e.set({cancel:{text:o.cancelGalleryTitle,priority:20,click:function(){i?s.setState(i):s.close(),this.controller.modal.focusManager.focus()}},separateCancel:new wp.media.View({className:"separator",priority:40})})},playlistMenu:function(e){var t=this.lastState(),i=t&&t.id,s=this;e.set({cancel:{text:o.cancelPlaylistTitle,priority:20,click:function(){i?s.setState(i):s.close(),this.controller.modal.focusManager.focus()}},separateCancel:new wp.media.View({className:"separator",priority:40})})},videoPlaylistMenu:function(e){var t=this.lastState(),i=t&&t.id,s=this;e.set({cancel:{text:o.cancelVideoPlaylistTitle,priority:20,click:function(){i?s.setState(i):s.close(),this.controller.modal.focusManager.focus()}},separateCancel:new wp.media.View({className:"separator",priority:40})})},embedContent:function(){var e=new wp.media.view.Embed({controller:this,model:this.state()}).render();this.content.set(e)},editSelectionContent:function(){var e=this.state(),t=e.get("selection"),t=new wp.media.view.AttachmentsBrowser({controller:this,collection:t,selection:t,model:e,sortable:!0,search:!1,date:!1,dragInfo:!0,AttachmentView:wp.media.view.Attachments.EditSelection}).render();t.toolbar.set("backToLibrary",{text:o.returnToLibrary,priority:-100,click:function(){this.controller.content.mode("browse"),this.controller.modal.focusManager.focus()}}),this.content.set(t),this.trigger("edit:selection",this)},editImageContent:function(){var e=this.state().get("image"),e=new wp.media.view.EditImage({model:e,controller:this}).render();this.content.set(e),e.loadEditor()},selectionStatusToolbar:function(e){var t=this.state().get("editable");e.set("selection",new wp.media.view.Selection({controller:this,collection:this.state().get("selection"),priority:-40,editable:t&&function(){this.controller.content.mode("edit-selection")}}).render())},mainInsertToolbar:function(e){var i=this;this.selectionStatusToolbar(e),e.set("insert",{style:"primary",priority:80,text:o.insertIntoPost,requires:{selection:!0},click:function(){var e=i.state(),t=e.get("selection");i.close(),e.trigger("insert",t).reset()}})},mainGalleryToolbar:function(e){var s=this;this.selectionStatusToolbar(e),e.set("gallery",{style:"primary",text:o.createNewGallery,priority:60,requires:{selection:!0},click:function(){var e=s.state().get("selection"),t=s.state("gallery-edit"),i=e.where({type:"image"});t.set("library",new wp.media.model.Selection(i,{props:e.props.toJSON(),multiple:!0})),this.controller.setState("gallery-edit"),this.controller.modal.focusManager.focus()}})},mainPlaylistToolbar:function(e){var s=this;this.selectionStatusToolbar(e),e.set("playlist",{style:"primary",text:o.createNewPlaylist,priority:100,requires:{selection:!0},click:function(){var e=s.state().get("selection"),t=s.state("playlist-edit"),i=e.where({type:"audio"});t.set("library",new wp.media.model.Selection(i,{props:e.props.toJSON(),multiple:!0})),this.controller.setState("playlist-edit"),this.controller.modal.focusManager.focus()}})},mainVideoPlaylistToolbar:function(e){var s=this;this.selectionStatusToolbar(e),e.set("video-playlist",{style:"primary",text:o.createNewVideoPlaylist,priority:100,requires:{selection:!0},click:function(){var e=s.state().get("selection"),t=s.state("video-playlist-edit"),i=e.where({type:"video"});t.set("library",new wp.media.model.Selection(i,{props:e.props.toJSON(),multiple:!0})),this.controller.setState("video-playlist-edit"),this.controller.modal.focusManager.focus()}})},featuredImageToolbar:function(e){this.createSelectToolbar(e,{text:o.setFeaturedImage,state:this.options.state})},mainEmbedToolbar:function(e){e.view=new wp.media.view.Toolbar.Embed({controller:this})},galleryEditToolbar:function(){var e=this.state().get("editing");this.toolbar.set(new wp.media.view.Toolbar({controller:this,items:{insert:{style:"primary",text:e?o.updateGallery:o.insertGallery,priority:80,requires:{library:!0},click:function(){var e=this.controller,t=e.state();e.close(),t.trigger("update",t.get("library")),e.setState(e.options.state),e.reset()}}}}))},galleryAddToolbar:function(){this.toolbar.set(new wp.media.view.Toolbar({controller:this,items:{insert:{style:"primary",text:o.addToGallery,priority:80,requires:{selection:!0},click:function(){var e=this.controller,t=e.state();e.state("gallery-edit").get("library").add(t.get("selection").models),t.trigger("reset"),e.setState("gallery-edit"),this.controller.modal.focusManager.focus()}}}}))},playlistEditToolbar:function(){var e=this.state().get("editing");this.toolbar.set(new wp.media.view.Toolbar({controller:this,items:{insert:{style:"primary",text:e?o.updatePlaylist:o.insertPlaylist,priority:80,requires:{library:!0},click:function(){var e=this.controller,t=e.state();e.close(),t.trigger("update",t.get("library")),e.setState(e.options.state),e.reset()}}}}))},playlistAddToolbar:function(){this.toolbar.set(new wp.media.view.Toolbar({controller:this,items:{insert:{style:"primary",text:o.addToPlaylist,priority:80,requires:{selection:!0},click:function(){var e=this.controller,t=e.state();e.state("playlist-edit").get("library").add(t.get("selection").models),t.trigger("reset"),e.setState("playlist-edit"),this.controller.modal.focusManager.focus()}}}}))},videoPlaylistEditToolbar:function(){var e=this.state().get("editing");this.toolbar.set(new wp.media.view.Toolbar({controller:this,items:{insert:{style:"primary",text:e?o.updateVideoPlaylist:o.insertVideoPlaylist,priority:140,requires:{library:!0},click:function(){var e=this.controller,t=e.state(),i=t.get("library");i.type="video",e.close(),t.trigger("update",i),e.setState(e.options.state),e.reset()}}}}))},videoPlaylistAddToolbar:function(){this.toolbar.set(new wp.media.view.Toolbar({controller:this,items:{insert:{style:"primary",text:o.addToVideoPlaylist,priority:140,requires:{selection:!0},click:function(){var e=this.controller,t=e.state();e.state("video-playlist-edit").get("library").add(t.get("selection").models),t.trigger("reset"),e.setState("video-playlist-edit"),this.controller.modal.focusManager.focus()}}}}))}});e.exports=s},455:e=>{var t=wp.media.view.MediaFrame,i=wp.media.view.l10n,s=t.extend({initialize:function(){t.prototype.initialize.apply(this,arguments),_.defaults(this.options,{selection:[],library:{},multiple:!1,state:"library"}),this.createSelection(),this.createStates(),this.bindHandlers()},createSelection:function(){var e=this.options.selection;e instanceof wp.media.model.Selection||(this.options.selection=new wp.media.model.Selection(e,{multiple:this.options.multiple})),this._selection={attachments:new wp.media.model.Attachments,difference:[]}},editImageContent:function(){var e=this.state().get("image"),e=new wp.media.view.EditImage({model:e,controller:this}).render();this.content.set(e),e.loadEditor()},createStates:function(){var e=this.options;this.options.states||this.states.add([new wp.media.controller.Library({library:wp.media.query(e.library),multiple:e.multiple,title:e.title,priority:20}),new wp.media.controller.EditImage({model:e.editImage})])},bindHandlers:function(){this.on("router:create:browse",this.createRouter,this),this.on("router:render:browse",this.browseRouter,this),this.on("content:create:browse",this.browseContent,this),this.on("content:render:upload",this.uploadContent,this),this.on("toolbar:create:select",this.createSelectToolbar,this),this.on("content:render:edit-image",this.editImageContent,this)},browseRouter:function(e){e.set({upload:{text:i.uploadFilesTitle,priority:20},browse:{text:i.mediaLibraryTitle,priority:40}})},browseContent:function(e){var t=this.state();this.$el.removeClass("hide-toolbar"),e.view=new wp.media.view.AttachmentsBrowser({controller:this,collection:t.get("library"),selection:t.get("selection"),model:t,sortable:t.get("sortable"),search:t.get("searchable"),filters:t.get("filterable"),date:t.get("date"),display:t.has("display")?t.get("display"):t.get("displaySettings"),dragInfo:t.get("dragInfo"),idealColumnWidth:t.get("idealColumnWidth"),suggestedWidth:t.get("suggestedWidth"),suggestedHeight:t.get("suggestedHeight"),AttachmentView:t.get("AttachmentView")})},uploadContent:function(){this.$el.removeClass("hide-toolbar"),this.content.set(new wp.media.view.UploaderInline({controller:this}))},createSelectToolbar:function(e,t){(t=t||this.options.button||{}).controller=this,e.view=new wp.media.view.Toolbar.Select(t)}});e.exports=s},170:e=>{var t=wp.media.View.extend({tagName:function(){return this.options.level||"h1"},className:"media-views-heading",initialize:function(){this.options.className&&this.$el.addClass(this.options.className),this.text=this.options.text},render:function(){return this.$el.html(this.text),this}});e.exports=t},1982:e=>{var t=wp.media.View.extend({className:"media-iframe",render:function(){return this.views.detach(),this.$el.html('"):"application/x-shockwave-flash"===n.source1mime?(d='',m.poster&&(d+=''),d+=""):-1!==n.source1mime.indexOf("audio")?(s=n,(l=p)?l(s):'"):"script"===n.type?''; }; var dataToHtml = function (editor, dataIn) { var data = global$2.extend({}, dataIn); if (!data.source1) { global$2.extend(data, HtmlToData.htmlToData(Settings.getScripts(editor), data.embed)); if (!data.source1) { return ''; } } if (!data.source2) { data.source2 = ''; } if (!data.poster) { data.poster = ''; } data.source1 = editor.convertURL(data.source1, 'source'); data.source2 = editor.convertURL(data.source2, 'source'); data.source1mime = Mime.guess(data.source1); data.source2mime = Mime.guess(data.source2); data.poster = editor.convertURL(data.poster, 'poster'); var pattern = matchPattern(data.source1); if (pattern) { data.source1 = pattern.url; data.type = pattern.type; data.allowFullscreen = pattern.allowFullscreen; data.width = data.width || pattern.w; data.height = data.height || pattern.h; } if (data.embed) { return UpdateHtml.updateHtml(data.embed, data, true); } else { var videoScript = VideoScript.getVideoScriptMatch(Settings.getScripts(editor), data.source1); if (videoScript) { data.type = 'script'; data.width = videoScript.width; data.height = videoScript.height; } var audioTemplateCallback = Settings.getAudioTemplateCallback(editor); var videoTemplateCallback = Settings.getVideoTemplateCallback(editor); data.width = data.width || 300; data.height = data.height || 150; global$2.each(data, function (value, key) { data[key] = editor.dom.encode(value); }); if (data.type === 'iframe') { return getIframeHtml(data); } else if (data.source1mime === 'application/x-shockwave-flash') { return getFlashHtml(data); } else if (data.source1mime.indexOf('audio') !== -1) { return getAudioHtml(data, audioTemplateCallback); } else if (data.type === 'script') { return getScriptHtml(data); } else { return getVideoHtml(data, videoTemplateCallback); } } }; var DataToHtml = { dataToHtml: dataToHtml }; var cache = {}; var embedPromise = function (data, dataToHtml, handler) { return new global$5(function (res, rej) { var wrappedResolve = function (response) { if (response.html) { cache[data.source1] = response; } return res({ url: data.source1, html: response.html ? response.html : dataToHtml(data) }); }; if (cache[data.source1]) { wrappedResolve(cache[data.source1]); } else { handler({ url: data.source1 }, wrappedResolve, rej); } }); }; var defaultPromise = function (data, dataToHtml) { return new global$5(function (res) { res({ html: dataToHtml(data), url: data.source1 }); }); }; var loadedData = function (editor) { return function (data) { return DataToHtml.dataToHtml(editor, data); }; }; var getEmbedHtml = function (editor, data) { var embedHandler = Settings.getUrlResolver(editor); return embedHandler ? embedPromise(data, loadedData(editor), embedHandler) : defaultPromise(data, loadedData(editor)); }; var isCached = function (url) { return cache.hasOwnProperty(url); }; var Service = { getEmbedHtml: getEmbedHtml, isCached: isCached }; var trimPx$1 = function (value) { return value.replace(/px$/, ''); }; var addPx$1 = function (value) { return /^[0-9.]+$/.test(value) ? value + 'px' : value; }; var getSize = function (name) { return function (elm) { return elm ? trimPx$1(elm.style[name]) : ''; }; }; var setSize = function (name) { return function (elm, value) { if (elm) { elm.style[name] = addPx$1(value); } }; }; var Size = { getMaxWidth: getSize('maxWidth'), getMaxHeight: getSize('maxHeight'), setMaxWidth: setSize('maxWidth'), setMaxHeight: setSize('maxHeight') }; var doSyncSize = function (widthCtrl, heightCtrl) { widthCtrl.state.set('oldVal', widthCtrl.value()); heightCtrl.state.set('oldVal', heightCtrl.value()); }; var doSizeControls = function (win, f) { var widthCtrl = win.find('#width')[0]; var heightCtrl = win.find('#height')[0]; var constrained = win.find('#constrain')[0]; if (widthCtrl && heightCtrl && constrained) { f(widthCtrl, heightCtrl, constrained.checked()); } }; var doUpdateSize = function (widthCtrl, heightCtrl, isContrained) { var oldWidth = widthCtrl.state.get('oldVal'); var oldHeight = heightCtrl.state.get('oldVal'); var newWidth = widthCtrl.value(); var newHeight = heightCtrl.value(); if (isContrained && oldWidth && oldHeight && newWidth && newHeight) { if (newWidth !== oldWidth) { newHeight = Math.round(newWidth / oldWidth * newHeight); if (!isNaN(newHeight)) { heightCtrl.value(newHeight); } } else { newWidth = Math.round(newHeight / oldHeight * newWidth); if (!isNaN(newWidth)) { widthCtrl.value(newWidth); } } } doSyncSize(widthCtrl, heightCtrl); }; var syncSize = function (win) { doSizeControls(win, doSyncSize); }; var updateSize = function (win) { doSizeControls(win, doUpdateSize); }; var createUi = function (onChange) { var recalcSize = function () { onChange(function (win) { updateSize(win); }); }; return { type: 'container', label: 'Dimensions', layout: 'flex', align: 'center', spacing: 5, items: [ { name: 'width', type: 'textbox', maxLength: 5, size: 5, onchange: recalcSize, ariaLabel: 'Width' }, { type: 'label', text: 'x' }, { name: 'height', type: 'textbox', maxLength: 5, size: 5, onchange: recalcSize, ariaLabel: 'Height' }, { name: 'constrain', type: 'checkbox', checked: true, text: 'Constrain proportions' } ] }; }; var SizeManager = { createUi: createUi, syncSize: syncSize, updateSize: updateSize }; var embedChange = global$1.ie && global$1.ie <= 8 ? 'onChange' : 'onInput'; var handleError = function (editor) { return function (error) { var errorMessage = error && error.msg ? 'Media embed handler error: ' + error.msg : 'Media embed handler threw unknown error.'; editor.notificationManager.open({ type: 'error', text: errorMessage }); }; }; var getData = function (editor) { var element = editor.selection.getNode(); var dataEmbed = element.getAttribute('data-ephox-embed-iri'); if (dataEmbed) { return { 'source1': dataEmbed, 'data-ephox-embed-iri': dataEmbed, 'width': Size.getMaxWidth(element), 'height': Size.getMaxHeight(element) }; } return element.getAttribute('data-mce-object') ? HtmlToData.htmlToData(Settings.getScripts(editor), editor.serializer.serialize(element, { selection: true })) : {}; }; var getSource = function (editor) { var elm = editor.selection.getNode(); if (elm.getAttribute('data-mce-object') || elm.getAttribute('data-ephox-embed-iri')) { return editor.selection.getContent(); } }; var addEmbedHtml = function (win, editor) { return function (response) { var html = response.html; var embed = win.find('#embed')[0]; var data = global$2.extend(HtmlToData.htmlToData(Settings.getScripts(editor), html), { source1: response.url }); win.fromJSON(data); if (embed) { embed.value(html); SizeManager.updateSize(win); } }; }; var selectPlaceholder = function (editor, beforeObjects) { var i; var y; var afterObjects = editor.dom.select('img[data-mce-object]'); for (i = 0; i < beforeObjects.length; i++) { for (y = afterObjects.length - 1; y >= 0; y--) { if (beforeObjects[i] === afterObjects[y]) { afterObjects.splice(y, 1); } } } editor.selection.select(afterObjects[0]); }; var handleInsert = function (editor, html) { var beforeObjects = editor.dom.select('img[data-mce-object]'); editor.insertContent(html); selectPlaceholder(editor, beforeObjects); editor.nodeChanged(); }; var submitForm = function (win, editor) { var data = win.toJSON(); data.embed = UpdateHtml.updateHtml(data.embed, data); if (data.embed && Service.isCached(data.source1)) { handleInsert(editor, data.embed); } else { Service.getEmbedHtml(editor, data).then(function (response) { handleInsert(editor, response.html); }).catch(handleError(editor)); } }; var populateMeta = function (win, meta) { global$2.each(meta, function (value, key) { win.find('#' + key).value(value); }); }; var showDialog = function (editor) { var win; var data; var generalFormItems = [{ name: 'source1', type: 'filepicker', filetype: 'media', size: 40, autofocus: true, label: 'Source', onpaste: function () { setTimeout(function () { Service.getEmbedHtml(editor, win.toJSON()).then(addEmbedHtml(win, editor)).catch(handleError(editor)); }, 1); }, onchange: function (e) { Service.getEmbedHtml(editor, win.toJSON()).then(addEmbedHtml(win, editor)).catch(handleError(editor)); populateMeta(win, e.meta); }, onbeforecall: function (e) { e.meta = win.toJSON(); } }]; var advancedFormItems = []; var reserialise = function (update) { update(win); data = win.toJSON(); win.find('#embed').value(UpdateHtml.updateHtml(data.embed, data)); }; if (Settings.hasAltSource(editor)) { advancedFormItems.push({ name: 'source2', type: 'filepicker', filetype: 'media', size: 40, label: 'Alternative source' }); } if (Settings.hasPoster(editor)) { advancedFormItems.push({ name: 'poster', type: 'filepicker', filetype: 'image', size: 40, label: 'Poster' }); } if (Settings.hasDimensions(editor)) { var control = SizeManager.createUi(reserialise); generalFormItems.push(control); } data = getData(editor); var embedTextBox = { id: 'mcemediasource', type: 'textbox', flex: 1, name: 'embed', value: getSource(editor), multiline: true, rows: 5, label: 'Source' }; var updateValueOnChange = function () { data = global$2.extend({}, HtmlToData.htmlToData(Settings.getScripts(editor), this.value())); this.parent().parent().fromJSON(data); }; embedTextBox[embedChange] = updateValueOnChange; var body = [ { title: 'General', type: 'form', items: generalFormItems }, { title: 'Embed', type: 'container', layout: 'flex', direction: 'column', align: 'stretch', padding: 10, spacing: 10, items: [ { type: 'label', text: 'Paste your embed code below:', forId: 'mcemediasource' }, embedTextBox ] } ]; if (advancedFormItems.length > 0) { body.push({ title: 'Advanced', type: 'form', items: advancedFormItems }); } win = editor.windowManager.open({ title: 'Insert/edit media', data: data, bodyType: 'tabpanel', body: body, onSubmit: function () { SizeManager.updateSize(win); submitForm(win, editor); } }); SizeManager.syncSize(win); }; var Dialog = { showDialog: showDialog }; var get$1 = function (editor) { var showDialog = function () { Dialog.showDialog(editor); }; return { showDialog: showDialog }; }; var Api = { get: get$1 }; var register = function (editor) { var showDialog = function () { Dialog.showDialog(editor); }; editor.addCommand('mceMedia', showDialog); }; var Commands = { register: register }; var global$8 = tinymce.util.Tools.resolve('tinymce.html.Node'); var sanitize = function (editor, html) { if (Settings.shouldFilterHtml(editor) === false) { return html; } var writer = global$7(); var blocked; global$4({ validate: false, allow_conditional_comments: false, special: 'script,noscript', comment: function (text) { writer.comment(text); }, cdata: function (text) { writer.cdata(text); }, text: function (text, raw) { writer.text(text, raw); }, start: function (name, attrs, empty) { blocked = true; if (name === 'script' || name === 'noscript' || name === 'svg') { return; } for (var i = attrs.length - 1; i >= 0; i--) { var attrName = attrs[i].name; if (attrName.indexOf('on') === 0) { delete attrs.map[attrName]; attrs.splice(i, 1); } if (attrName === 'style') { attrs[i].value = editor.dom.serializeStyle(editor.dom.parseStyle(attrs[i].value), name); } } writer.start(name, attrs, empty); blocked = false; }, end: function (name) { if (blocked) { return; } writer.end(name); } }, global$6({})).parse(html); return writer.getContent(); }; var Sanitize = { sanitize: sanitize }; var createPlaceholderNode = function (editor, node) { var placeHolder; var name = node.name; placeHolder = new global$8('img', 1); placeHolder.shortEnded = true; retainAttributesAndInnerHtml(editor, node, placeHolder); placeHolder.attr({ 'width': node.attr('width') || '300', 'height': node.attr('height') || (name === 'audio' ? '30' : '150'), 'style': node.attr('style'), 'src': global$1.transparentSrc, 'data-mce-object': name, 'class': 'mce-object mce-object-' + name }); return placeHolder; }; var createPreviewIframeNode = function (editor, node) { var previewWrapper; var previewNode; var shimNode; var name = node.name; previewWrapper = new global$8('span', 1); previewWrapper.attr({ 'contentEditable': 'false', 'style': node.attr('style'), 'data-mce-object': name, 'class': 'mce-preview-object mce-object-' + name }); retainAttributesAndInnerHtml(editor, node, previewWrapper); previewNode = new global$8(name, 1); previewNode.attr({ src: node.attr('src'), allowfullscreen: node.attr('allowfullscreen'), style: node.attr('style'), class: node.attr('class'), width: node.attr('width'), height: node.attr('height'), frameborder: '0' }); shimNode = new global$8('span', 1); shimNode.attr('class', 'mce-shim'); previewWrapper.append(previewNode); previewWrapper.append(shimNode); return previewWrapper; }; var retainAttributesAndInnerHtml = function (editor, sourceNode, targetNode) { var attrName; var attrValue; var attribs; var ai; var innerHtml; attribs = sourceNode.attributes; ai = attribs.length; while (ai--) { attrName = attribs[ai].name; attrValue = attribs[ai].value; if (attrName !== 'width' && attrName !== 'height' && attrName !== 'style') { if (attrName === 'data' || attrName === 'src') { attrValue = editor.convertURL(attrValue, attrName); } targetNode.attr('data-mce-p-' + attrName, attrValue); } } innerHtml = sourceNode.firstChild && sourceNode.firstChild.value; if (innerHtml) { targetNode.attr('data-mce-html', escape(Sanitize.sanitize(editor, innerHtml))); targetNode.firstChild = null; } }; var isWithinEphoxEmbed = function (node) { while (node = node.parent) { if (node.attr('data-ephox-embed-iri')) { return true; } } return false; }; var placeHolderConverter = function (editor) { return function (nodes) { var i = nodes.length; var node; var videoScript; while (i--) { node = nodes[i]; if (!node.parent) { continue; } if (node.parent.attr('data-mce-object')) { continue; } if (node.name === 'script') { videoScript = VideoScript.getVideoScriptMatch(Settings.getScripts(editor), node.attr('src')); if (!videoScript) { continue; } } if (videoScript) { if (videoScript.width) { node.attr('width', videoScript.width.toString()); } if (videoScript.height) { node.attr('height', videoScript.height.toString()); } } if (node.name === 'iframe' && Settings.hasLiveEmbeds(editor) && global$1.ceFalse) { if (!isWithinEphoxEmbed(node)) { node.replace(createPreviewIframeNode(editor, node)); } } else { if (!isWithinEphoxEmbed(node)) { node.replace(createPlaceholderNode(editor, node)); } } } }; }; var Nodes = { createPreviewIframeNode: createPreviewIframeNode, createPlaceholderNode: createPlaceholderNode, placeHolderConverter: placeHolderConverter }; var setup = function (editor) { editor.on('preInit', function () { var specialElements = editor.schema.getSpecialElements(); global$2.each('video audio iframe object'.split(' '), function (name) { specialElements[name] = new RegExp(']*>', 'gi'); }); var boolAttrs = editor.schema.getBoolAttrs(); global$2.each('webkitallowfullscreen mozallowfullscreen allowfullscreen'.split(' '), function (name) { boolAttrs[name] = {}; }); editor.parser.addNodeFilter('iframe,video,audio,object,embed,script', Nodes.placeHolderConverter(editor)); editor.serializer.addAttributeFilter('data-mce-object', function (nodes, name) { var i = nodes.length; var node; var realElm; var ai; var attribs; var innerHtml; var innerNode; var realElmName; var className; while (i--) { node = nodes[i]; if (!node.parent) { continue; } realElmName = node.attr(name); realElm = new global$8(realElmName, 1); if (realElmName !== 'audio' && realElmName !== 'script') { className = node.attr('class'); if (className && className.indexOf('mce-preview-object') !== -1) { realElm.attr({ width: node.firstChild.attr('width'), height: node.firstChild.attr('height') }); } else { realElm.attr({ width: node.attr('width'), height: node.attr('height') }); } } realElm.attr({ style: node.attr('style') }); attribs = node.attributes; ai = attribs.length; while (ai--) { var attrName = attribs[ai].name; if (attrName.indexOf('data-mce-p-') === 0) { realElm.attr(attrName.substr(11), attribs[ai].value); } } if (realElmName === 'script') { realElm.attr('type', 'text/javascript'); } innerHtml = node.attr('data-mce-html'); if (innerHtml) { innerNode = new global$8('#text', 3); innerNode.raw = true; innerNode.value = Sanitize.sanitize(editor, unescape(innerHtml)); realElm.append(innerNode); } node.replace(realElm); } }); }); editor.on('setContent', function () { editor.$('span.mce-preview-object').each(function (index, elm) { var $elm = editor.$(elm); if ($elm.find('span.mce-shim', elm).length === 0) { $elm.append(''); } }); }); }; var FilterContent = { setup: setup }; var setup$1 = function (editor) { editor.on('ResolveName', function (e) { var name; if (e.target.nodeType === 1 && (name = e.target.getAttribute('data-mce-object'))) { e.name = name; } }); }; var ResolveName = { setup: setup$1 }; var setup$2 = function (editor) { editor.on('click keyup', function () { var selectedNode = editor.selection.getNode(); if (selectedNode && editor.dom.hasClass(selectedNode, 'mce-preview-object')) { if (editor.dom.getAttrib(selectedNode, 'data-mce-selected')) { selectedNode.setAttribute('data-mce-selected', '2'); } } }); editor.on('ObjectSelected', function (e) { var objectType = e.target.getAttribute('data-mce-object'); if (objectType === 'audio' || objectType === 'script') { e.preventDefault(); } }); editor.on('objectResized', function (e) { var target = e.target; var html; if (target.getAttribute('data-mce-object')) { html = target.getAttribute('data-mce-html'); if (html) { html = unescape(html); target.setAttribute('data-mce-html', escape(UpdateHtml.updateHtml(html, { width: e.width, height: e.height }))); } } }); }; var Selection = { setup: setup$2 }; var register$1 = function (editor) { editor.addButton('media', { tooltip: 'Insert/edit media', cmd: 'mceMedia', stateSelector: [ 'img[data-mce-object]', 'span[data-mce-object]', 'div[data-ephox-embed-iri]' ] }); editor.addMenuItem('media', { icon: 'media', text: 'Media', cmd: 'mceMedia', context: 'insert', prependToContext: true }); }; var Buttons = { register: register$1 }; global.add('media', function (editor) { Commands.register(editor); Buttons.register(editor); ResolveName.setup(editor); FilterContent.setup(editor); Selection.setup(editor); return Api.get(editor); }); function Plugin () { } return Plugin; }()); })(); tinymce/plugins/wpdialogs/plugin.min.js000064400000002452147573120640014320 0ustar00tinymce.WPWindowManager=tinymce.InlineWindowManager=function(a){if(this.wp)return this;this.wp={},this.parent=a.windowManager,this.editor=a,tinymce.extend(this,this.parent),this.open=function(e,i){var n,o=this,t=this.wp;if(!e.wpDialog)return this.parent.open.apply(this,arguments);e.id&&("undefined"!=typeof jQuery&&jQuery.wp&&jQuery.wp.wpdialog?(t.$element=n=jQuery("#"+e.id),n.length&&(window.console&&window.console.log&&window.console.log("tinymce.WPWindowManager is deprecated. Use the default editor.windowManager to open dialogs with inline HTML."),t.features=e,t.params=i,a.nodeChanged(),n.data("wpdialog")||n.wpdialog({title:e.title,width:e.width,height:e.height,modal:!0,dialogClass:"wp-dialog",zIndex:3e5}),n.wpdialog("open"),n.on("wpdialogclose",function(){o.wp.$element&&(o.wp={})}))):window.console&&window.console.error&&window.console.error('wpdialog.js is not loaded. Please set "wpdialogs" as dependency for your script when calling wp_enqueue_script(). You may also want to enqueue the "wp-jquery-ui-dialog" stylesheet.'))},this.close=function(){if(!this.wp.features||!this.wp.features.wpDialog)return this.parent.close.apply(this,arguments);this.wp.$element.wpdialog("close")}},tinymce.PluginManager.add("wpdialogs",function(e){e.on("init",function(){e.windowManager=new tinymce.WPWindowManager(e)})});tinymce/plugins/wpdialogs/plugin.js000064400000004607147573120640013542 0ustar00/* global tinymce */ /** * Included for back-compat. * The default WindowManager in TinyMCE 4.0 supports three types of dialogs: * - With HTML created from JS. * - With inline HTML (like WPWindowManager). * - Old type iframe based dialogs. * For examples see the default plugins: https://github.com/tinymce/tinymce/tree/master/js/tinymce/plugins */ tinymce.WPWindowManager = tinymce.InlineWindowManager = function( editor ) { if ( this.wp ) { return this; } this.wp = {}; this.parent = editor.windowManager; this.editor = editor; tinymce.extend( this, this.parent ); this.open = function( args, params ) { var $element, self = this, wp = this.wp; if ( ! args.wpDialog ) { return this.parent.open.apply( this, arguments ); } else if ( ! args.id ) { return; } if ( typeof jQuery === 'undefined' || ! jQuery.wp || ! jQuery.wp.wpdialog ) { // wpdialog.js is not loaded. if ( window.console && window.console.error ) { window.console.error('wpdialog.js is not loaded. Please set "wpdialogs" as dependency for your script when calling wp_enqueue_script(). You may also want to enqueue the "wp-jquery-ui-dialog" stylesheet.'); } return; } wp.$element = $element = jQuery( '#' + args.id ); if ( ! $element.length ) { return; } if ( window.console && window.console.log ) { window.console.log('tinymce.WPWindowManager is deprecated. Use the default editor.windowManager to open dialogs with inline HTML.'); } wp.features = args; wp.params = params; // Store selection. Takes a snapshot in the FocusManager of the selection before focus is moved to the dialog. editor.nodeChanged(); // Create the dialog if necessary. if ( ! $element.data('wpdialog') ) { $element.wpdialog({ title: args.title, width: args.width, height: args.height, modal: true, dialogClass: 'wp-dialog', zIndex: 300000 }); } $element.wpdialog('open'); $element.on( 'wpdialogclose', function() { if ( self.wp.$element ) { self.wp = {}; } }); }; this.close = function() { if ( ! this.wp.features || ! this.wp.features.wpDialog ) { return this.parent.close.apply( this, arguments ); } this.wp.$element.wpdialog('close'); }; }; tinymce.PluginManager.add( 'wpdialogs', function( editor ) { // Replace window manager. editor.on( 'init', function() { editor.windowManager = new tinymce.WPWindowManager( editor ); }); }); tinymce/plugins/paste/plugin.min.js000064400000074165147573120640013455 0ustar00!function(v){"use strict";var p=function(t){var e=t,n=function(){return e};return{get:n,set:function(t){e=t},clone:function(){return p(n())}}},e=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=function(t){return!(!/(^|[ ,])powerpaste([, ]|$)/.test(t.settings.plugins)||!e.get("powerpaste")||("undefined"!=typeof v.window.console&&v.window.console.log&&v.window.console.log("PowerPaste is incompatible with Paste plugin! Remove 'paste' from the 'plugins' option."),0))},u=function(t,e){return{clipboard:t,quirks:e}},d=function(t,e,n,r){return t.fire("PastePreProcess",{content:e,internal:n,wordContent:r})},m=function(t,e,n,r){return t.fire("PastePostProcess",{node:e,internal:n,wordContent:r})},s=function(t,e){return t.fire("PastePlainTextToggle",{state:e})},n=function(t,e){return t.fire("paste",{ieFake:e})},g={shouldPlainTextInform:function(t){return t.getParam("paste_plaintext_inform",!0)},shouldBlockDrop:function(t){return t.getParam("paste_block_drop",!1)},shouldPasteDataImages:function(t){return t.getParam("paste_data_images",!1)},shouldFilterDrop:function(t){return t.getParam("paste_filter_drop",!0)},getPreProcess:function(t){return t.getParam("paste_preprocess")},getPostProcess:function(t){return t.getParam("paste_postprocess")},getWebkitStyles:function(t){return t.getParam("paste_webkit_styles")},shouldRemoveWebKitStyles:function(t){return t.getParam("paste_remove_styles_if_webkit",!0)},shouldMergeFormats:function(t){return t.getParam("paste_merge_formats",!0)},isSmartPasteEnabled:function(t){return t.getParam("smart_paste",!0)},isPasteAsTextEnabled:function(t){return t.getParam("paste_as_text",!1)},getRetainStyleProps:function(t){return t.getParam("paste_retain_style_properties")},getWordValidElements:function(t){return t.getParam("paste_word_valid_elements","-strong/b,-em/i,-u,-span,-p,-ol,-ul,-li,-h1,-h2,-h3,-h4,-h5,-h6,-p/div,-a[href|name],sub,sup,strike,br,del,table[width],tr,td[colspan|rowspan|width],th[colspan|rowspan|width],thead,tfoot,tbody")},shouldConvertWordFakeLists:function(t){return t.getParam("paste_convert_word_fake_lists",!0)},shouldUseDefaultFilters:function(t){return t.getParam("paste_enable_default_filters",!0)}},r=function(t,e,n){var r,o,i;"text"===e.pasteFormat.get()?(e.pasteFormat.set("html"),s(t,!1)):(e.pasteFormat.set("text"),s(t,!0),i=t,!1===n.get()&&g.shouldPlainTextInform(i)&&(o="Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.",(r=t).notificationManager.open({text:r.translate(o),type:"info"}),n.set(!0))),t.focus()},c=function(t,n,e){t.addCommand("mceTogglePlainTextPaste",function(){r(t,n,e)}),t.addCommand("mceInsertClipboardContent",function(t,e){e.content&&n.pasteHtml(e.content,e.internal),e.text&&n.pasteText(e.text)})},h=tinymce.util.Tools.resolve("tinymce.Env"),y=tinymce.util.Tools.resolve("tinymce.util.Delay"),b=tinymce.util.Tools.resolve("tinymce.util.Tools"),o=tinymce.util.Tools.resolve("tinymce.util.VK"),t="x-tinymce/html",i="\x3c!-- "+t+" --\x3e",l=function(t){return i+t},f=function(t){return t.replace(i,"")},w=function(t){return-1!==t.indexOf(i)},x=function(){return t},_=tinymce.util.Tools.resolve("tinymce.html.Entities"),P=function(t){return t.replace(/\r?\n/g,"
")},T=function(t,e,n){var r=t.split(/\n\n/),o=function(t,e){var n,r=[],o="<"+t;if("object"==typeof e){for(n in e)e.hasOwnProperty(n)&&r.push(n+'="'+_.encodeAllRaw(e[n])+'"');r.length&&(o+=" "+r.join(" "))}return o+">"}(e,n),i="",a=b.map(r,function(t){return t.split(/\n/).join("
")});return 1===a.length?a[0]:b.map(a,function(t){return o+t+i}).join("")},D=function(t){return!/<(?:\/?(?!(?:div|p|br|span)>)\w+|(?:(?!(?:span style="white-space:\s?pre;?">)|br\s?\/>))\w+\s[^>]+)>/i.test(t)},C=function(t,e,n){return e?T(t,e,n):P(t)},k=tinymce.util.Tools.resolve("tinymce.html.DomParser"),F=tinymce.util.Tools.resolve("tinymce.html.Serializer"),E=tinymce.util.Tools.resolve("tinymce.html.Node"),R=tinymce.util.Tools.resolve("tinymce.html.Schema");function I(e,t){return b.each(t,function(t){e=t.constructor===RegExp?e.replace(t,""):e.replace(t[0],t[1])}),e}var O={filter:I,innerText:function(e){var n=R(),r=k({},n),o="",i=n.getShortEndedElements(),a=b.makeMap("script noscript style textarea video audio iframe object"," "),u=n.getBlockElements();return e=I(e,[//g]),function t(e){var n=e.name,r=e;if("br"!==n){if("wbr"!==n)if(i[n]&&(o+=" "),a[n])o+=" ";else{if(3===e.type&&(o+=e.value),!e.shortEnded&&(e=e.firstChild))for(;t(e),e=e.next;);u[n]&&r.next&&(o+="\n","p"===n&&(o+="\n"))}}else o+="\n"}(r.parse(e)),o},trimHtml:function(t){return t=I(t,[/^[\s\S]*]*>\s*|\s*<\/body[^>]*>[\s\S]*$/gi,/|/g,[/( ?)\u00a0<\/span>( ?)/g,function(t,e,n){return e||n?"\xa0":" "}],/
/g,/
$/i])},createIdGenerator:function(t){var e=0;return function(){return t+e++}},isMsEdge:function(){return-1!==v.navigator.userAgent.indexOf(" Edge/")}};function S(e){var n,t;return t=[/^[IVXLMCD]{1,2}\.[ \u00a0]/,/^[ivxlmcd]{1,2}\.[ \u00a0]/,/^[a-z]{1,2}[\.\)][ \u00a0]/,/^[A-Z]{1,2}[\.\)][ \u00a0]/,/^[0-9]+\.[ \u00a0]/,/^[\u3007\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d]+\.[ \u00a0]/,/^[\u58f1\u5f10\u53c2\u56db\u4f0d\u516d\u4e03\u516b\u4e5d\u62fe]+\.[ \u00a0]/],e=e.replace(/^[\u00a0 ]+/,""),b.each(t,function(t){if(t.test(e))return!(n=!0)}),n}function A(t){var i,a,u=1;function n(t){var e="";if(3===t.type)return t.value;if(t=t.firstChild)for(;e+=n(t),t=t.next;);return e}function s(t,e){if(3===t.type&&e.test(t.value))return t.value=t.value.replace(e,""),!1;if(t=t.firstChild)do{if(!s(t,e))return!1}while(t=t.next);return!0}function e(e,n,r){var o=e._listLevel||u;o!==u&&(o/gi,/]+id="?docs-internal-[^>]*>/gi,//gi,/<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi,[/<(\/?)s>/gi,"<$1strike>"],[/ /gi,"\xa0"],[/([\s\u00a0]*)<\/span>/gi,function(t,e){return 0')}),!0);var r,o,i},tt=function(t,e){var n,r;!1===g.isSmartPasteEnabled(t)?X(t,e):(n=t,r=e,b.each([J,Q,X],function(t){return!0!==t(n,r,X)}))},et=function(){},nt=function(t){return function(){return t}},rt=nt(!1),ot=nt(!0),it=function(){return at},at=(M=function(t){return t.isNone()},B={fold:function(t,e){return t()},is:rt,isSome:rt,isNone:ot,getOr:N=function(t){return t},getOrThunk:L=function(t){return t()},getOrDie:function(t){throw new Error(t||"error: getOrDie called on none.")},getOrNull:nt(null),getOrUndefined:nt(undefined),or:N,orThunk:L,map:it,each:et,bind:it,exists:rt,forall:ot,filter:it,equals:M,equals_:M,toArray:function(){return[]},toString:nt("none()")},Object.freeze&&Object.freeze(B),B),ut=function(n){var t=nt(n),e=function(){return o},r=function(t){return t(n)},o={fold:function(t,e){return e(n)},is:function(t){return n===t},isSome:ot,isNone:rt,getOr:t,getOrThunk:t,getOrDie:t,getOrNull:t,getOrUndefined:t,or:e,orThunk:e,map:function(t){return ut(t(n))},each:function(t){t(n)},bind:r,exists:r,forall:r,filter:function(t){return t(n)?o:at},toArray:function(){return[n]},toString:function(){return"some("+n+")"},equals:function(t){return t.is(n)},equals_:function(t,e){return t.fold(rt,function(t){return e(n,t)})}};return o},st={some:ut,none:it,from:function(t){return null===t||t===undefined?at:ut(t)}},ct=(H="function",function(t){return function(t){if(null===t)return"null";var e=typeof t;return"object"===e&&(Array.prototype.isPrototypeOf(t)||t.constructor&&"Array"===t.constructor.name)?"array":"object"===e&&(String.prototype.isPrototypeOf(t)||t.constructor&&"String"===t.constructor.name)?"string":e}(t)===H}),lt=Array.prototype.slice,ft=function(t,e){for(var n=t.length,r=new Array(n),o=0;o=a.length&&r(o)}))})})},Pt=function(t,e){return n=ft(t,e),_t(n,xt);var n},Tt=function(t,e,n){var r=n||w(e),o=G(t,f(e),r);!1===o.cancelled&&tt(t,o.content)},Dt=function(t,e){e=t.dom.encode(e).replace(/\r\n/g,"\n"),e=C(e,t.settings.forced_root_block,t.settings.forced_root_block_attrs),Tt(t,e,!1)},Ct=function(t){var e={};if(t){if(t.getData){var n=t.getData("Text");n&&0',!1)}else Tt(t,'',!1)}(e,t)})}),!0}return!1},It=function(t){return o.metaKeyPressed(t)&&86===t.keyCode||t.shiftKey&&45===t.keyCode},Ot=function(s,c,l){var e,f,d=(e=p(st.none()),{clear:function(){e.set(st.none())},set:function(t){e.set(st.some(t))},isSet:function(){return e.get().isSome()},on:function(t){e.get().each(t)}});function m(t,e,n,r){var o,i;kt(t,"text/html")?o=t["text/html"]:(o=c.getHtml(),r=r||w(o),c.isDefaultContent(o)&&(n=!0)),o=O.trimHtml(o),c.remove(),i=!1===r&&D(o),o.length&&!i||(n=!0),n&&(o=kt(t,"text/plain")&&i?t["text/plain"]:O.innerText(o)),c.isDefaultContent(o)?e||s.windowManager.alert("Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents."):n?Dt(s,o):Tt(s,o,r)}s.on("keydown",function(t){function e(t){It(t)&&!t.isDefaultPrevented()&&c.remove()}if(It(t)&&!t.isDefaultPrevented()){if((f=t.shiftKey&&86===t.keyCode)&&h.webkit&&-1!==v.navigator.userAgent.indexOf("Version/"))return;if(t.stopImmediatePropagation(),d.set(t),window.setTimeout(function(){d.clear()},100),h.ie&&f)return t.preventDefault(),void n(s,!0);c.remove(),c.create(),s.once("keyup",e),s.once("paste",function(){s.off("keyup",e)})}}),s.on("paste",function(t){var e,n,r,o=d.isSet(),i=(e=s,n=Ct(t.clipboardData||e.getDoc().dataTransfer),O.isMsEdge()?b.extend(n,{"text/html":""}):n),a="text"===l.get()||f,u=kt(i,x());f=!1,t.isDefaultPrevented()||(r=t.clipboardData,-1!==v.navigator.userAgent.indexOf("Android")&&r&&r.items&&0===r.items.length)?c.remove():Ft(i)||!Rt(s,t,c.getLastRng()||s.selection.getRng())?(o||t.preventDefault(),!h.ie||o&&!t.ieFake||kt(i,"text/html")||(c.create(),s.dom.bind(c.getEl(),"paste",function(t){t.stopPropagation()}),s.getDoc().execCommand("Paste",!1,null),i["text/html"]=c.getHtml()),kt(i,"text/html")?(t.preventDefault(),u||(u=w(i["text/html"])),m(i,o,a,u)):y.setEditorTimeout(s,function(){m(i,o,a,u)},0)):c.remove()})},St=function(t){return h.ie&&t.inline?v.document.body:t.getBody()},At=function(e,t,n){var r;St(r=e)!==r.getBody()&&e.dom.bind(t,"paste keyup",function(t){Lt(e,n)||e.fire("paste")})},jt=function(t){return t.dom.get("mcepastebin")},Mt=function(t,e){return e===t},Lt=function(t,e){var n,r=jt(t);return(n=r)&&"mcepastebin"===n.id&&Mt(e,r.innerHTML)},Nt=function(a){var u=p(null),s="%MCEPASTEBIN%";return{create:function(){return e=u,n=s,o=(t=a).dom,i=t.getBody(),e.set(t.selection.getRng()),r=t.dom.add(St(t),"div",{id:"mcepastebin","class":"mce-pastebin",contentEditable:!0,"data-mce-bogus":"all",style:"position: fixed; top: 50%; width: 10px; height: 10px; overflow: hidden; opacity: 0"},n),(h.ie||h.gecko)&&o.setStyle(r,"left","rtl"===o.getStyle(i,"direction",!0)?65535:-65535),o.bind(r,"beforedeactivate focusin focusout",function(t){t.stopPropagation()}),At(t,r,n),r.focus(),void t.selection.select(r,!0);var t,e,n,r,o,i},remove:function(){return function(t,e){if(jt(t)){for(var n=void 0,r=e.get();n=t.dom.get("mcepastebin");)t.dom.remove(n),t.dom.unbind(n);r&&t.selection.setRng(r)}e.set(null)}(a,u)},getEl:function(){return jt(a)},getHtml:function(){return function(n){var e,t,r,o,i,a=function(t,e){t.appendChild(e),n.dom.remove(e,!0)};for(t=b.grep(St(n).childNodes,function(t){return"mcepastebin"===t.id}),e=t.shift(),b.each(t,function(t){a(e,t)}),r=(o=n.dom.select("div[id=mcepastebin]",e)).length-1;0<=r;r--)i=n.dom.create("div"),e.insertBefore(i,o[r]),a(i,o[r]);return e?e.innerHTML:""}(a)},getLastRng:function(){return u.get()},isDefault:function(){return Lt(a,s)},isDefaultContent:function(t){return Mt(s,t)}}},Bt=function(n,t){var e=Nt(n);return n.on("preInit",function(){return Ot(a=n,e,t),void a.parser.addNodeFilter("img",function(t,e,n){var r,o=function(t){t.attr("data-mce-object")||u===h.transparentSrc||t.remove()};if(!a.settings.paste_data_images&&(r=n).data&&!0===r.data.paste)for(var i=t.length;i--;)(u=t[i].attributes.map.src)&&(0===u.indexOf("webkit-fake-url")?o(t[i]):a.settings.allow_html_data_urls||0!==u.indexOf("data:")||o(t[i]))});var a,u}),{pasteFormat:t,pasteHtml:function(t,e){return Tt(n,t,e)},pasteText:function(t){return Dt(n,t)},pasteImageData:function(t,e){return Rt(n,t,e)},getDataTransferItems:Ct,hasHtmlOrText:Ft,hasContentType:kt}},Ht=function(){},$t=function(t,e,n){if(r=t,!1!==h.iOS||r===undefined||"function"!=typeof r.setData||!0===O.isMsEdge())return!1;try{return t.clearData(),t.setData("text/html",e),t.setData("text/plain",n),t.setData(x(),e),!0}catch(o){return!1}var r},Wt=function(t,e,n,r){$t(t.clipboardData,e.html,e.text)?(t.preventDefault(),r()):n(e.html,r)},Ut=function(u){return function(t,e){var n=l(t),r=u.dom.create("div",{contenteditable:"false","data-mce-bogus":"all"}),o=u.dom.create("div",{contenteditable:"true"},n);u.dom.setStyles(r,{position:"fixed",top:"0",left:"-3000px",width:"1000px",overflow:"hidden"}),r.appendChild(o),u.dom.add(u.getBody(),r);var i=u.selection.getRng();o.focus();var a=u.dom.createRng();a.selectNodeContents(o),u.selection.setRng(a),setTimeout(function(){u.selection.setRng(i),r.parentNode.removeChild(r),e()},0)}},zt=function(t){return{html:t.selection.getContent({contextual:!0}),text:t.selection.getContent({format:"text"})}},Vt=function(t){return!t.selection.isCollapsed()||!!(e=t).dom.getParent(e.selection.getStart(),"td[data-mce-selected],th[data-mce-selected]",e.getBody());var e},Kt=function(t){var e,n;t.on("cut",(e=t,function(t){Vt(e)&&Wt(t,zt(e),Ut(e),function(){setTimeout(function(){e.execCommand("Delete")},0)})})),t.on("copy",(n=t,function(t){Vt(n)&&Wt(t,zt(n),Ut(n),Ht)}))},qt=tinymce.util.Tools.resolve("tinymce.dom.RangeUtils"),Gt=function(t,e){return qt.getCaretRangeFromPoint(e.clientX,e.clientY,t.getDoc())},Xt=function(t,e){t.focus(),t.selection.setRng(e)},Yt=function(a,u,s){g.shouldBlockDrop(a)&&a.on("dragend dragover draggesture dragdrop drop drag",function(t){t.preventDefault(),t.stopPropagation()}),g.shouldPasteDataImages(a)||a.on("drop",function(t){var e=t.dataTransfer;e&&e.files&&0 [\\s\\r\\n]+|
)*(<\\/?("+n.join("|")+")[^>]*>)(?:
 [\\s\\r\\n]+|
)*","g");return e=O.filter(e,[[r,"$1"]]),e=O.filter(e,[[/

/g,"

"],[/
/g," "],[/

/g,"
"]])}function te(t,e,n,r){if(r||n)return e;var c,o=g.getWebkitStyles(t);if(!1===g.shouldRemoveWebKitStyles(t)||"all"===o)return e;if(o&&(c=o.split(/[, ]/)),c){var l=t.dom,f=t.selection.getNode();e=e.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi,function(t,e,n,r){var o=l.parseStyle(l.decode(n)),i={};if("none"===c)return e+r;for(var a=0;a]+) style="([^"]*)"([^>]*>)/gi,"$1$3");return e=e.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi,function(t,e,n,r){return e+' style="'+n+'"'+r})}function ee(n,t){n.$("a",t).find("font,u").each(function(t,e){n.dom.remove(e,!0)})}var ne=function(t){var e,n;h.webkit&&Jt(t,te),h.ie&&(Jt(t,Qt),n=ee,(e=t).on("PastePostProcess",function(t){n(e,t.node)}))},re=function(t,e,n){var r=n.control;r.active("text"===e.pasteFormat.get()),t.on("PastePlainTextToggle",function(t){r.active(t.state)})},oe=function(t,e){var n=function(r){for(var o=[],t=1;t'; var mark = function (html) { return internalMark + html; }; var unmark = function (html) { return html.replace(internalMark, ''); }; var isMarked = function (html) { return html.indexOf(internalMark) !== -1; }; var InternalHtml = { mark: mark, unmark: unmark, isMarked: isMarked, internalHtmlMime: function () { return internalMimeType; } }; var global$6 = tinymce.util.Tools.resolve('tinymce.html.Entities'); var isPlainText = function (text) { return !/<(?:\/?(?!(?:div|p|br|span)>)\w+|(?:(?!(?:span style="white-space:\s?pre;?">)|br\s?\/>))\w+\s[^>]+)>/i.test(text); }; var toBRs = function (text) { return text.replace(/\r?\n/g, '
'); }; var openContainer = function (rootTag, rootAttrs) { var key; var attrs = []; var tag = '<' + rootTag; if (typeof rootAttrs === 'object') { for (key in rootAttrs) { if (rootAttrs.hasOwnProperty(key)) { attrs.push(key + '="' + global$6.encodeAllRaw(rootAttrs[key]) + '"'); } } if (attrs.length) { tag += ' ' + attrs.join(' '); } } return tag + '>'; }; var toBlockElements = function (text, rootTag, rootAttrs) { var blocks = text.split(/\n\n/); var tagOpen = openContainer(rootTag, rootAttrs); var tagClose = ''; var paragraphs = global$4.map(blocks, function (p) { return p.split(/\n/).join('
'); }); var stitch = function (p) { return tagOpen + p + tagClose; }; return paragraphs.length === 1 ? paragraphs[0] : global$4.map(paragraphs, stitch).join(''); }; var convert = function (text, rootTag, rootAttrs) { return rootTag ? toBlockElements(text, rootTag, rootAttrs) : toBRs(text); }; var Newlines = { isPlainText: isPlainText, convert: convert, toBRs: toBRs, toBlockElements: toBlockElements }; var global$7 = tinymce.util.Tools.resolve('tinymce.html.DomParser'); var global$8 = tinymce.util.Tools.resolve('tinymce.html.Serializer'); var global$9 = tinymce.util.Tools.resolve('tinymce.html.Node'); var global$a = tinymce.util.Tools.resolve('tinymce.html.Schema'); function filter(content, items) { global$4.each(items, function (v) { if (v.constructor === RegExp) { content = content.replace(v, ''); } else { content = content.replace(v[0], v[1]); } }); return content; } function innerText(html) { var schema = global$a(); var domParser = global$7({}, schema); var text = ''; var shortEndedElements = schema.getShortEndedElements(); var ignoreElements = global$4.makeMap('script noscript style textarea video audio iframe object', ' '); var blockElements = schema.getBlockElements(); function walk(node) { var name = node.name, currentNode = node; if (name === 'br') { text += '\n'; return; } if (name === 'wbr') { return; } if (shortEndedElements[name]) { text += ' '; } if (ignoreElements[name]) { text += ' '; return; } if (node.type === 3) { text += node.value; } if (!node.shortEnded) { if (node = node.firstChild) { do { walk(node); } while (node = node.next); } } if (blockElements[name] && currentNode.next) { text += '\n'; if (name === 'p') { text += '\n'; } } } html = filter(html, [//g]); walk(domParser.parse(html)); return text; } function trimHtml(html) { function trimSpaces(all, s1, s2) { if (!s1 && !s2) { return ' '; } return '\xA0'; } html = filter(html, [ /^[\s\S]*]*>\s*|\s*<\/body[^>]*>[\s\S]*$/ig, /|/g, [ /( ?)\u00a0<\/span>( ?)/g, trimSpaces ], /
/g, /
$/i ]); return html; } function createIdGenerator(prefix) { var count = 0; return function () { return prefix + count++; }; } var isMsEdge = function () { return domGlobals.navigator.userAgent.indexOf(' Edge/') !== -1; }; var Utils = { filter: filter, innerText: innerText, trimHtml: trimHtml, createIdGenerator: createIdGenerator, isMsEdge: isMsEdge }; function isWordContent(content) { return / 1) { currentListNode.attr('start', '' + start); } paragraphNode.wrap(currentListNode); } else { currentListNode.append(paragraphNode); } paragraphNode.name = 'li'; if (level > lastLevel && prevListNode) { prevListNode.lastChild.append(currentListNode); } lastLevel = level; removeIgnoredNodes(paragraphNode); trimListStart(paragraphNode, /^\u00a0+/); trimListStart(paragraphNode, /^\s*([\u2022\u00b7\u00a7\u25CF]|\w+\.)/); trimListStart(paragraphNode, /^\u00a0+/); } var elements = []; var child = node.firstChild; while (typeof child !== 'undefined' && child !== null) { elements.push(child); child = child.walk(); if (child !== null) { while (typeof child !== 'undefined' && child.parent !== node) { child = child.walk(); } } } for (var i = 0; i < elements.length; i++) { node = elements[i]; if (node.name === 'p' && node.firstChild) { var nodeText = getText(node); if (isBulletList(nodeText)) { convertParagraphToLi(node, 'ul'); continue; } if (isNumericList(nodeText)) { var matches = /([0-9]+)\./.exec(nodeText); var start = 1; if (matches) { start = parseInt(matches[1], 10); } convertParagraphToLi(node, 'ol', start); continue; } if (node._listLevel) { convertParagraphToLi(node, 'ul', 1); continue; } currentListNode = null; } else { prevListNode = currentListNode; currentListNode = null; } } } function filterStyles(editor, validStyles, node, styleValue) { var outputStyles = {}, matches; var styles = editor.dom.parseStyle(styleValue); global$4.each(styles, function (value, name) { switch (name) { case 'mso-list': matches = /\w+ \w+([0-9]+)/i.exec(styleValue); if (matches) { node._listLevel = parseInt(matches[1], 10); } if (/Ignore/i.test(value) && node.firstChild) { node._listIgnore = true; node.firstChild._listIgnore = true; } break; case 'horiz-align': name = 'text-align'; break; case 'vert-align': name = 'vertical-align'; break; case 'font-color': case 'mso-foreground': name = 'color'; break; case 'mso-background': case 'mso-highlight': name = 'background'; break; case 'font-weight': case 'font-style': if (value !== 'normal') { outputStyles[name] = value; } return; case 'mso-element': if (/^(comment|comment-list)$/i.test(value)) { node.remove(); return; } break; } if (name.indexOf('mso-comment') === 0) { node.remove(); return; } if (name.indexOf('mso-') === 0) { return; } if (Settings.getRetainStyleProps(editor) === 'all' || validStyles && validStyles[name]) { outputStyles[name] = value; } }); if (/(bold)/i.test(outputStyles['font-weight'])) { delete outputStyles['font-weight']; node.wrap(new global$9('b', 1)); } if (/(italic)/i.test(outputStyles['font-style'])) { delete outputStyles['font-style']; node.wrap(new global$9('i', 1)); } outputStyles = editor.dom.serializeStyle(outputStyles, node.name); if (outputStyles) { return outputStyles; } return null; } var filterWordContent = function (editor, content) { var retainStyleProperties, validStyles; retainStyleProperties = Settings.getRetainStyleProps(editor); if (retainStyleProperties) { validStyles = global$4.makeMap(retainStyleProperties.split(/[, ]/)); } content = Utils.filter(content, [ /
/gi, /]+id="?docs-internal-[^>]*>/gi, //gi, /<(!|script[^>]*>.*?<\/script(?=[>\s])|\/?(\?xml(:\w+)?|img|meta|link|style|\w:\w+)(?=[\s\/>]))[^>]*>/gi, [ /<(\/?)s>/gi, '<$1strike>' ], [ / /gi, '\xA0' ], [ /([\s\u00a0]*)<\/span>/gi, function (str, spaces) { return spaces.length > 0 ? spaces.replace(/./, ' ').slice(Math.floor(spaces.length / 2)).split('').join('\xA0') : ''; } ] ]); var validElements = Settings.getWordValidElements(editor); var schema = global$a({ valid_elements: validElements, valid_children: '-li[p]' }); global$4.each(schema.elements, function (rule) { if (!rule.attributes.class) { rule.attributes.class = {}; rule.attributesOrder.push('class'); } if (!rule.attributes.style) { rule.attributes.style = {}; rule.attributesOrder.push('style'); } }); var domParser = global$7({}, schema); domParser.addAttributeFilter('style', function (nodes) { var i = nodes.length, node; while (i--) { node = nodes[i]; node.attr('style', filterStyles(editor, validStyles, node, node.attr('style'))); if (node.name === 'span' && node.parent && !node.attributes.length) { node.unwrap(); } } }); domParser.addAttributeFilter('class', function (nodes) { var i = nodes.length, node, className; while (i--) { node = nodes[i]; className = node.attr('class'); if (/^(MsoCommentReference|MsoCommentText|msoDel)$/i.test(className)) { node.remove(); } node.attr('class', null); } }); domParser.addNodeFilter('del', function (nodes) { var i = nodes.length; while (i--) { nodes[i].remove(); } }); domParser.addNodeFilter('a', function (nodes) { var i = nodes.length, node, href, name; while (i--) { node = nodes[i]; href = node.attr('href'); name = node.attr('name'); if (href && href.indexOf('#_msocom_') !== -1) { node.remove(); continue; } if (href && href.indexOf('file://') === 0) { href = href.split('#')[1]; if (href) { href = '#' + href; } } if (!href && !name) { node.unwrap(); } else { if (name && !/^_?(?:toc|edn|ftn)/i.test(name)) { node.unwrap(); continue; } node.attr({ href: href, name: name }); } } }); var rootNode = domParser.parse(content); if (Settings.shouldConvertWordFakeLists(editor)) { convertFakeListsToProperLists(rootNode); } content = global$8({ validate: editor.settings.validate }, schema).serialize(rootNode); return content; }; var preProcess = function (editor, content) { return Settings.shouldUseDefaultFilters(editor) ? filterWordContent(editor, content) : content; }; var WordFilter = { preProcess: preProcess, isWordContent: isWordContent }; var preProcess$1 = function (editor, html) { var parser = global$7({}, editor.schema); parser.addNodeFilter('meta', function (nodes) { global$4.each(nodes, function (node) { return node.remove(); }); }); var fragment = parser.parse(html, { forced_root_block: false, isRootContent: true }); return global$8({ validate: editor.settings.validate }, editor.schema).serialize(fragment); }; var processResult = function (content, cancelled) { return { content: content, cancelled: cancelled }; }; var postProcessFilter = function (editor, html, internal, isWordHtml) { var tempBody = editor.dom.create('div', { style: 'display:none' }, html); var postProcessArgs = Events.firePastePostProcess(editor, tempBody, internal, isWordHtml); return processResult(postProcessArgs.node.innerHTML, postProcessArgs.isDefaultPrevented()); }; var filterContent = function (editor, content, internal, isWordHtml) { var preProcessArgs = Events.firePastePreProcess(editor, content, internal, isWordHtml); var filteredContent = preProcess$1(editor, preProcessArgs.content); if (editor.hasEventListeners('PastePostProcess') && !preProcessArgs.isDefaultPrevented()) { return postProcessFilter(editor, filteredContent, internal, isWordHtml); } else { return processResult(filteredContent, preProcessArgs.isDefaultPrevented()); } }; var process = function (editor, html, internal) { var isWordHtml = WordFilter.isWordContent(html); var content = isWordHtml ? WordFilter.preProcess(editor, html) : html; return filterContent(editor, content, internal, isWordHtml); }; var ProcessFilters = { process: process }; var pasteHtml = function (editor, html) { editor.insertContent(html, { merge: Settings.shouldMergeFormats(editor), paste: true }); return true; }; var isAbsoluteUrl = function (url) { return /^https?:\/\/[\w\?\-\/+=.&%@~#]+$/i.test(url); }; var isImageUrl = function (url) { return isAbsoluteUrl(url) && /.(gif|jpe?g|png)$/.test(url); }; var createImage = function (editor, url, pasteHtmlFn) { editor.undoManager.extra(function () { pasteHtmlFn(editor, url); }, function () { editor.insertContent(''); }); return true; }; var createLink = function (editor, url, pasteHtmlFn) { editor.undoManager.extra(function () { pasteHtmlFn(editor, url); }, function () { editor.execCommand('mceInsertLink', false, url); }); return true; }; var linkSelection = function (editor, html, pasteHtmlFn) { return editor.selection.isCollapsed() === false && isAbsoluteUrl(html) ? createLink(editor, html, pasteHtmlFn) : false; }; var insertImage = function (editor, html, pasteHtmlFn) { return isImageUrl(html) ? createImage(editor, html, pasteHtmlFn) : false; }; var smartInsertContent = function (editor, html) { global$4.each([ linkSelection, insertImage, pasteHtml ], function (action) { return action(editor, html, pasteHtml) !== true; }); }; var insertContent = function (editor, html) { if (Settings.isSmartPasteEnabled(editor) === false) { pasteHtml(editor, html); } else { smartInsertContent(editor, html); } }; var SmartPaste = { isImageUrl: isImageUrl, isAbsoluteUrl: isAbsoluteUrl, insertContent: insertContent }; var noop = function () { }; var constant = function (value) { return function () { return value; }; }; function curry(fn) { var initialArgs = []; for (var _i = 1; _i < arguments.length; _i++) { initialArgs[_i - 1] = arguments[_i]; } return function () { var restArgs = []; for (var _i = 0; _i < arguments.length; _i++) { restArgs[_i] = arguments[_i]; } var all = initialArgs.concat(restArgs); return fn.apply(null, all); }; } var never = constant(false); var always = constant(true); var none = function () { return NONE; }; var NONE = function () { var eq = function (o) { return o.isNone(); }; var call = function (thunk) { return thunk(); }; var id = function (n) { return n; }; var me = { fold: function (n, s) { return n(); }, is: never, isSome: never, isNone: always, getOr: id, getOrThunk: call, getOrDie: function (msg) { throw new Error(msg || 'error: getOrDie called on none.'); }, getOrNull: constant(null), getOrUndefined: constant(undefined), or: id, orThunk: call, map: none, each: noop, bind: none, exists: never, forall: always, filter: none, equals: eq, equals_: eq, toArray: function () { return []; }, toString: constant('none()') }; if (Object.freeze) { Object.freeze(me); } return me; }(); var some = function (a) { var constant_a = constant(a); var self = function () { return me; }; var bind = function (f) { return f(a); }; var me = { fold: function (n, s) { return s(a); }, is: function (v) { return a === v; }, isSome: always, isNone: never, getOr: constant_a, getOrThunk: constant_a, getOrDie: constant_a, getOrNull: constant_a, getOrUndefined: constant_a, or: self, orThunk: self, map: function (f) { return some(f(a)); }, each: function (f) { f(a); }, bind: bind, exists: bind, forall: bind, filter: function (f) { return f(a) ? me : NONE; }, toArray: function () { return [a]; }, toString: function () { return 'some(' + a + ')'; }, equals: function (o) { return o.is(a); }, equals_: function (o, elementEq) { return o.fold(never, function (b) { return elementEq(a, b); }); } }; return me; }; var from = function (value) { return value === null || value === undefined ? NONE : some(value); }; var Option = { some: some, none: none, from: from }; var typeOf = function (x) { if (x === null) { return 'null'; } var t = typeof x; if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) { return 'array'; } if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) { return 'string'; } return t; }; var isType = function (type) { return function (value) { return typeOf(value) === type; }; }; var isFunction = isType('function'); var nativeSlice = Array.prototype.slice; var map = function (xs, f) { var len = xs.length; var r = new Array(len); for (var i = 0; i < len; i++) { var x = xs[i]; r[i] = f(x, i); } return r; }; var each = function (xs, f) { for (var i = 0, len = xs.length; i < len; i++) { var x = xs[i]; f(x, i); } }; var filter$1 = function (xs, pred) { var r = []; for (var i = 0, len = xs.length; i < len; i++) { var x = xs[i]; if (pred(x, i)) { r.push(x); } } return r; }; var from$1 = isFunction(Array.from) ? Array.from : function (x) { return nativeSlice.call(x); }; var exports$1 = {}, module = { exports: exports$1 }; (function (define, exports, module, require) { (function (f) { if (typeof exports === 'object' && typeof module !== 'undefined') { module.exports = f(); } else if (typeof define === 'function' && define.amd) { define([], f); } else { var g; if (typeof window !== 'undefined') { g = window; } else if (typeof global !== 'undefined') { g = global; } else if (typeof self !== 'undefined') { g = self; } else { g = this; } g.EphoxContactWrapper = f(); } }(function () { return function () { function r(e, n, t) { function o(i, f) { if (!n[i]) { if (!e[i]) { var c = 'function' == typeof require && require; if (!f && c) return c(i, !0); if (u) return u(i, !0); var a = new Error('Cannot find module \'' + i + '\''); throw a.code = 'MODULE_NOT_FOUND', a; } var p = n[i] = { exports: {} }; e[i][0].call(p.exports, function (r) { var n = e[i][1][r]; return o(n || r); }, p, p.exports, r, e, n, t); } return n[i].exports; } for (var u = 'function' == typeof require && require, i = 0; i < t.length; i++) o(t[i]); return o; } return r; }()({ 1: [ function (require, module, exports) { var process = module.exports = {}; var cachedSetTimeout; var cachedClearTimeout; function defaultSetTimout() { throw new Error('setTimeout has not been defined'); } function defaultClearTimeout() { throw new Error('clearTimeout has not been defined'); } (function () { try { if (typeof setTimeout === 'function') { cachedSetTimeout = setTimeout; } else { cachedSetTimeout = defaultSetTimout; } } catch (e) { cachedSetTimeout = defaultSetTimout; } try { if (typeof clearTimeout === 'function') { cachedClearTimeout = clearTimeout; } else { cachedClearTimeout = defaultClearTimeout; } } catch (e) { cachedClearTimeout = defaultClearTimeout; } }()); function runTimeout(fun) { if (cachedSetTimeout === setTimeout) { return setTimeout(fun, 0); } if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { cachedSetTimeout = setTimeout; return setTimeout(fun, 0); } try { return cachedSetTimeout(fun, 0); } catch (e) { try { return cachedSetTimeout.call(null, fun, 0); } catch (e) { return cachedSetTimeout.call(this, fun, 0); } } } function runClearTimeout(marker) { if (cachedClearTimeout === clearTimeout) { return clearTimeout(marker); } if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { cachedClearTimeout = clearTimeout; return clearTimeout(marker); } try { return cachedClearTimeout(marker); } catch (e) { try { return cachedClearTimeout.call(null, marker); } catch (e) { return cachedClearTimeout.call(this, marker); } } } var queue = []; var draining = false; var currentQueue; var queueIndex = -1; function cleanUpNextTick() { if (!draining || !currentQueue) { return; } draining = false; if (currentQueue.length) { queue = currentQueue.concat(queue); } else { queueIndex = -1; } if (queue.length) { drainQueue(); } } function drainQueue() { if (draining) { return; } var timeout = runTimeout(cleanUpNextTick); draining = true; var len = queue.length; while (len) { currentQueue = queue; queue = []; while (++queueIndex < len) { if (currentQueue) { currentQueue[queueIndex].run(); } } queueIndex = -1; len = queue.length; } currentQueue = null; draining = false; runClearTimeout(timeout); } process.nextTick = function (fun) { var args = new Array(arguments.length - 1); if (arguments.length > 1) { for (var i = 1; i < arguments.length; i++) { args[i - 1] = arguments[i]; } } queue.push(new Item(fun, args)); if (queue.length === 1 && !draining) { runTimeout(drainQueue); } }; function Item(fun, array) { this.fun = fun; this.array = array; } Item.prototype.run = function () { this.fun.apply(null, this.array); }; process.title = 'browser'; process.browser = true; process.env = {}; process.argv = []; process.version = ''; process.versions = {}; function noop() { } process.on = noop; process.addListener = noop; process.once = noop; process.off = noop; process.removeListener = noop; process.removeAllListeners = noop; process.emit = noop; process.prependListener = noop; process.prependOnceListener = noop; process.listeners = function (name) { return []; }; process.binding = function (name) { throw new Error('process.binding is not supported'); }; process.cwd = function () { return '/'; }; process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; process.umask = function () { return 0; }; }, {} ], 2: [ function (require, module, exports) { (function (setImmediate) { (function (root) { var setTimeoutFunc = setTimeout; function noop() { } function bind(fn, thisArg) { return function () { fn.apply(thisArg, arguments); }; } function Promise(fn) { if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new'); if (typeof fn !== 'function') throw new TypeError('not a function'); this._state = 0; this._handled = false; this._value = undefined; this._deferreds = []; doResolve(fn, this); } function handle(self, deferred) { while (self._state === 3) { self = self._value; } if (self._state === 0) { self._deferreds.push(deferred); return; } self._handled = true; Promise._immediateFn(function () { var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; if (cb === null) { (self._state === 1 ? resolve : reject)(deferred.promise, self._value); return; } var ret; try { ret = cb(self._value); } catch (e) { reject(deferred.promise, e); return; } resolve(deferred.promise, ret); }); } function resolve(self, newValue) { try { if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.'); if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) { var then = newValue.then; if (newValue instanceof Promise) { self._state = 3; self._value = newValue; finale(self); return; } else if (typeof then === 'function') { doResolve(bind(then, newValue), self); return; } } self._state = 1; self._value = newValue; finale(self); } catch (e) { reject(self, e); } } function reject(self, newValue) { self._state = 2; self._value = newValue; finale(self); } function finale(self) { if (self._state === 2 && self._deferreds.length === 0) { Promise._immediateFn(function () { if (!self._handled) { Promise._unhandledRejectionFn(self._value); } }); } for (var i = 0, len = self._deferreds.length; i < len; i++) { handle(self, self._deferreds[i]); } self._deferreds = null; } function Handler(onFulfilled, onRejected, promise) { this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; this.onRejected = typeof onRejected === 'function' ? onRejected : null; this.promise = promise; } function doResolve(fn, self) { var done = false; try { fn(function (value) { if (done) return; done = true; resolve(self, value); }, function (reason) { if (done) return; done = true; reject(self, reason); }); } catch (ex) { if (done) return; done = true; reject(self, ex); } } Promise.prototype['catch'] = function (onRejected) { return this.then(null, onRejected); }; Promise.prototype.then = function (onFulfilled, onRejected) { var prom = new this.constructor(noop); handle(this, new Handler(onFulfilled, onRejected, prom)); return prom; }; Promise.all = function (arr) { var args = Array.prototype.slice.call(arr); return new Promise(function (resolve, reject) { if (args.length === 0) return resolve([]); var remaining = args.length; function res(i, val) { try { if (val && (typeof val === 'object' || typeof val === 'function')) { var then = val.then; if (typeof then === 'function') { then.call(val, function (val) { res(i, val); }, reject); return; } } args[i] = val; if (--remaining === 0) { resolve(args); } } catch (ex) { reject(ex); } } for (var i = 0; i < args.length; i++) { res(i, args[i]); } }); }; Promise.resolve = function (value) { if (value && typeof value === 'object' && value.constructor === Promise) { return value; } return new Promise(function (resolve) { resolve(value); }); }; Promise.reject = function (value) { return new Promise(function (resolve, reject) { reject(value); }); }; Promise.race = function (values) { return new Promise(function (resolve, reject) { for (var i = 0, len = values.length; i < len; i++) { values[i].then(resolve, reject); } }); }; Promise._immediateFn = typeof setImmediate === 'function' ? function (fn) { setImmediate(fn); } : function (fn) { setTimeoutFunc(fn, 0); }; Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) { if (typeof console !== 'undefined' && console) { console.warn('Possible Unhandled Promise Rejection:', err); } }; Promise._setImmediateFn = function _setImmediateFn(fn) { Promise._immediateFn = fn; }; Promise._setUnhandledRejectionFn = function _setUnhandledRejectionFn(fn) { Promise._unhandledRejectionFn = fn; }; if (typeof module !== 'undefined' && module.exports) { module.exports = Promise; } else if (!root.Promise) { root.Promise = Promise; } }(this)); }.call(this, require('timers').setImmediate)); }, { 'timers': 3 } ], 3: [ function (require, module, exports) { (function (setImmediate, clearImmediate) { var nextTick = require('process/browser.js').nextTick; var apply = Function.prototype.apply; var slice = Array.prototype.slice; var immediateIds = {}; var nextImmediateId = 0; exports.setTimeout = function () { return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout); }; exports.setInterval = function () { return new Timeout(apply.call(setInterval, window, arguments), clearInterval); }; exports.clearTimeout = exports.clearInterval = function (timeout) { timeout.close(); }; function Timeout(id, clearFn) { this._id = id; this._clearFn = clearFn; } Timeout.prototype.unref = Timeout.prototype.ref = function () { }; Timeout.prototype.close = function () { this._clearFn.call(window, this._id); }; exports.enroll = function (item, msecs) { clearTimeout(item._idleTimeoutId); item._idleTimeout = msecs; }; exports.unenroll = function (item) { clearTimeout(item._idleTimeoutId); item._idleTimeout = -1; }; exports._unrefActive = exports.active = function (item) { clearTimeout(item._idleTimeoutId); var msecs = item._idleTimeout; if (msecs >= 0) { item._idleTimeoutId = setTimeout(function onTimeout() { if (item._onTimeout) item._onTimeout(); }, msecs); } }; exports.setImmediate = typeof setImmediate === 'function' ? setImmediate : function (fn) { var id = nextImmediateId++; var args = arguments.length < 2 ? false : slice.call(arguments, 1); immediateIds[id] = true; nextTick(function onNextTick() { if (immediateIds[id]) { if (args) { fn.apply(null, args); } else { fn.call(null); } exports.clearImmediate(id); } }); return id; }; exports.clearImmediate = typeof clearImmediate === 'function' ? clearImmediate : function (id) { delete immediateIds[id]; }; }.call(this, require('timers').setImmediate, require('timers').clearImmediate)); }, { 'process/browser.js': 1, 'timers': 3 } ], 4: [ function (require, module, exports) { var promisePolyfill = require('promise-polyfill'); var Global = function () { if (typeof window !== 'undefined') { return window; } else { return Function('return this;')(); } }(); module.exports = { boltExport: Global.Promise || promisePolyfill }; }, { 'promise-polyfill': 2 } ] }, {}, [4])(4); })); }(undefined, exports$1, module, undefined)); var Promise = module.exports.boltExport; var nu = function (baseFn) { var data = Option.none(); var callbacks = []; var map = function (f) { return nu(function (nCallback) { get(function (data) { nCallback(f(data)); }); }); }; var get = function (nCallback) { if (isReady()) { call(nCallback); } else { callbacks.push(nCallback); } }; var set = function (x) { data = Option.some(x); run(callbacks); callbacks = []; }; var isReady = function () { return data.isSome(); }; var run = function (cbs) { each(cbs, call); }; var call = function (cb) { data.each(function (x) { domGlobals.setTimeout(function () { cb(x); }, 0); }); }; baseFn(set); return { get: get, map: map, isReady: isReady }; }; var pure = function (a) { return nu(function (callback) { callback(a); }); }; var LazyValue = { nu: nu, pure: pure }; var errorReporter = function (err) { domGlobals.setTimeout(function () { throw err; }, 0); }; var make = function (run) { var get = function (callback) { run().then(callback, errorReporter); }; var map = function (fab) { return make(function () { return run().then(fab); }); }; var bind = function (aFutureB) { return make(function () { return run().then(function (v) { return aFutureB(v).toPromise(); }); }); }; var anonBind = function (futureB) { return make(function () { return run().then(function () { return futureB.toPromise(); }); }); }; var toLazy = function () { return LazyValue.nu(get); }; var toCached = function () { var cache = null; return make(function () { if (cache === null) { cache = run(); } return cache; }); }; var toPromise = run; return { map: map, bind: bind, anonBind: anonBind, toLazy: toLazy, toCached: toCached, toPromise: toPromise, get: get }; }; var nu$1 = function (baseFn) { return make(function () { return new Promise(baseFn); }); }; var pure$1 = function (a) { return make(function () { return Promise.resolve(a); }); }; var Future = { nu: nu$1, pure: pure$1 }; var par = function (asyncValues, nu) { return nu(function (callback) { var r = []; var count = 0; var cb = function (i) { return function (value) { r[i] = value; count++; if (count >= asyncValues.length) { callback(r); } }; }; if (asyncValues.length === 0) { callback([]); } else { each(asyncValues, function (asyncValue, i) { asyncValue.get(cb(i)); }); } }); }; var par$1 = function (futures) { return par(futures, Future.nu); }; var traverse = function (array, fn) { return par$1(map(array, fn)); }; var mapM = traverse; var value = function () { var subject = Cell(Option.none()); var clear = function () { subject.set(Option.none()); }; var set = function (s) { subject.set(Option.some(s)); }; var on = function (f) { subject.get().each(f); }; var isSet = function () { return subject.get().isSome(); }; return { clear: clear, set: set, isSet: isSet, on: on }; }; var pasteHtml$1 = function (editor, html, internalFlag) { var internal = internalFlag ? internalFlag : InternalHtml.isMarked(html); var args = ProcessFilters.process(editor, InternalHtml.unmark(html), internal); if (args.cancelled === false) { SmartPaste.insertContent(editor, args.content); } }; var pasteText = function (editor, text) { text = editor.dom.encode(text).replace(/\r\n/g, '\n'); text = Newlines.convert(text, editor.settings.forced_root_block, editor.settings.forced_root_block_attrs); pasteHtml$1(editor, text, false); }; var getDataTransferItems = function (dataTransfer) { var items = {}; var mceInternalUrlPrefix = 'data:text/mce-internal,'; if (dataTransfer) { if (dataTransfer.getData) { var legacyText = dataTransfer.getData('Text'); if (legacyText && legacyText.length > 0) { if (legacyText.indexOf(mceInternalUrlPrefix) === -1) { items['text/plain'] = legacyText; } } } if (dataTransfer.types) { for (var i = 0; i < dataTransfer.types.length; i++) { var contentType = dataTransfer.types[i]; try { items[contentType] = dataTransfer.getData(contentType); } catch (ex) { items[contentType] = ''; } } } } return items; }; var getClipboardContent = function (editor, clipboardEvent) { var content = getDataTransferItems(clipboardEvent.clipboardData || editor.getDoc().dataTransfer); return Utils.isMsEdge() ? global$4.extend(content, { 'text/html': '' }) : content; }; var hasContentType = function (clipboardContent, mimeType) { return mimeType in clipboardContent && clipboardContent[mimeType].length > 0; }; var hasHtmlOrText = function (content) { return hasContentType(content, 'text/html') || hasContentType(content, 'text/plain'); }; var getBase64FromUri = function (uri) { var idx; idx = uri.indexOf(','); if (idx !== -1) { return uri.substr(idx + 1); } return null; }; var isValidDataUriImage = function (settings, imgElm) { return settings.images_dataimg_filter ? settings.images_dataimg_filter(imgElm) : true; }; var extractFilename = function (editor, str) { var m = str.match(/([\s\S]+?)\.(?:jpeg|jpg|png|gif)$/i); return m ? editor.dom.encode(m[1]) : null; }; var uniqueId = Utils.createIdGenerator('mceclip'); var pasteImage = function (editor, imageItem) { var base64 = getBase64FromUri(imageItem.uri); var id = uniqueId(); var name = editor.settings.images_reuse_filename && imageItem.blob.name ? extractFilename(editor, imageItem.blob.name) : id; var img = new domGlobals.Image(); img.src = imageItem.uri; if (isValidDataUriImage(editor.settings, img)) { var blobCache = editor.editorUpload.blobCache; var blobInfo = void 0, existingBlobInfo = void 0; existingBlobInfo = blobCache.findFirst(function (cachedBlobInfo) { return cachedBlobInfo.base64() === base64; }); if (!existingBlobInfo) { blobInfo = blobCache.create(id, imageItem.blob, base64, name); blobCache.add(blobInfo); } else { blobInfo = existingBlobInfo; } pasteHtml$1(editor, '', false); } else { pasteHtml$1(editor, '', false); } }; var isClipboardEvent = function (event) { return event.type === 'paste'; }; var readBlobsAsDataUris = function (items) { return mapM(items, function (item) { return Future.nu(function (resolve) { var blob = item.getAsFile ? item.getAsFile() : item; var reader = new window.FileReader(); reader.onload = function () { resolve({ blob: blob, uri: reader.result }); }; reader.readAsDataURL(blob); }); }); }; var getImagesFromDataTransfer = function (dataTransfer) { var items = dataTransfer.items ? map(from$1(dataTransfer.items), function (item) { return item.getAsFile(); }) : []; var files = dataTransfer.files ? from$1(dataTransfer.files) : []; var images = filter$1(items.length > 0 ? items : files, function (file) { return /^image\/(jpeg|png|gif|bmp)$/.test(file.type); }); return images; }; var pasteImageData = function (editor, e, rng) { var dataTransfer = isClipboardEvent(e) ? e.clipboardData : e.dataTransfer; if (editor.settings.paste_data_images && dataTransfer) { var images = getImagesFromDataTransfer(dataTransfer); if (images.length > 0) { e.preventDefault(); readBlobsAsDataUris(images).get(function (blobResults) { if (rng) { editor.selection.setRng(rng); } each(blobResults, function (result) { pasteImage(editor, result); }); }); return true; } } return false; }; var isBrokenAndroidClipboardEvent = function (e) { var clipboardData = e.clipboardData; return domGlobals.navigator.userAgent.indexOf('Android') !== -1 && clipboardData && clipboardData.items && clipboardData.items.length === 0; }; var isKeyboardPasteEvent = function (e) { return global$5.metaKeyPressed(e) && e.keyCode === 86 || e.shiftKey && e.keyCode === 45; }; var registerEventHandlers = function (editor, pasteBin, pasteFormat) { var keyboardPasteEvent = value(); var keyboardPastePlainTextState; editor.on('keydown', function (e) { function removePasteBinOnKeyUp(e) { if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) { pasteBin.remove(); } } if (isKeyboardPasteEvent(e) && !e.isDefaultPrevented()) { keyboardPastePlainTextState = e.shiftKey && e.keyCode === 86; if (keyboardPastePlainTextState && global$2.webkit && domGlobals.navigator.userAgent.indexOf('Version/') !== -1) { return; } e.stopImmediatePropagation(); keyboardPasteEvent.set(e); window.setTimeout(function () { keyboardPasteEvent.clear(); }, 100); if (global$2.ie && keyboardPastePlainTextState) { e.preventDefault(); Events.firePaste(editor, true); return; } pasteBin.remove(); pasteBin.create(); editor.once('keyup', removePasteBinOnKeyUp); editor.once('paste', function () { editor.off('keyup', removePasteBinOnKeyUp); }); } }); function insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal) { var content, isPlainTextHtml; if (hasContentType(clipboardContent, 'text/html')) { content = clipboardContent['text/html']; } else { content = pasteBin.getHtml(); internal = internal ? internal : InternalHtml.isMarked(content); if (pasteBin.isDefaultContent(content)) { plainTextMode = true; } } content = Utils.trimHtml(content); pasteBin.remove(); isPlainTextHtml = internal === false && Newlines.isPlainText(content); if (!content.length || isPlainTextHtml) { plainTextMode = true; } if (plainTextMode) { if (hasContentType(clipboardContent, 'text/plain') && isPlainTextHtml) { content = clipboardContent['text/plain']; } else { content = Utils.innerText(content); } } if (pasteBin.isDefaultContent(content)) { if (!isKeyBoardPaste) { editor.windowManager.alert('Please use Ctrl+V/Cmd+V keyboard shortcuts to paste contents.'); } return; } if (plainTextMode) { pasteText(editor, content); } else { pasteHtml$1(editor, content, internal); } } var getLastRng = function () { return pasteBin.getLastRng() || editor.selection.getRng(); }; editor.on('paste', function (e) { var isKeyBoardPaste = keyboardPasteEvent.isSet(); var clipboardContent = getClipboardContent(editor, e); var plainTextMode = pasteFormat.get() === 'text' || keyboardPastePlainTextState; var internal = hasContentType(clipboardContent, InternalHtml.internalHtmlMime()); keyboardPastePlainTextState = false; if (e.isDefaultPrevented() || isBrokenAndroidClipboardEvent(e)) { pasteBin.remove(); return; } if (!hasHtmlOrText(clipboardContent) && pasteImageData(editor, e, getLastRng())) { pasteBin.remove(); return; } if (!isKeyBoardPaste) { e.preventDefault(); } if (global$2.ie && (!isKeyBoardPaste || e.ieFake) && !hasContentType(clipboardContent, 'text/html')) { pasteBin.create(); editor.dom.bind(pasteBin.getEl(), 'paste', function (e) { e.stopPropagation(); }); editor.getDoc().execCommand('Paste', false, null); clipboardContent['text/html'] = pasteBin.getHtml(); } if (hasContentType(clipboardContent, 'text/html')) { e.preventDefault(); if (!internal) { internal = InternalHtml.isMarked(clipboardContent['text/html']); } insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal); } else { global$3.setEditorTimeout(editor, function () { insertClipboardContent(clipboardContent, isKeyBoardPaste, plainTextMode, internal); }, 0); } }); }; var registerEventsAndFilters = function (editor, pasteBin, pasteFormat) { registerEventHandlers(editor, pasteBin, pasteFormat); var src; editor.parser.addNodeFilter('img', function (nodes, name, args) { var isPasteInsert = function (args) { return args.data && args.data.paste === true; }; var remove = function (node) { if (!node.attr('data-mce-object') && src !== global$2.transparentSrc) { node.remove(); } }; var isWebKitFakeUrl = function (src) { return src.indexOf('webkit-fake-url') === 0; }; var isDataUri = function (src) { return src.indexOf('data:') === 0; }; if (!editor.settings.paste_data_images && isPasteInsert(args)) { var i = nodes.length; while (i--) { src = nodes[i].attributes.map.src; if (!src) { continue; } if (isWebKitFakeUrl(src)) { remove(nodes[i]); } else if (!editor.settings.allow_html_data_urls && isDataUri(src)) { remove(nodes[i]); } } } }); }; var getPasteBinParent = function (editor) { return global$2.ie && editor.inline ? domGlobals.document.body : editor.getBody(); }; var isExternalPasteBin = function (editor) { return getPasteBinParent(editor) !== editor.getBody(); }; var delegatePasteEvents = function (editor, pasteBinElm, pasteBinDefaultContent) { if (isExternalPasteBin(editor)) { editor.dom.bind(pasteBinElm, 'paste keyup', function (e) { if (!isDefault(editor, pasteBinDefaultContent)) { editor.fire('paste'); } }); } }; var create = function (editor, lastRngCell, pasteBinDefaultContent) { var dom = editor.dom, body = editor.getBody(); var pasteBinElm; lastRngCell.set(editor.selection.getRng()); pasteBinElm = editor.dom.add(getPasteBinParent(editor), 'div', { 'id': 'mcepastebin', 'class': 'mce-pastebin', 'contentEditable': true, 'data-mce-bogus': 'all', 'style': 'position: fixed; top: 50%; width: 10px; height: 10px; overflow: hidden; opacity: 0' }, pasteBinDefaultContent); if (global$2.ie || global$2.gecko) { dom.setStyle(pasteBinElm, 'left', dom.getStyle(body, 'direction', true) === 'rtl' ? 65535 : -65535); } dom.bind(pasteBinElm, 'beforedeactivate focusin focusout', function (e) { e.stopPropagation(); }); delegatePasteEvents(editor, pasteBinElm, pasteBinDefaultContent); pasteBinElm.focus(); editor.selection.select(pasteBinElm, true); }; var remove = function (editor, lastRngCell) { if (getEl(editor)) { var pasteBinClone = void 0; var lastRng = lastRngCell.get(); while (pasteBinClone = editor.dom.get('mcepastebin')) { editor.dom.remove(pasteBinClone); editor.dom.unbind(pasteBinClone); } if (lastRng) { editor.selection.setRng(lastRng); } } lastRngCell.set(null); }; var getEl = function (editor) { return editor.dom.get('mcepastebin'); }; var getHtml = function (editor) { var pasteBinElm, pasteBinClones, i, dirtyWrappers, cleanWrapper; var copyAndRemove = function (toElm, fromElm) { toElm.appendChild(fromElm); editor.dom.remove(fromElm, true); }; pasteBinClones = global$4.grep(getPasteBinParent(editor).childNodes, function (elm) { return elm.id === 'mcepastebin'; }); pasteBinElm = pasteBinClones.shift(); global$4.each(pasteBinClones, function (pasteBinClone) { copyAndRemove(pasteBinElm, pasteBinClone); }); dirtyWrappers = editor.dom.select('div[id=mcepastebin]', pasteBinElm); for (i = dirtyWrappers.length - 1; i >= 0; i--) { cleanWrapper = editor.dom.create('div'); pasteBinElm.insertBefore(cleanWrapper, dirtyWrappers[i]); copyAndRemove(cleanWrapper, dirtyWrappers[i]); } return pasteBinElm ? pasteBinElm.innerHTML : ''; }; var getLastRng = function (lastRng) { return lastRng.get(); }; var isDefaultContent = function (pasteBinDefaultContent, content) { return content === pasteBinDefaultContent; }; var isPasteBin = function (elm) { return elm && elm.id === 'mcepastebin'; }; var isDefault = function (editor, pasteBinDefaultContent) { var pasteBinElm = getEl(editor); return isPasteBin(pasteBinElm) && isDefaultContent(pasteBinDefaultContent, pasteBinElm.innerHTML); }; var PasteBin = function (editor) { var lastRng = Cell(null); var pasteBinDefaultContent = '%MCEPASTEBIN%'; return { create: function () { return create(editor, lastRng, pasteBinDefaultContent); }, remove: function () { return remove(editor, lastRng); }, getEl: function () { return getEl(editor); }, getHtml: function () { return getHtml(editor); }, getLastRng: function () { return getLastRng(lastRng); }, isDefault: function () { return isDefault(editor, pasteBinDefaultContent); }, isDefaultContent: function (content) { return isDefaultContent(pasteBinDefaultContent, content); } }; }; var Clipboard = function (editor, pasteFormat) { var pasteBin = PasteBin(editor); editor.on('preInit', function () { return registerEventsAndFilters(editor, pasteBin, pasteFormat); }); return { pasteFormat: pasteFormat, pasteHtml: function (html, internalFlag) { return pasteHtml$1(editor, html, internalFlag); }, pasteText: function (text) { return pasteText(editor, text); }, pasteImageData: function (e, rng) { return pasteImageData(editor, e, rng); }, getDataTransferItems: getDataTransferItems, hasHtmlOrText: hasHtmlOrText, hasContentType: hasContentType }; }; var noop$1 = function () { }; var hasWorkingClipboardApi = function (clipboardData) { return global$2.iOS === false && clipboardData !== undefined && typeof clipboardData.setData === 'function' && Utils.isMsEdge() !== true; }; var setHtml5Clipboard = function (clipboardData, html, text) { if (hasWorkingClipboardApi(clipboardData)) { try { clipboardData.clearData(); clipboardData.setData('text/html', html); clipboardData.setData('text/plain', text); clipboardData.setData(InternalHtml.internalHtmlMime(), html); return true; } catch (e) { return false; } } else { return false; } }; var setClipboardData = function (evt, data, fallback, done) { if (setHtml5Clipboard(evt.clipboardData, data.html, data.text)) { evt.preventDefault(); done(); } else { fallback(data.html, done); } }; var fallback = function (editor) { return function (html, done) { var markedHtml = InternalHtml.mark(html); var outer = editor.dom.create('div', { 'contenteditable': 'false', 'data-mce-bogus': 'all' }); var inner = editor.dom.create('div', { contenteditable: 'true' }, markedHtml); editor.dom.setStyles(outer, { position: 'fixed', top: '0', left: '-3000px', width: '1000px', overflow: 'hidden' }); outer.appendChild(inner); editor.dom.add(editor.getBody(), outer); var range = editor.selection.getRng(); inner.focus(); var offscreenRange = editor.dom.createRng(); offscreenRange.selectNodeContents(inner); editor.selection.setRng(offscreenRange); setTimeout(function () { editor.selection.setRng(range); outer.parentNode.removeChild(outer); done(); }, 0); }; }; var getData = function (editor) { return { html: editor.selection.getContent({ contextual: true }), text: editor.selection.getContent({ format: 'text' }) }; }; var isTableSelection = function (editor) { return !!editor.dom.getParent(editor.selection.getStart(), 'td[data-mce-selected],th[data-mce-selected]', editor.getBody()); }; var hasSelectedContent = function (editor) { return !editor.selection.isCollapsed() || isTableSelection(editor); }; var cut = function (editor) { return function (evt) { if (hasSelectedContent(editor)) { setClipboardData(evt, getData(editor), fallback(editor), function () { setTimeout(function () { editor.execCommand('Delete'); }, 0); }); } }; }; var copy = function (editor) { return function (evt) { if (hasSelectedContent(editor)) { setClipboardData(evt, getData(editor), fallback(editor), noop$1); } }; }; var register$1 = function (editor) { editor.on('cut', cut(editor)); editor.on('copy', copy(editor)); }; var CutCopy = { register: register$1 }; var global$b = tinymce.util.Tools.resolve('tinymce.dom.RangeUtils'); var getCaretRangeFromEvent = function (editor, e) { return global$b.getCaretRangeFromPoint(e.clientX, e.clientY, editor.getDoc()); }; var isPlainTextFileUrl = function (content) { var plainTextContent = content['text/plain']; return plainTextContent ? plainTextContent.indexOf('file://') === 0 : false; }; var setFocusedRange = function (editor, rng) { editor.focus(); editor.selection.setRng(rng); }; var setup = function (editor, clipboard, draggingInternallyState) { if (Settings.shouldBlockDrop(editor)) { editor.on('dragend dragover draggesture dragdrop drop drag', function (e) { e.preventDefault(); e.stopPropagation(); }); } if (!Settings.shouldPasteDataImages(editor)) { editor.on('drop', function (e) { var dataTransfer = e.dataTransfer; if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) { e.preventDefault(); } }); } editor.on('drop', function (e) { var dropContent, rng; rng = getCaretRangeFromEvent(editor, e); if (e.isDefaultPrevented() || draggingInternallyState.get()) { return; } dropContent = clipboard.getDataTransferItems(e.dataTransfer); var internal = clipboard.hasContentType(dropContent, InternalHtml.internalHtmlMime()); if ((!clipboard.hasHtmlOrText(dropContent) || isPlainTextFileUrl(dropContent)) && clipboard.pasteImageData(e, rng)) { return; } if (rng && Settings.shouldFilterDrop(editor)) { var content_1 = dropContent['mce-internal'] || dropContent['text/html'] || dropContent['text/plain']; if (content_1) { e.preventDefault(); global$3.setEditorTimeout(editor, function () { editor.undoManager.transact(function () { if (dropContent['mce-internal']) { editor.execCommand('Delete'); } setFocusedRange(editor, rng); content_1 = Utils.trimHtml(content_1); if (!dropContent['text/html']) { clipboard.pasteText(content_1); } else { clipboard.pasteHtml(content_1, internal); } }); }); } } }); editor.on('dragstart', function (e) { draggingInternallyState.set(true); }); editor.on('dragover dragend', function (e) { if (Settings.shouldPasteDataImages(editor) && draggingInternallyState.get() === false) { e.preventDefault(); setFocusedRange(editor, getCaretRangeFromEvent(editor, e)); } if (e.type === 'dragend') { draggingInternallyState.set(false); } }); }; var DragDrop = { setup: setup }; var setup$1 = function (editor) { var plugin = editor.plugins.paste; var preProcess = Settings.getPreProcess(editor); if (preProcess) { editor.on('PastePreProcess', function (e) { preProcess.call(plugin, plugin, e); }); } var postProcess = Settings.getPostProcess(editor); if (postProcess) { editor.on('PastePostProcess', function (e) { postProcess.call(plugin, plugin, e); }); } }; var PrePostProcess = { setup: setup$1 }; function addPreProcessFilter(editor, filterFunc) { editor.on('PastePreProcess', function (e) { e.content = filterFunc(editor, e.content, e.internal, e.wordContent); }); } function addPostProcessFilter(editor, filterFunc) { editor.on('PastePostProcess', function (e) { filterFunc(editor, e.node); }); } function removeExplorerBrElementsAfterBlocks(editor, html) { if (!WordFilter.isWordContent(html)) { return html; } var blockElements = []; global$4.each(editor.schema.getBlockElements(), function (block, blockName) { blockElements.push(blockName); }); var explorerBlocksRegExp = new RegExp('(?:
 [\\s\\r\\n]+|
)*(<\\/?(' + blockElements.join('|') + ')[^>]*>)(?:
 [\\s\\r\\n]+|
)*', 'g'); html = Utils.filter(html, [[ explorerBlocksRegExp, '$1' ]]); html = Utils.filter(html, [ [ /

/g, '

' ], [ /
/g, ' ' ], [ /

/g, '
' ] ]); return html; } function removeWebKitStyles(editor, content, internal, isWordHtml) { if (isWordHtml || internal) { return content; } var webKitStylesSetting = Settings.getWebkitStyles(editor); var webKitStyles; if (Settings.shouldRemoveWebKitStyles(editor) === false || webKitStylesSetting === 'all') { return content; } if (webKitStylesSetting) { webKitStyles = webKitStylesSetting.split(/[, ]/); } if (webKitStyles) { var dom_1 = editor.dom, node_1 = editor.selection.getNode(); content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, function (all, before, value, after) { var inputStyles = dom_1.parseStyle(dom_1.decode(value)); var outputStyles = {}; if (webKitStyles === 'none') { return before + after; } for (var i = 0; i < webKitStyles.length; i++) { var inputValue = inputStyles[webKitStyles[i]], currentValue = dom_1.getStyle(node_1, webKitStyles[i], true); if (/color/.test(webKitStyles[i])) { inputValue = dom_1.toHex(inputValue); currentValue = dom_1.toHex(currentValue); } if (currentValue !== inputValue) { outputStyles[webKitStyles[i]] = inputValue; } } outputStyles = dom_1.serializeStyle(outputStyles, 'span'); if (outputStyles) { return before + ' style="' + outputStyles + '"' + after; } return before + after; }); } else { content = content.replace(/(<[^>]+) style="([^"]*)"([^>]*>)/gi, '$1$3'); } content = content.replace(/(<[^>]+) data-mce-style="([^"]+)"([^>]*>)/gi, function (all, before, value, after) { return before + ' style="' + value + '"' + after; }); return content; } function removeUnderlineAndFontInAnchor(editor, root) { editor.$('a', root).find('font,u').each(function (i, node) { editor.dom.remove(node, true); }); } var setup$2 = function (editor) { if (global$2.webkit) { addPreProcessFilter(editor, removeWebKitStyles); } if (global$2.ie) { addPreProcessFilter(editor, removeExplorerBrElementsAfterBlocks); addPostProcessFilter(editor, removeUnderlineAndFontInAnchor); } }; var Quirks = { setup: setup$2 }; var stateChange = function (editor, clipboard, e) { var ctrl = e.control; ctrl.active(clipboard.pasteFormat.get() === 'text'); editor.on('PastePlainTextToggle', function (e) { ctrl.active(e.state); }); }; var register$2 = function (editor, clipboard) { var postRender = curry(stateChange, editor, clipboard); editor.addButton('pastetext', { active: false, icon: 'pastetext', tooltip: 'Paste as text', cmd: 'mceTogglePlainTextPaste', onPostRender: postRender }); editor.addMenuItem('pastetext', { text: 'Paste as text', selectable: true, active: clipboard.pasteFormat, cmd: 'mceTogglePlainTextPaste', onPostRender: postRender }); }; var Buttons = { register: register$2 }; global$1.add('paste', function (editor) { if (DetectProPlugin.hasProPlugin(editor) === false) { var userIsInformedState = Cell(false); var draggingInternallyState = Cell(false); var pasteFormat = Cell(Settings.isPasteAsTextEnabled(editor) ? 'text' : 'html'); var clipboard = Clipboard(editor, pasteFormat); var quirks = Quirks.setup(editor); Buttons.register(editor, clipboard); Commands.register(editor, clipboard, userIsInformedState); PrePostProcess.setup(editor); CutCopy.register(editor); DragDrop.setup(editor, clipboard, draggingInternallyState); return Api.get(clipboard, quirks); } }); function Plugin () { } return Plugin; }(window)); })(); tinymce/plugins/wpview/plugin.min.js000064400000005526147573120640013655 0ustar00!function(c){c.PluginManager.add("wpview",function(o){function e(){}var n=window.wp;return n&&n.mce&&n.mce.views&&(o.on("init",function(){var e=window.MutationObserver||window.WebKitMutationObserver;e&&new e(function(){o.fire("wp-body-class-change")}).observe(o.getBody(),{attributes:!0,attributeFilter:["class"]}),o.on("wp-body-class-change",function(){var n=o.getBody().className;o.$('iframe[class="wpview-sandbox"]').each(function(e,t){if(!t.src||'javascript:""'===t.src)try{t.contentWindow.document.body.className=n}catch(e){}})})}),o.on("beforesetcontent",function(e){var t;if(e.selection||n.mce.views.unbind(),e.content){if(!e.load&&(t=o.selection.getNode())&&t!==o.getBody()&&/^\s*https?:\/\/\S+\s*$/i.test(e.content)){if(!(t=o.dom.getParent(t,"p"))||!/^[\s\uFEFF\u00A0]*$/.test(o.$(t).text()||""))return;t.innerHTML=""}e.content=n.mce.views.setMarkers(e.content,o)}}),o.on("setcontent",function(){n.mce.views.render()}),o.on("preprocess hide",function(e){o.$("div[data-wpview-text], p[data-wpview-marker]",e.node).each(function(e,t){t.innerHTML="."})},!0),o.on("postprocess",function(e){e.content=a(e.content)}),o.on("beforeaddundo",function(e){var t=e.level.content||e.level.fragments&&e.level.fragments.join(""),n=e.lastLevel?e.lastLevel.content||e.lastLevel.fragments&&e.lastLevel.fragments.join(""):o.startContent;t&&n&&-1!==t.indexOf(" data-wpview-")&&-1!==n.indexOf(" data-wpview-")&&a(n)===a(t)&&e.preventDefault()}),o.on("drop objectselected",function(e){i(e.targetClone)&&(e.targetClone=o.getDoc().createTextNode(window.decodeURIComponent(o.dom.getAttrib(e.targetClone,"data-wpview-text"))))}),o.on("pastepreprocess",function(e){var t=e.content;t&&(t=c.trim(t.replace(/<[^>]+>/g,"")),/^https?:\/\/\S+$/i.test(t))&&(e.content=t)}),o.on("resolvename",function(e){i(e.target)&&(e.name=o.dom.getAttrib(e.target,"data-wpview-type")||"object")}),o.on("click keyup",function(){var e=o.selection.getNode();i(e)&&o.dom.getAttrib(e,"data-mce-selected")&&e.setAttribute("data-mce-selected","2")}),o.addButton("wp_view_edit",{tooltip:"Edit|button",icon:"dashicon dashicons-edit",onclick:function(){var e=o.selection.getNode();i(e)&&n.mce.views.edit(o,e)}}),o.addButton("wp_view_remove",{tooltip:"Remove",icon:"dashicon dashicons-no",onclick:function(){o.fire("cut")}}),o.once("preinit",function(){var t;o.wp&&o.wp._createToolbar&&(t=o.wp._createToolbar(["wp_view_edit","wp_view_remove"]),o.on("wptoolbar",function(e){!e.collapsed&&i(e.element)&&(e.toolbar=t)}))}),o.wp=o.wp||{},o.wp.getView=e,o.wp.setViewCursor=e),{getView:e};function i(e){return o.dom.hasClass(e,"wpview")}function a(e){function t(e,t){return"

"+window.decodeURIComponent(t)+"

"}return e&&-1!==e.indexOf(" data-wpview-")?e.replace(/]+data-wpview-text="([^"]+)"[^>]*>(?:\.|[\s\S]+?wpview-end[^>]+>\s*<\/span>\s*)?<\/div>/g,t).replace(/]+data-wpview-marker="([^"]+)"[^>]*>[\s\S]*?<\/p>/g,t):e}})}(window.tinymce);tinymce/plugins/wpview/plugin.js000064400000013703147573120640013067 0ustar00/** * WordPress View plugin. */ ( function( tinymce ) { tinymce.PluginManager.add( 'wpview', function( editor ) { function noop () {} // Set this here as wp-tinymce.js may be loaded too early. var wp = window.wp; if ( ! wp || ! wp.mce || ! wp.mce.views ) { return { getView: noop }; } // Check if a node is a view or not. function isView( node ) { return editor.dom.hasClass( node, 'wpview' ); } // Replace view tags with their text. function resetViews( content ) { function callback( match, $1 ) { return '

' + window.decodeURIComponent( $1 ) + '

'; } if ( ! content || content.indexOf( ' data-wpview-' ) === -1 ) { return content; } return content .replace( /]+data-wpview-text="([^"]+)"[^>]*>(?:\.|[\s\S]+?wpview-end[^>]+>\s*<\/span>\s*)?<\/div>/g, callback ) .replace( /]+data-wpview-marker="([^"]+)"[^>]*>[\s\S]*?<\/p>/g, callback ); } editor.on( 'init', function() { var MutationObserver = window.MutationObserver || window.WebKitMutationObserver; if ( MutationObserver ) { new MutationObserver( function() { editor.fire( 'wp-body-class-change' ); } ) .observe( editor.getBody(), { attributes: true, attributeFilter: ['class'] } ); } // Pass on body class name changes from the editor to the wpView iframes. editor.on( 'wp-body-class-change', function() { var className = editor.getBody().className; editor.$( 'iframe[class="wpview-sandbox"]' ).each( function( i, iframe ) { // Make sure it is a local iframe. // jshint scripturl: true if ( ! iframe.src || iframe.src === 'javascript:""' ) { try { iframe.contentWindow.document.body.className = className; } catch( er ) {} } }); } ); }); // Scan new content for matching view patterns and replace them with markers. editor.on( 'beforesetcontent', function( event ) { var node; if ( ! event.selection ) { wp.mce.views.unbind(); } if ( ! event.content ) { return; } if ( ! event.load ) { node = editor.selection.getNode(); if ( node && node !== editor.getBody() && /^\s*https?:\/\/\S+\s*$/i.test( event.content ) ) { // When a url is pasted or inserted, only try to embed it when it is in an empty paragraph. node = editor.dom.getParent( node, 'p' ); if ( node && /^[\s\uFEFF\u00A0]*$/.test( editor.$( node ).text() || '' ) ) { // Make sure there are no empty inline elements in the

. node.innerHTML = ''; } else { return; } } } event.content = wp.mce.views.setMarkers( event.content, editor ); } ); // Replace any new markers nodes with views. editor.on( 'setcontent', function() { wp.mce.views.render(); } ); // Empty view nodes for easier processing. editor.on( 'preprocess hide', function( event ) { editor.$( 'div[data-wpview-text], p[data-wpview-marker]', event.node ).each( function( i, node ) { node.innerHTML = '.'; } ); }, true ); // Replace views with their text. editor.on( 'postprocess', function( event ) { event.content = resetViews( event.content ); } ); // Prevent adding of undo levels when replacing wpview markers // or when there are changes only in the (non-editable) previews. editor.on( 'beforeaddundo', function( event ) { var lastContent; var newContent = event.level.content || ( event.level.fragments && event.level.fragments.join( '' ) ); if ( ! event.lastLevel ) { lastContent = editor.startContent; } else { lastContent = event.lastLevel.content || ( event.lastLevel.fragments && event.lastLevel.fragments.join( '' ) ); } if ( ! newContent || ! lastContent || newContent.indexOf( ' data-wpview-' ) === -1 || lastContent.indexOf( ' data-wpview-' ) === -1 ) { return; } if ( resetViews( lastContent ) === resetViews( newContent ) ) { event.preventDefault(); } } ); // Make sure views are copied as their text. editor.on( 'drop objectselected', function( event ) { if ( isView( event.targetClone ) ) { event.targetClone = editor.getDoc().createTextNode( window.decodeURIComponent( editor.dom.getAttrib( event.targetClone, 'data-wpview-text' ) ) ); } } ); // Clean up URLs for easier processing. editor.on( 'pastepreprocess', function( event ) { var content = event.content; if ( content ) { content = tinymce.trim( content.replace( /<[^>]+>/g, '' ) ); if ( /^https?:\/\/\S+$/i.test( content ) ) { event.content = content; } } } ); // Show the view type in the element path. editor.on( 'resolvename', function( event ) { if ( isView( event.target ) ) { event.name = editor.dom.getAttrib( event.target, 'data-wpview-type' ) || 'object'; } } ); // See `media` plugin. editor.on( 'click keyup', function() { var node = editor.selection.getNode(); if ( isView( node ) ) { if ( editor.dom.getAttrib( node, 'data-mce-selected' ) ) { node.setAttribute( 'data-mce-selected', '2' ); } } } ); editor.addButton( 'wp_view_edit', { tooltip: 'Edit|button', // '|button' is not displayed, only used for context. icon: 'dashicon dashicons-edit', onclick: function() { var node = editor.selection.getNode(); if ( isView( node ) ) { wp.mce.views.edit( editor, node ); } } } ); editor.addButton( 'wp_view_remove', { tooltip: 'Remove', icon: 'dashicon dashicons-no', onclick: function() { editor.fire( 'cut' ); } } ); editor.once( 'preinit', function() { var toolbar; if ( editor.wp && editor.wp._createToolbar ) { toolbar = editor.wp._createToolbar( [ 'wp_view_edit', 'wp_view_remove' ] ); editor.on( 'wptoolbar', function( event ) { if ( ! event.collapsed && isView( event.element ) ) { event.toolbar = toolbar; } } ); } } ); editor.wp = editor.wp || {}; editor.wp.getView = noop; editor.wp.setViewCursor = noop; return { getView: noop }; } ); } )( window.tinymce ); tinymce/plugins/wpemoji/plugin.min.js000064400000002757147573120640014011 0ustar00!function(m){m.PluginManager.add("wpemoji",function(n){var t,o=window.wp,e=window._wpemojiSettings,i=m.Env,a=window.navigator.userAgent,w=-1]+data-wp-emoji="[^>]+>/g,function(e){var t=e.match(/alt="([^"]+)"/);return t&&t[1]?t[1]:e}))}),n.on("resolvename",function(e){"IMG"===e.target.nodeName&&n.dom.getAttrib(e.target,"data-wp-emoji")&&e.preventDefault()}))})}(window.tinymce);tinymce/plugins/wpemoji/plugin.js000064400000006774147573120640013232 0ustar00( function( tinymce ) { tinymce.PluginManager.add( 'wpemoji', function( editor ) { var typing, wp = window.wp, settings = window._wpemojiSettings, env = tinymce.Env, ua = window.navigator.userAgent, isWin = ua.indexOf( 'Windows' ) > -1, isWin8 = ( function() { var match = ua.match( /Windows NT 6\.(\d)/ ); if ( match && match[1] > 1 ) { return true; } return false; }()); if ( ! wp || ! wp.emoji || settings.supports.everything ) { return; } function setImgAttr( image ) { image.className = 'emoji'; image.setAttribute( 'data-mce-resize', 'false' ); image.setAttribute( 'data-mce-placeholder', '1' ); image.setAttribute( 'data-wp-emoji', '1' ); } function replaceEmoji( node ) { var imgAttr = { 'data-mce-resize': 'false', 'data-mce-placeholder': '1', 'data-wp-emoji': '1' }; wp.emoji.parse( node, { imgAttr: imgAttr } ); } // Test if the node text contains emoji char(s) and replace. function parseNode( node ) { var selection, bookmark; if ( node && window.twemoji && window.twemoji.test( node.textContent || node.innerText ) ) { if ( env.webkit ) { selection = editor.selection; bookmark = selection.getBookmark(); } replaceEmoji( node ); if ( env.webkit ) { selection.moveToBookmark( bookmark ); } } } if ( isWin8 ) { /* * Windows 8+ emoji can be "typed" with the onscreen keyboard. * That triggers the normal keyboard events, but not the 'input' event. * Thankfully it sets keyCode 231 when the onscreen keyboard inserts any emoji. */ editor.on( 'keyup', function( event ) { if ( event.keyCode === 231 ) { parseNode( editor.selection.getNode() ); } } ); } else if ( ! isWin ) { /* * In MacOS inserting emoji doesn't trigger the stanradr keyboard events. * Thankfully it triggers the 'input' event. * This works in Android and iOS as well. */ editor.on( 'keydown keyup', function( event ) { typing = ( event.type === 'keydown' ); } ); editor.on( 'input', function() { if ( typing ) { return; } parseNode( editor.selection.getNode() ); }); } editor.on( 'setcontent', function( event ) { var selection = editor.selection, node = selection.getNode(); if ( window.twemoji && window.twemoji.test( node.textContent || node.innerText ) ) { replaceEmoji( node ); // In IE all content in the editor is left selected after wp.emoji.parse()... // Collapse the selection to the beginning. if ( env.ie && env.ie < 9 && event.load && node && node.nodeName === 'BODY' ) { selection.collapse( true ); } } } ); // Convert Twemoji compatible pasted emoji replacement images into our format. editor.on( 'PastePostProcess', function( event ) { if ( window.twemoji ) { tinymce.each( editor.dom.$( 'img.emoji', event.node ), function( image ) { if ( image.alt && window.twemoji.test( image.alt ) ) { setImgAttr( image ); } }); } }); editor.on( 'postprocess', function( event ) { if ( event.content ) { event.content = event.content.replace( /]+data-wp-emoji="[^>]+>/g, function( img ) { var alt = img.match( /alt="([^"]+)"/ ); if ( alt && alt[1] ) { return alt[1]; } return img; }); } } ); editor.on( 'resolvename', function( event ) { if ( event.target.nodeName === 'IMG' && editor.dom.getAttrib( event.target, 'data-wp-emoji' ) ) { event.preventDefault(); } } ); } ); } )( window.tinymce ); tinymce/plugins/fullscreen/plugin.min.js000064400000004210147573120640014463 0ustar00!function(m){"use strict";var i=function(e){var n=e,t=function(){return n};return{get:t,set:function(e){n=e},clone:function(){return i(t())}}},e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=function(e){return{isFullscreen:function(){return null!==e.get()}}},n=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),g=function(e,n){e.fire("FullscreenStateChanged",{state:n})},w=n.DOM,r=function(e,n){var t,r,l,i,o,c,s=m.document.body,u=m.document.documentElement,d=n.get(),a=function(){var e,n,t,i;w.setStyle(l,"height",(t=m.window,i=m.document.body,i.offsetWidth&&(e=i.offsetWidth,n=i.offsetHeight),t.innerWidth&&t.innerHeight&&(e=t.innerWidth,n=t.innerHeight),{w:e,h:n}).h-(r.clientHeight-l.clientHeight))},h=function(){w.unbind(m.window,"resize",a)};if(t=(r=e.getContainer()).style,i=(l=e.getContentAreaContainer().firstChild).style,d)i.width=d.iframeWidth,i.height=d.iframeHeight,d.containerWidth&&(t.width=d.containerWidth),d.containerHeight&&(t.height=d.containerHeight),w.removeClass(s,"mce-fullscreen"),w.removeClass(u,"mce-fullscreen"),w.removeClass(r,"mce-fullscreen"),o=d.scrollPos,m.window.scrollTo(o.x,o.y),w.unbind(m.window,"resize",d.resizeHandler),e.off("remove",d.removeHandler),n.set(null),g(e,!1);else{var f={scrollPos:(c=w.getViewPort(),{x:c.x,y:c.y}),containerWidth:t.width,containerHeight:t.height,iframeWidth:i.width,iframeHeight:i.height,resizeHandler:a,removeHandler:h};i.width=i.height="100%",t.width=t.height="",w.addClass(s,"mce-fullscreen"),w.addClass(u,"mce-fullscreen"),w.addClass(r,"mce-fullscreen"),w.bind(m.window,"resize",a),e.on("remove",h),a(),n.set(f),g(e,!0)}},l=function(e,n){e.addCommand("mceFullScreen",function(){r(e,n)})},o=function(t){return function(e){var n=e.control;t.on("FullscreenStateChanged",function(e){n.active(e.state)})}},c=function(e){e.addMenuItem("fullscreen",{text:"Fullscreen",shortcut:"Ctrl+Shift+F",selectable:!0,cmd:"mceFullScreen",onPostRender:o(e),context:"view"}),e.addButton("fullscreen",{active:!1,tooltip:"Fullscreen",cmd:"mceFullScreen",onPostRender:o(e)})};e.add("fullscreen",function(e){var n=i(null);return e.settings.inline||(l(e,n),c(e),e.addShortcut("Ctrl+Shift+F","","mceFullScreen")),t(n)})}(window);tinymce/plugins/fullscreen/plugin.js000064400000012733147573120640013712 0ustar00(function () { var fullscreen = (function (domGlobals) { 'use strict'; var Cell = function (initial) { var value = initial; var get = function () { return value; }; var set = function (v) { value = v; }; var clone = function () { return Cell(get()); }; return { get: get, set: set, clone: clone }; }; var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); var get = function (fullscreenState) { return { isFullscreen: function () { return fullscreenState.get() !== null; } }; }; var Api = { get: get }; var global$1 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils'); var fireFullscreenStateChanged = function (editor, state) { editor.fire('FullscreenStateChanged', { state: state }); }; var Events = { fireFullscreenStateChanged: fireFullscreenStateChanged }; var DOM = global$1.DOM; var getWindowSize = function () { var w; var h; var win = domGlobals.window; var doc = domGlobals.document; var body = doc.body; if (body.offsetWidth) { w = body.offsetWidth; h = body.offsetHeight; } if (win.innerWidth && win.innerHeight) { w = win.innerWidth; h = win.innerHeight; } return { w: w, h: h }; }; var getScrollPos = function () { var vp = DOM.getViewPort(); return { x: vp.x, y: vp.y }; }; var setScrollPos = function (pos) { domGlobals.window.scrollTo(pos.x, pos.y); }; var toggleFullscreen = function (editor, fullscreenState) { var body = domGlobals.document.body; var documentElement = domGlobals.document.documentElement; var editorContainerStyle; var editorContainer, iframe, iframeStyle; var fullscreenInfo = fullscreenState.get(); var resize = function () { DOM.setStyle(iframe, 'height', getWindowSize().h - (editorContainer.clientHeight - iframe.clientHeight)); }; var removeResize = function () { DOM.unbind(domGlobals.window, 'resize', resize); }; editorContainer = editor.getContainer(); editorContainerStyle = editorContainer.style; iframe = editor.getContentAreaContainer().firstChild; iframeStyle = iframe.style; if (!fullscreenInfo) { var newFullScreenInfo = { scrollPos: getScrollPos(), containerWidth: editorContainerStyle.width, containerHeight: editorContainerStyle.height, iframeWidth: iframeStyle.width, iframeHeight: iframeStyle.height, resizeHandler: resize, removeHandler: removeResize }; iframeStyle.width = iframeStyle.height = '100%'; editorContainerStyle.width = editorContainerStyle.height = ''; DOM.addClass(body, 'mce-fullscreen'); DOM.addClass(documentElement, 'mce-fullscreen'); DOM.addClass(editorContainer, 'mce-fullscreen'); DOM.bind(domGlobals.window, 'resize', resize); editor.on('remove', removeResize); resize(); fullscreenState.set(newFullScreenInfo); Events.fireFullscreenStateChanged(editor, true); } else { iframeStyle.width = fullscreenInfo.iframeWidth; iframeStyle.height = fullscreenInfo.iframeHeight; if (fullscreenInfo.containerWidth) { editorContainerStyle.width = fullscreenInfo.containerWidth; } if (fullscreenInfo.containerHeight) { editorContainerStyle.height = fullscreenInfo.containerHeight; } DOM.removeClass(body, 'mce-fullscreen'); DOM.removeClass(documentElement, 'mce-fullscreen'); DOM.removeClass(editorContainer, 'mce-fullscreen'); setScrollPos(fullscreenInfo.scrollPos); DOM.unbind(domGlobals.window, 'resize', fullscreenInfo.resizeHandler); editor.off('remove', fullscreenInfo.removeHandler); fullscreenState.set(null); Events.fireFullscreenStateChanged(editor, false); } }; var Actions = { toggleFullscreen: toggleFullscreen }; var register = function (editor, fullscreenState) { editor.addCommand('mceFullScreen', function () { Actions.toggleFullscreen(editor, fullscreenState); }); }; var Commands = { register: register }; var postRender = function (editor) { return function (e) { var ctrl = e.control; editor.on('FullscreenStateChanged', function (e) { ctrl.active(e.state); }); }; }; var register$1 = function (editor) { editor.addMenuItem('fullscreen', { text: 'Fullscreen', shortcut: 'Ctrl+Shift+F', selectable: true, cmd: 'mceFullScreen', onPostRender: postRender(editor), context: 'view' }); editor.addButton('fullscreen', { active: false, tooltip: 'Fullscreen', cmd: 'mceFullScreen', onPostRender: postRender(editor) }); }; var Buttons = { register: register$1 }; global.add('fullscreen', function (editor) { var fullscreenState = Cell(null); if (editor.settings.inline) { return Api.get(fullscreenState); } Commands.register(editor, fullscreenState); Buttons.register(editor); editor.addShortcut('Ctrl+Shift+F', '', 'mceFullScreen'); return Api.get(fullscreenState); }); function Plugin () { } return Plugin; }(window)); })(); tinymce/plugins/lists/plugin.min.js000064400000064530147573120640013472 0ustar00!function(u){"use strict";var e,n,t,r,o,i,s,a,c,f=tinymce.util.Tools.resolve("tinymce.PluginManager"),d=tinymce.util.Tools.resolve("tinymce.dom.RangeUtils"),l=tinymce.util.Tools.resolve("tinymce.dom.TreeWalker"),m=tinymce.util.Tools.resolve("tinymce.util.VK"),p=tinymce.util.Tools.resolve("tinymce.dom.BookmarkManager"),v=tinymce.util.Tools.resolve("tinymce.util.Tools"),g=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),h=function(e){return e&&"BR"===e.nodeName},y=function(e){return e&&3===e.nodeType},N=function(e){return e&&/^(OL|UL|DL)$/.test(e.nodeName)},S=function(e){return e&&/^(OL|UL)$/.test(e.nodeName)},C=function(e){return e&&/^(DT|DD)$/.test(e.nodeName)},O=function(e){return e&&/^(LI|DT|DD)$/.test(e.nodeName)},b=function(e){return e&&/^(TH|TD)$/.test(e.nodeName)},T=h,E=function(e,n){return n&&!!e.schema.getTextBlockElements()[n.nodeName]},L=function(e,n){return e&&e.nodeName in n},D=function(e,n){return!!h(n)&&!(!e.isBlock(n.nextSibling)||h(n.previousSibling))},w=function(e,n,t){var r=e.isEmpty(n);return!(t&&0=e.childNodes.length?t.data.length:0}:t.previousSibling&&y(t.previousSibling)?{container:t.previousSibling,offset:t.previousSibling.data.length}:t.nextSibling&&y(t.nextSibling)?{container:t.nextSibling,offset:0}:{container:e,offset:n}},x=function(e){var n=e.cloneRange(),t=A(e.startContainer,e.startOffset);n.setStart(t.container,t.offset);var r=A(e.endContainer,e.endOffset);return n.setEnd(r.container,r.offset),n},R=g.DOM,I=function(o){var i={},e=function(e){var n,t,r;t=o[e?"startContainer":"endContainer"],r=o[e?"startOffset":"endOffset"],1===t.nodeType&&(n=R.create("span",{"data-mce-type":"bookmark"}),t.hasChildNodes()?(r=Math.min(r,t.childNodes.length-1),e?t.insertBefore(n,t.childNodes[r]):R.insertAfter(n,t.childNodes[r])):t.appendChild(n),t=n,r=0),i[e?"startContainer":"endContainer"]=t,i[e?"startOffset":"endOffset"]=r};return e(!0),o.collapsed||e(),i},_=function(o){function e(e){var n,t,r;n=r=o[e?"startContainer":"endContainer"],t=o[e?"startOffset":"endOffset"],n&&(1===n.nodeType&&(t=function(e){for(var n=e.parentNode.firstChild,t=0;n;){if(n===e)return t;1===n.nodeType&&"bookmark"===n.getAttribute("data-mce-type")||t++,n=n.nextSibling}return-1}(n),n=n.parentNode,R.remove(r),!n.hasChildNodes()&&R.isBlock(n)&&n.appendChild(R.create("br"))),o[e?"startContainer":"endContainer"]=n,o[e?"startOffset":"endOffset"]=t)}e(!0),e();var n=R.createRng();return n.setStart(o.startContainer,o.startOffset),o.endContainer&&n.setEnd(o.endContainer,o.endOffset),x(n)},B=function(){},P=function(e){return function(){return e}},M=function(t){return function(){for(var e=[],n=0;ne.length?Sn(t,e,n):Nn(t,e,n)},[]),oe(o).map(function(e){return e.list})).toArray();var t,r,o},Pn=function(e){var n,t,r=J(ve.getSelectedListItems(e),ye.fromDom);return Ne(te(r,M(On)),te((n=r,(t=Y.call(n,0)).reverse(),t),M(On)),function(e,n){return{start:e,end:n}})},Mn=function(s,e,a){var n,t,r,o=(n=e,t=Pn(s),r=kn(!1),J(n,function(e){return{sourceList:e,entries:xn(0,t,r,e)}}));Z(o,function(e){var n,t,r,o,i,u;n=e.entries,t=a,Z(ee(n,Tn),function(e){return function(e,n){switch(e){case"Indent":n.depth++;break;case"Outdent":n.depth--;break;case"Flatten":n.depth=0}}(t,e)}),r=e.sourceList,i=s,u=e.entries,o=re(function(e,n){if(0===e.length)return[];for(var t=n(e[0]),r=[],o=[],i=0,u=e.length;i 0) { return false; } return empty; }; var isChildOfBody = function (dom, elm) { return dom.isChildOf(elm, dom.getRoot()); }; var NodeType = { isTextNode: isTextNode, isListNode: isListNode, isOlUlNode: isOlUlNode, isDlItemNode: isDlItemNode, isListItemNode: isListItemNode, isTableCellNode: isTableCellNode, isBr: isBr, isFirstChild: isFirstChild, isLastChild: isLastChild, isTextBlock: isTextBlock, isBlock: isBlock, isBogusBr: isBogusBr, isEmpty: isEmpty, isChildOfBody: isChildOfBody }; var getNormalizedPoint = function (container, offset) { if (NodeType.isTextNode(container)) { return { container: container, offset: offset }; } var node = global$1.getNode(container, offset); if (NodeType.isTextNode(node)) { return { container: node, offset: offset >= container.childNodes.length ? node.data.length : 0 }; } else if (node.previousSibling && NodeType.isTextNode(node.previousSibling)) { return { container: node.previousSibling, offset: node.previousSibling.data.length }; } else if (node.nextSibling && NodeType.isTextNode(node.nextSibling)) { return { container: node.nextSibling, offset: 0 }; } return { container: container, offset: offset }; }; var normalizeRange = function (rng) { var outRng = rng.cloneRange(); var rangeStart = getNormalizedPoint(rng.startContainer, rng.startOffset); outRng.setStart(rangeStart.container, rangeStart.offset); var rangeEnd = getNormalizedPoint(rng.endContainer, rng.endOffset); outRng.setEnd(rangeEnd.container, rangeEnd.offset); return outRng; }; var Range = { getNormalizedPoint: getNormalizedPoint, normalizeRange: normalizeRange }; var DOM = global$6.DOM; var createBookmark = function (rng) { var bookmark = {}; var setupEndPoint = function (start) { var offsetNode, container, offset; container = rng[start ? 'startContainer' : 'endContainer']; offset = rng[start ? 'startOffset' : 'endOffset']; if (container.nodeType === 1) { offsetNode = DOM.create('span', { 'data-mce-type': 'bookmark' }); if (container.hasChildNodes()) { offset = Math.min(offset, container.childNodes.length - 1); if (start) { container.insertBefore(offsetNode, container.childNodes[offset]); } else { DOM.insertAfter(offsetNode, container.childNodes[offset]); } } else { container.appendChild(offsetNode); } container = offsetNode; offset = 0; } bookmark[start ? 'startContainer' : 'endContainer'] = container; bookmark[start ? 'startOffset' : 'endOffset'] = offset; }; setupEndPoint(true); if (!rng.collapsed) { setupEndPoint(); } return bookmark; }; var resolveBookmark = function (bookmark) { function restoreEndPoint(start) { var container, offset, node; var nodeIndex = function (container) { var node = container.parentNode.firstChild, idx = 0; while (node) { if (node === container) { return idx; } if (node.nodeType !== 1 || node.getAttribute('data-mce-type') !== 'bookmark') { idx++; } node = node.nextSibling; } return -1; }; container = node = bookmark[start ? 'startContainer' : 'endContainer']; offset = bookmark[start ? 'startOffset' : 'endOffset']; if (!container) { return; } if (container.nodeType === 1) { offset = nodeIndex(container); container = container.parentNode; DOM.remove(node); if (!container.hasChildNodes() && DOM.isBlock(container)) { container.appendChild(DOM.create('br')); } } bookmark[start ? 'startContainer' : 'endContainer'] = container; bookmark[start ? 'startOffset' : 'endOffset'] = offset; } restoreEndPoint(true); restoreEndPoint(); var rng = DOM.createRng(); rng.setStart(bookmark.startContainer, bookmark.startOffset); if (bookmark.endContainer) { rng.setEnd(bookmark.endContainer, bookmark.endOffset); } return Range.normalizeRange(rng); }; var Bookmark = { createBookmark: createBookmark, resolveBookmark: resolveBookmark }; var noop = function () { }; var constant = function (value) { return function () { return value; }; }; var not = function (f) { return function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } return !f.apply(null, args); }; }; var never = constant(false); var always = constant(true); var none = function () { return NONE; }; var NONE = function () { var eq = function (o) { return o.isNone(); }; var call = function (thunk) { return thunk(); }; var id = function (n) { return n; }; var me = { fold: function (n, s) { return n(); }, is: never, isSome: never, isNone: always, getOr: id, getOrThunk: call, getOrDie: function (msg) { throw new Error(msg || 'error: getOrDie called on none.'); }, getOrNull: constant(null), getOrUndefined: constant(undefined), or: id, orThunk: call, map: none, each: noop, bind: none, exists: never, forall: always, filter: none, equals: eq, equals_: eq, toArray: function () { return []; }, toString: constant('none()') }; if (Object.freeze) { Object.freeze(me); } return me; }(); var some = function (a) { var constant_a = constant(a); var self = function () { return me; }; var bind = function (f) { return f(a); }; var me = { fold: function (n, s) { return s(a); }, is: function (v) { return a === v; }, isSome: always, isNone: never, getOr: constant_a, getOrThunk: constant_a, getOrDie: constant_a, getOrNull: constant_a, getOrUndefined: constant_a, or: self, orThunk: self, map: function (f) { return some(f(a)); }, each: function (f) { f(a); }, bind: bind, exists: bind, forall: bind, filter: function (f) { return f(a) ? me : NONE; }, toArray: function () { return [a]; }, toString: function () { return 'some(' + a + ')'; }, equals: function (o) { return o.is(a); }, equals_: function (o, elementEq) { return o.fold(never, function (b) { return elementEq(a, b); }); } }; return me; }; var from = function (value) { return value === null || value === undefined ? NONE : some(value); }; var Option = { some: some, none: none, from: from }; var typeOf = function (x) { if (x === null) { return 'null'; } var t = typeof x; if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) { return 'array'; } if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) { return 'string'; } return t; }; var isType = function (type) { return function (value) { return typeOf(value) === type; }; }; var isString = isType('string'); var isArray = isType('array'); var isBoolean = isType('boolean'); var isFunction = isType('function'); var isNumber = isType('number'); var nativeSlice = Array.prototype.slice; var nativePush = Array.prototype.push; var map = function (xs, f) { var len = xs.length; var r = new Array(len); for (var i = 0; i < len; i++) { var x = xs[i]; r[i] = f(x, i); } return r; }; var each = function (xs, f) { for (var i = 0, len = xs.length; i < len; i++) { var x = xs[i]; f(x, i); } }; var filter = function (xs, pred) { var r = []; for (var i = 0, len = xs.length; i < len; i++) { var x = xs[i]; if (pred(x, i)) { r.push(x); } } return r; }; var groupBy = function (xs, f) { if (xs.length === 0) { return []; } else { var wasType = f(xs[0]); var r = []; var group = []; for (var i = 0, len = xs.length; i < len; i++) { var x = xs[i]; var type = f(x); if (type !== wasType) { r.push(group); group = []; } wasType = type; group.push(x); } if (group.length !== 0) { r.push(group); } return r; } }; var foldl = function (xs, f, acc) { each(xs, function (x) { acc = f(acc, x); }); return acc; }; var find = function (xs, pred) { for (var i = 0, len = xs.length; i < len; i++) { var x = xs[i]; if (pred(x, i)) { return Option.some(x); } } return Option.none(); }; var flatten = function (xs) { var r = []; for (var i = 0, len = xs.length; i < len; ++i) { if (!isArray(xs[i])) { throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs); } nativePush.apply(r, xs[i]); } return r; }; var bind = function (xs, f) { var output = map(xs, f); return flatten(output); }; var reverse = function (xs) { var r = nativeSlice.call(xs, 0); r.reverse(); return r; }; var head = function (xs) { return xs.length === 0 ? Option.none() : Option.some(xs[0]); }; var last = function (xs) { return xs.length === 0 ? Option.none() : Option.some(xs[xs.length - 1]); }; var from$1 = isFunction(Array.from) ? Array.from : function (x) { return nativeSlice.call(x); }; var Global = typeof domGlobals.window !== 'undefined' ? domGlobals.window : Function('return this;')(); var path = function (parts, scope) { var o = scope !== undefined && scope !== null ? scope : Global; for (var i = 0; i < parts.length && o !== undefined && o !== null; ++i) { o = o[parts[i]]; } return o; }; var resolve = function (p, scope) { var parts = p.split('.'); return path(parts, scope); }; var unsafe = function (name, scope) { return resolve(name, scope); }; var getOrDie = function (name, scope) { var actual = unsafe(name, scope); if (actual === undefined || actual === null) { throw new Error(name + ' not available on this browser'); } return actual; }; var Global$1 = { getOrDie: getOrDie }; var htmlElement = function (scope) { return Global$1.getOrDie('HTMLElement', scope); }; var isPrototypeOf = function (x) { var scope = resolve('ownerDocument.defaultView', x); return htmlElement(scope).prototype.isPrototypeOf(x); }; var HTMLElement = { isPrototypeOf: isPrototypeOf }; var global$7 = tinymce.util.Tools.resolve('tinymce.dom.DomQuery'); var getParentList = function (editor) { var selectionStart = editor.selection.getStart(true); return editor.dom.getParent(selectionStart, 'OL,UL,DL', getClosestListRootElm(editor, selectionStart)); }; var isParentListSelected = function (parentList, selectedBlocks) { return parentList && selectedBlocks.length === 1 && selectedBlocks[0] === parentList; }; var findSubLists = function (parentList) { return global$5.grep(parentList.querySelectorAll('ol,ul,dl'), function (elm) { return NodeType.isListNode(elm); }); }; var getSelectedSubLists = function (editor) { var parentList = getParentList(editor); var selectedBlocks = editor.selection.getSelectedBlocks(); if (isParentListSelected(parentList, selectedBlocks)) { return findSubLists(parentList); } else { return global$5.grep(selectedBlocks, function (elm) { return NodeType.isListNode(elm) && parentList !== elm; }); } }; var findParentListItemsNodes = function (editor, elms) { var listItemsElms = global$5.map(elms, function (elm) { var parentLi = editor.dom.getParent(elm, 'li,dd,dt', getClosestListRootElm(editor, elm)); return parentLi ? parentLi : elm; }); return global$7.unique(listItemsElms); }; var getSelectedListItems = function (editor) { var selectedBlocks = editor.selection.getSelectedBlocks(); return global$5.grep(findParentListItemsNodes(editor, selectedBlocks), function (block) { return NodeType.isListItemNode(block); }); }; var getSelectedDlItems = function (editor) { return filter(getSelectedListItems(editor), NodeType.isDlItemNode); }; var getClosestListRootElm = function (editor, elm) { var parentTableCell = editor.dom.getParents(elm, 'TD,TH'); var root = parentTableCell.length > 0 ? parentTableCell[0] : editor.getBody(); return root; }; var findLastParentListNode = function (editor, elm) { var parentLists = editor.dom.getParents(elm, 'ol,ul', getClosestListRootElm(editor, elm)); return last(parentLists); }; var getSelectedLists = function (editor) { var firstList = findLastParentListNode(editor, editor.selection.getStart()); var subsequentLists = filter(editor.selection.getSelectedBlocks(), NodeType.isOlUlNode); return firstList.toArray().concat(subsequentLists); }; var getSelectedListRoots = function (editor) { var selectedLists = getSelectedLists(editor); return getUniqueListRoots(editor, selectedLists); }; var getUniqueListRoots = function (editor, lists) { var listRoots = map(lists, function (list) { return findLastParentListNode(editor, list).getOr(list); }); return global$7.unique(listRoots); }; var isList = function (editor) { var list = getParentList(editor); return HTMLElement.isPrototypeOf(list); }; var Selection = { isList: isList, getParentList: getParentList, getSelectedSubLists: getSelectedSubLists, getSelectedListItems: getSelectedListItems, getClosestListRootElm: getClosestListRootElm, getSelectedDlItems: getSelectedDlItems, getSelectedListRoots: getSelectedListRoots }; var fromHtml = function (html, scope) { var doc = scope || domGlobals.document; var div = doc.createElement('div'); div.innerHTML = html; if (!div.hasChildNodes() || div.childNodes.length > 1) { domGlobals.console.error('HTML does not have a single root node', html); throw new Error('HTML must have a single root node'); } return fromDom(div.childNodes[0]); }; var fromTag = function (tag, scope) { var doc = scope || domGlobals.document; var node = doc.createElement(tag); return fromDom(node); }; var fromText = function (text, scope) { var doc = scope || domGlobals.document; var node = doc.createTextNode(text); return fromDom(node); }; var fromDom = function (node) { if (node === null || node === undefined) { throw new Error('Node cannot be null or undefined'); } return { dom: constant(node) }; }; var fromPoint = function (docElm, x, y) { var doc = docElm.dom(); return Option.from(doc.elementFromPoint(x, y)).map(fromDom); }; var Element = { fromHtml: fromHtml, fromTag: fromTag, fromText: fromText, fromDom: fromDom, fromPoint: fromPoint }; var lift2 = function (oa, ob, f) { return oa.isSome() && ob.isSome() ? Option.some(f(oa.getOrDie(), ob.getOrDie())) : Option.none(); }; var fromElements = function (elements, scope) { var doc = scope || domGlobals.document; var fragment = doc.createDocumentFragment(); each(elements, function (element) { fragment.appendChild(element.dom()); }); return Element.fromDom(fragment); }; var Immutable = function () { var fields = []; for (var _i = 0; _i < arguments.length; _i++) { fields[_i] = arguments[_i]; } return function () { var values = []; for (var _i = 0; _i < arguments.length; _i++) { values[_i] = arguments[_i]; } if (fields.length !== values.length) { throw new Error('Wrong number of arguments to struct. Expected "[' + fields.length + ']", got ' + values.length + ' arguments'); } var struct = {}; each(fields, function (name, i) { struct[name] = constant(values[i]); }); return struct; }; }; var keys = Object.keys; var each$1 = function (obj, f) { var props = keys(obj); for (var k = 0, len = props.length; k < len; k++) { var i = props[k]; var x = obj[i]; f(x, i); } }; var node = function () { var f = Global$1.getOrDie('Node'); return f; }; var compareDocumentPosition = function (a, b, match) { return (a.compareDocumentPosition(b) & match) !== 0; }; var documentPositionPreceding = function (a, b) { return compareDocumentPosition(a, b, node().DOCUMENT_POSITION_PRECEDING); }; var documentPositionContainedBy = function (a, b) { return compareDocumentPosition(a, b, node().DOCUMENT_POSITION_CONTAINED_BY); }; var Node = { documentPositionPreceding: documentPositionPreceding, documentPositionContainedBy: documentPositionContainedBy }; var cached = function (f) { var called = false; var r; return function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } if (!called) { called = true; r = f.apply(null, args); } return r; }; }; var firstMatch = function (regexes, s) { for (var i = 0; i < regexes.length; i++) { var x = regexes[i]; if (x.test(s)) { return x; } } return undefined; }; var find$1 = function (regexes, agent) { var r = firstMatch(regexes, agent); if (!r) { return { major: 0, minor: 0 }; } var group = function (i) { return Number(agent.replace(r, '$' + i)); }; return nu(group(1), group(2)); }; var detect = function (versionRegexes, agent) { var cleanedAgent = String(agent).toLowerCase(); if (versionRegexes.length === 0) { return unknown(); } return find$1(versionRegexes, cleanedAgent); }; var unknown = function () { return nu(0, 0); }; var nu = function (major, minor) { return { major: major, minor: minor }; }; var Version = { nu: nu, detect: detect, unknown: unknown }; var edge = 'Edge'; var chrome = 'Chrome'; var ie = 'IE'; var opera = 'Opera'; var firefox = 'Firefox'; var safari = 'Safari'; var isBrowser = function (name, current) { return function () { return current === name; }; }; var unknown$1 = function () { return nu$1({ current: undefined, version: Version.unknown() }); }; var nu$1 = function (info) { var current = info.current; var version = info.version; return { current: current, version: version, isEdge: isBrowser(edge, current), isChrome: isBrowser(chrome, current), isIE: isBrowser(ie, current), isOpera: isBrowser(opera, current), isFirefox: isBrowser(firefox, current), isSafari: isBrowser(safari, current) }; }; var Browser = { unknown: unknown$1, nu: nu$1, edge: constant(edge), chrome: constant(chrome), ie: constant(ie), opera: constant(opera), firefox: constant(firefox), safari: constant(safari) }; var windows = 'Windows'; var ios = 'iOS'; var android = 'Android'; var linux = 'Linux'; var osx = 'OSX'; var solaris = 'Solaris'; var freebsd = 'FreeBSD'; var isOS = function (name, current) { return function () { return current === name; }; }; var unknown$2 = function () { return nu$2({ current: undefined, version: Version.unknown() }); }; var nu$2 = function (info) { var current = info.current; var version = info.version; return { current: current, version: version, isWindows: isOS(windows, current), isiOS: isOS(ios, current), isAndroid: isOS(android, current), isOSX: isOS(osx, current), isLinux: isOS(linux, current), isSolaris: isOS(solaris, current), isFreeBSD: isOS(freebsd, current) }; }; var OperatingSystem = { unknown: unknown$2, nu: nu$2, windows: constant(windows), ios: constant(ios), android: constant(android), linux: constant(linux), osx: constant(osx), solaris: constant(solaris), freebsd: constant(freebsd) }; var DeviceType = function (os, browser, userAgent) { var isiPad = os.isiOS() && /ipad/i.test(userAgent) === true; var isiPhone = os.isiOS() && !isiPad; var isAndroid3 = os.isAndroid() && os.version.major === 3; var isAndroid4 = os.isAndroid() && os.version.major === 4; var isTablet = isiPad || isAndroid3 || isAndroid4 && /mobile/i.test(userAgent) === true; var isTouch = os.isiOS() || os.isAndroid(); var isPhone = isTouch && !isTablet; var iOSwebview = browser.isSafari() && os.isiOS() && /safari/i.test(userAgent) === false; return { isiPad: constant(isiPad), isiPhone: constant(isiPhone), isTablet: constant(isTablet), isPhone: constant(isPhone), isTouch: constant(isTouch), isAndroid: os.isAndroid, isiOS: os.isiOS, isWebView: constant(iOSwebview) }; }; var detect$1 = function (candidates, userAgent) { var agent = String(userAgent).toLowerCase(); return find(candidates, function (candidate) { return candidate.search(agent); }); }; var detectBrowser = function (browsers, userAgent) { return detect$1(browsers, userAgent).map(function (browser) { var version = Version.detect(browser.versionRegexes, userAgent); return { current: browser.name, version: version }; }); }; var detectOs = function (oses, userAgent) { return detect$1(oses, userAgent).map(function (os) { var version = Version.detect(os.versionRegexes, userAgent); return { current: os.name, version: version }; }); }; var UaString = { detectBrowser: detectBrowser, detectOs: detectOs }; var contains = function (str, substr) { return str.indexOf(substr) !== -1; }; var normalVersionRegex = /.*?version\/\ ?([0-9]+)\.([0-9]+).*/; var checkContains = function (target) { return function (uastring) { return contains(uastring, target); }; }; var browsers = [ { name: 'Edge', versionRegexes: [/.*?edge\/ ?([0-9]+)\.([0-9]+)$/], search: function (uastring) { return contains(uastring, 'edge/') && contains(uastring, 'chrome') && contains(uastring, 'safari') && contains(uastring, 'applewebkit'); } }, { name: 'Chrome', versionRegexes: [ /.*?chrome\/([0-9]+)\.([0-9]+).*/, normalVersionRegex ], search: function (uastring) { return contains(uastring, 'chrome') && !contains(uastring, 'chromeframe'); } }, { name: 'IE', versionRegexes: [ /.*?msie\ ?([0-9]+)\.([0-9]+).*/, /.*?rv:([0-9]+)\.([0-9]+).*/ ], search: function (uastring) { return contains(uastring, 'msie') || contains(uastring, 'trident'); } }, { name: 'Opera', versionRegexes: [ normalVersionRegex, /.*?opera\/([0-9]+)\.([0-9]+).*/ ], search: checkContains('opera') }, { name: 'Firefox', versionRegexes: [/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/], search: checkContains('firefox') }, { name: 'Safari', versionRegexes: [ normalVersionRegex, /.*?cpu os ([0-9]+)_([0-9]+).*/ ], search: function (uastring) { return (contains(uastring, 'safari') || contains(uastring, 'mobile/')) && contains(uastring, 'applewebkit'); } } ]; var oses = [ { name: 'Windows', search: checkContains('win'), versionRegexes: [/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/] }, { name: 'iOS', search: function (uastring) { return contains(uastring, 'iphone') || contains(uastring, 'ipad'); }, versionRegexes: [ /.*?version\/\ ?([0-9]+)\.([0-9]+).*/, /.*cpu os ([0-9]+)_([0-9]+).*/, /.*cpu iphone os ([0-9]+)_([0-9]+).*/ ] }, { name: 'Android', search: checkContains('android'), versionRegexes: [/.*?android\ ?([0-9]+)\.([0-9]+).*/] }, { name: 'OSX', search: checkContains('os x'), versionRegexes: [/.*?os\ x\ ?([0-9]+)_([0-9]+).*/] }, { name: 'Linux', search: checkContains('linux'), versionRegexes: [] }, { name: 'Solaris', search: checkContains('sunos'), versionRegexes: [] }, { name: 'FreeBSD', search: checkContains('freebsd'), versionRegexes: [] } ]; var PlatformInfo = { browsers: constant(browsers), oses: constant(oses) }; var detect$2 = function (userAgent) { var browsers = PlatformInfo.browsers(); var oses = PlatformInfo.oses(); var browser = UaString.detectBrowser(browsers, userAgent).fold(Browser.unknown, Browser.nu); var os = UaString.detectOs(oses, userAgent).fold(OperatingSystem.unknown, OperatingSystem.nu); var deviceType = DeviceType(os, browser, userAgent); return { browser: browser, os: os, deviceType: deviceType }; }; var PlatformDetection = { detect: detect$2 }; var detect$3 = cached(function () { var userAgent = domGlobals.navigator.userAgent; return PlatformDetection.detect(userAgent); }); var PlatformDetection$1 = { detect: detect$3 }; var ATTRIBUTE = domGlobals.Node.ATTRIBUTE_NODE; var CDATA_SECTION = domGlobals.Node.CDATA_SECTION_NODE; var COMMENT = domGlobals.Node.COMMENT_NODE; var DOCUMENT = domGlobals.Node.DOCUMENT_NODE; var DOCUMENT_TYPE = domGlobals.Node.DOCUMENT_TYPE_NODE; var DOCUMENT_FRAGMENT = domGlobals.Node.DOCUMENT_FRAGMENT_NODE; var ELEMENT = domGlobals.Node.ELEMENT_NODE; var TEXT = domGlobals.Node.TEXT_NODE; var PROCESSING_INSTRUCTION = domGlobals.Node.PROCESSING_INSTRUCTION_NODE; var ENTITY_REFERENCE = domGlobals.Node.ENTITY_REFERENCE_NODE; var ENTITY = domGlobals.Node.ENTITY_NODE; var NOTATION = domGlobals.Node.NOTATION_NODE; var ELEMENT$1 = ELEMENT; var is = function (element, selector) { var dom = element.dom(); if (dom.nodeType !== ELEMENT$1) { return false; } else { var elem = dom; if (elem.matches !== undefined) { return elem.matches(selector); } else if (elem.msMatchesSelector !== undefined) { return elem.msMatchesSelector(selector); } else if (elem.webkitMatchesSelector !== undefined) { return elem.webkitMatchesSelector(selector); } else if (elem.mozMatchesSelector !== undefined) { return elem.mozMatchesSelector(selector); } else { throw new Error('Browser lacks native selectors'); } } }; var eq = function (e1, e2) { return e1.dom() === e2.dom(); }; var regularContains = function (e1, e2) { var d1 = e1.dom(); var d2 = e2.dom(); return d1 === d2 ? false : d1.contains(d2); }; var ieContains = function (e1, e2) { return Node.documentPositionContainedBy(e1.dom(), e2.dom()); }; var browser = PlatformDetection$1.detect().browser; var contains$1 = browser.isIE() ? ieContains : regularContains; var is$1 = is; var parent = function (element) { return Option.from(element.dom().parentNode).map(Element.fromDom); }; var children = function (element) { return map(element.dom().childNodes, Element.fromDom); }; var child = function (element, index) { var cs = element.dom().childNodes; return Option.from(cs[index]).map(Element.fromDom); }; var firstChild = function (element) { return child(element, 0); }; var lastChild = function (element) { return child(element, element.dom().childNodes.length - 1); }; var spot = Immutable('element', 'offset'); var before = function (marker, element) { var parent$1 = parent(marker); parent$1.each(function (v) { v.dom().insertBefore(element.dom(), marker.dom()); }); }; var append = function (parent, element) { parent.dom().appendChild(element.dom()); }; var before$1 = function (marker, elements) { each(elements, function (x) { before(marker, x); }); }; var append$1 = function (parent, elements) { each(elements, function (x) { append(parent, x); }); }; var remove = function (element) { var dom = element.dom(); if (dom.parentNode !== null) { dom.parentNode.removeChild(dom); } }; var name = function (element) { var r = element.dom().nodeName; return r.toLowerCase(); }; var type = function (element) { return element.dom().nodeType; }; var isType$1 = function (t) { return function (element) { return type(element) === t; }; }; var isElement = isType$1(ELEMENT); var rawSet = function (dom, key, value) { if (isString(value) || isBoolean(value) || isNumber(value)) { dom.setAttribute(key, value + ''); } else { domGlobals.console.error('Invalid call to Attr.set. Key ', key, ':: Value ', value, ':: Element ', dom); throw new Error('Attribute value was not simple'); } }; var setAll = function (element, attrs) { var dom = element.dom(); each$1(attrs, function (v, k) { rawSet(dom, k, v); }); }; var clone = function (element) { return foldl(element.dom().attributes, function (acc, attr) { acc[attr.name] = attr.value; return acc; }, {}); }; var isSupported = function (dom) { return dom.style !== undefined && isFunction(dom.style.getPropertyValue); }; var internalSet = function (dom, property, value) { if (!isString(value)) { domGlobals.console.error('Invalid call to CSS.set. Property ', property, ':: Value ', value, ':: Element ', dom); throw new Error('CSS value must be a string: ' + value); } if (isSupported(dom)) { dom.style.setProperty(property, value); } }; var set = function (element, property, value) { var dom = element.dom(); internalSet(dom, property, value); }; var clone$1 = function (original, isDeep) { return Element.fromDom(original.dom().cloneNode(isDeep)); }; var deep = function (original) { return clone$1(original, true); }; var shallowAs = function (original, tag) { var nu = Element.fromTag(tag); var attributes = clone(original); setAll(nu, attributes); return nu; }; var mutate = function (original, tag) { var nu = shallowAs(original, tag); before(original, nu); var children$1 = children(original); append$1(nu, children$1); remove(original); return nu; }; var joinSegment = function (parent, child) { append(parent.item, child.list); }; var joinSegments = function (segments) { for (var i = 1; i < segments.length; i++) { joinSegment(segments[i - 1], segments[i]); } }; var appendSegments = function (head$1, tail) { lift2(last(head$1), head(tail), joinSegment); }; var createSegment = function (scope, listType) { var segment = { list: Element.fromTag(listType, scope), item: Element.fromTag('li', scope) }; append(segment.list, segment.item); return segment; }; var createSegments = function (scope, entry, size) { var segments = []; for (var i = 0; i < size; i++) { segments.push(createSegment(scope, entry.listType)); } return segments; }; var populateSegments = function (segments, entry) { for (var i = 0; i < segments.length - 1; i++) { set(segments[i].item, 'list-style-type', 'none'); } last(segments).each(function (segment) { setAll(segment.list, entry.listAttributes); setAll(segment.item, entry.itemAttributes); append$1(segment.item, entry.content); }); }; var normalizeSegment = function (segment, entry) { if (name(segment.list) !== entry.listType) { segment.list = mutate(segment.list, entry.listType); } setAll(segment.list, entry.listAttributes); }; var createItem = function (scope, attr, content) { var item = Element.fromTag('li', scope); setAll(item, attr); append$1(item, content); return item; }; var appendItem = function (segment, item) { append(segment.list, item); segment.item = item; }; var writeShallow = function (scope, cast, entry) { var newCast = cast.slice(0, entry.depth); last(newCast).each(function (segment) { var item = createItem(scope, entry.itemAttributes, entry.content); appendItem(segment, item); normalizeSegment(segment, entry); }); return newCast; }; var writeDeep = function (scope, cast, entry) { var segments = createSegments(scope, entry, entry.depth - cast.length); joinSegments(segments); populateSegments(segments, entry); appendSegments(cast, segments); return cast.concat(segments); }; var composeList = function (scope, entries) { var cast = foldl(entries, function (cast, entry) { return entry.depth > cast.length ? writeDeep(scope, cast, entry) : writeShallow(scope, cast, entry); }, []); return head(cast).map(function (segment) { return segment.list; }); }; var isList$1 = function (el) { return is$1(el, 'OL,UL'); }; var hasFirstChildList = function (el) { return firstChild(el).map(isList$1).getOr(false); }; var hasLastChildList = function (el) { return lastChild(el).map(isList$1).getOr(false); }; var isIndented = function (entry) { return entry.depth > 0; }; var isSelected = function (entry) { return entry.isSelected; }; var cloneItemContent = function (li) { var children$1 = children(li); var content = hasLastChildList(li) ? children$1.slice(0, -1) : children$1; return map(content, deep); }; var createEntry = function (li, depth, isSelected) { return parent(li).filter(isElement).map(function (list) { return { depth: depth, isSelected: isSelected, content: cloneItemContent(li), itemAttributes: clone(li), listAttributes: clone(list), listType: name(list) }; }); }; var indentEntry = function (indentation, entry) { switch (indentation) { case 'Indent': entry.depth++; break; case 'Outdent': entry.depth--; break; case 'Flatten': entry.depth = 0; } }; var hasOwnProperty = Object.prototype.hasOwnProperty; var shallow = function (old, nu) { return nu; }; var baseMerge = function (merger) { return function () { var objects = new Array(arguments.length); for (var i = 0; i < objects.length; i++) { objects[i] = arguments[i]; } if (objects.length === 0) { throw new Error('Can\'t merge zero objects'); } var ret = {}; for (var j = 0; j < objects.length; j++) { var curObject = objects[j]; for (var key in curObject) { if (hasOwnProperty.call(curObject, key)) { ret[key] = merger(ret[key], curObject[key]); } } } return ret; }; }; var merge = baseMerge(shallow); var cloneListProperties = function (target, source) { target.listType = source.listType; target.listAttributes = merge({}, source.listAttributes); }; var previousSiblingEntry = function (entries, start) { var depth = entries[start].depth; for (var i = start - 1; i >= 0; i--) { if (entries[i].depth === depth) { return Option.some(entries[i]); } if (entries[i].depth < depth) { break; } } return Option.none(); }; var normalizeEntries = function (entries) { each(entries, function (entry, i) { previousSiblingEntry(entries, i).each(function (matchingEntry) { cloneListProperties(entry, matchingEntry); }); }); }; var Cell = function (initial) { var value = initial; var get = function () { return value; }; var set = function (v) { value = v; }; var clone = function () { return Cell(get()); }; return { get: get, set: set, clone: clone }; }; var parseItem = function (depth, itemSelection, selectionState, item) { return firstChild(item).filter(isList$1).fold(function () { itemSelection.each(function (selection) { if (eq(selection.start, item)) { selectionState.set(true); } }); var currentItemEntry = createEntry(item, depth, selectionState.get()); itemSelection.each(function (selection) { if (eq(selection.end, item)) { selectionState.set(false); } }); var childListEntries = lastChild(item).filter(isList$1).map(function (list) { return parseList(depth, itemSelection, selectionState, list); }).getOr([]); return currentItemEntry.toArray().concat(childListEntries); }, function (list) { return parseList(depth, itemSelection, selectionState, list); }); }; var parseList = function (depth, itemSelection, selectionState, list) { return bind(children(list), function (element) { var parser = isList$1(element) ? parseList : parseItem; var newDepth = depth + 1; return parser(newDepth, itemSelection, selectionState, element); }); }; var parseLists = function (lists, itemSelection) { var selectionState = Cell(false); var initialDepth = 0; return map(lists, function (list) { return { sourceList: list, entries: parseList(initialDepth, itemSelection, selectionState, list) }; }); }; var global$8 = tinymce.util.Tools.resolve('tinymce.Env'); var createTextBlock = function (editor, contentNode) { var dom = editor.dom; var blockElements = editor.schema.getBlockElements(); var fragment = dom.createFragment(); var node, textBlock, blockName, hasContentNode; if (editor.settings.forced_root_block) { blockName = editor.settings.forced_root_block; } if (blockName) { textBlock = dom.create(blockName); if (textBlock.tagName === editor.settings.forced_root_block) { dom.setAttribs(textBlock, editor.settings.forced_root_block_attrs); } if (!NodeType.isBlock(contentNode.firstChild, blockElements)) { fragment.appendChild(textBlock); } } if (contentNode) { while (node = contentNode.firstChild) { var nodeName = node.nodeName; if (!hasContentNode && (nodeName !== 'SPAN' || node.getAttribute('data-mce-type') !== 'bookmark')) { hasContentNode = true; } if (NodeType.isBlock(node, blockElements)) { fragment.appendChild(node); textBlock = null; } else { if (blockName) { if (!textBlock) { textBlock = dom.create(blockName); fragment.appendChild(textBlock); } textBlock.appendChild(node); } else { fragment.appendChild(node); } } } } if (!editor.settings.forced_root_block) { fragment.appendChild(dom.create('br')); } else { if (!hasContentNode && (!global$8.ie || global$8.ie > 10)) { textBlock.appendChild(dom.create('br', { 'data-mce-bogus': '1' })); } } return fragment; }; var outdentedComposer = function (editor, entries) { return map(entries, function (entry) { var content = fromElements(entry.content); return Element.fromDom(createTextBlock(editor, content.dom())); }); }; var indentedComposer = function (editor, entries) { normalizeEntries(entries); return composeList(editor.contentDocument, entries).toArray(); }; var composeEntries = function (editor, entries) { return bind(groupBy(entries, isIndented), function (entries) { var groupIsIndented = head(entries).map(isIndented).getOr(false); return groupIsIndented ? indentedComposer(editor, entries) : outdentedComposer(editor, entries); }); }; var indentSelectedEntries = function (entries, indentation) { each(filter(entries, isSelected), function (entry) { return indentEntry(indentation, entry); }); }; var getItemSelection = function (editor) { var selectedListItems = map(Selection.getSelectedListItems(editor), Element.fromDom); return lift2(find(selectedListItems, not(hasFirstChildList)), find(reverse(selectedListItems), not(hasFirstChildList)), function (start, end) { return { start: start, end: end }; }); }; var listsIndentation = function (editor, lists, indentation) { var entrySets = parseLists(lists, getItemSelection(editor)); each(entrySets, function (entrySet) { indentSelectedEntries(entrySet.entries, indentation); before$1(entrySet.sourceList, composeEntries(editor, entrySet.entries)); remove(entrySet.sourceList); }); }; var DOM$1 = global$6.DOM; var splitList = function (editor, ul, li) { var tmpRng, fragment, bookmarks, node, newBlock; var removeAndKeepBookmarks = function (targetNode) { global$5.each(bookmarks, function (node) { targetNode.parentNode.insertBefore(node, li.parentNode); }); DOM$1.remove(targetNode); }; bookmarks = DOM$1.select('span[data-mce-type="bookmark"]', ul); newBlock = createTextBlock(editor, li); tmpRng = DOM$1.createRng(); tmpRng.setStartAfter(li); tmpRng.setEndAfter(ul); fragment = tmpRng.extractContents(); for (node = fragment.firstChild; node; node = node.firstChild) { if (node.nodeName === 'LI' && editor.dom.isEmpty(node)) { DOM$1.remove(node); break; } } if (!editor.dom.isEmpty(fragment)) { DOM$1.insertAfter(fragment, ul); } DOM$1.insertAfter(newBlock, ul); if (NodeType.isEmpty(editor.dom, li.parentNode)) { removeAndKeepBookmarks(li.parentNode); } DOM$1.remove(li); if (NodeType.isEmpty(editor.dom, ul)) { DOM$1.remove(ul); } }; var SplitList = { splitList: splitList }; var outdentDlItem = function (editor, item) { if (is$1(item, 'dd')) { mutate(item, 'dt'); } else if (is$1(item, 'dt')) { parent(item).each(function (dl) { return SplitList.splitList(editor, dl.dom(), item.dom()); }); } }; var indentDlItem = function (item) { if (is$1(item, 'dt')) { mutate(item, 'dd'); } }; var dlIndentation = function (editor, indentation, dlItems) { if (indentation === 'Indent') { each(dlItems, indentDlItem); } else { each(dlItems, function (item) { return outdentDlItem(editor, item); }); } }; var selectionIndentation = function (editor, indentation) { var lists = map(Selection.getSelectedListRoots(editor), Element.fromDom); var dlItems = map(Selection.getSelectedDlItems(editor), Element.fromDom); var isHandled = false; if (lists.length || dlItems.length) { var bookmark = editor.selection.getBookmark(); listsIndentation(editor, lists, indentation); dlIndentation(editor, indentation, dlItems); editor.selection.moveToBookmark(bookmark); editor.selection.setRng(Range.normalizeRange(editor.selection.getRng())); editor.nodeChanged(); isHandled = true; } return isHandled; }; var indentListSelection = function (editor) { return selectionIndentation(editor, 'Indent'); }; var outdentListSelection = function (editor) { return selectionIndentation(editor, 'Outdent'); }; var flattenListSelection = function (editor) { return selectionIndentation(editor, 'Flatten'); }; var updateListStyle = function (dom, el, detail) { var type = detail['list-style-type'] ? detail['list-style-type'] : null; dom.setStyle(el, 'list-style-type', type); }; var setAttribs = function (elm, attrs) { global$5.each(attrs, function (value, key) { elm.setAttribute(key, value); }); }; var updateListAttrs = function (dom, el, detail) { setAttribs(el, detail['list-attributes']); global$5.each(dom.select('li', el), function (li) { setAttribs(li, detail['list-item-attributes']); }); }; var updateListWithDetails = function (dom, el, detail) { updateListStyle(dom, el, detail); updateListAttrs(dom, el, detail); }; var removeStyles = function (dom, element, styles) { global$5.each(styles, function (style) { var _a; return dom.setStyle(element, (_a = {}, _a[style] = '', _a)); }); }; var getEndPointNode = function (editor, rng, start, root) { var container, offset; container = rng[start ? 'startContainer' : 'endContainer']; offset = rng[start ? 'startOffset' : 'endOffset']; if (container.nodeType === 1) { container = container.childNodes[Math.min(offset, container.childNodes.length - 1)] || container; } if (!start && NodeType.isBr(container.nextSibling)) { container = container.nextSibling; } while (container.parentNode !== root) { if (NodeType.isTextBlock(editor, container)) { return container; } if (/^(TD|TH)$/.test(container.parentNode.nodeName)) { return container; } container = container.parentNode; } return container; }; var getSelectedTextBlocks = function (editor, rng, root) { var textBlocks = [], dom = editor.dom; var startNode = getEndPointNode(editor, rng, true, root); var endNode = getEndPointNode(editor, rng, false, root); var block; var siblings = []; for (var node = startNode; node; node = node.nextSibling) { siblings.push(node); if (node === endNode) { break; } } global$5.each(siblings, function (node) { if (NodeType.isTextBlock(editor, node)) { textBlocks.push(node); block = null; return; } if (dom.isBlock(node) || NodeType.isBr(node)) { if (NodeType.isBr(node)) { dom.remove(node); } block = null; return; } var nextSibling = node.nextSibling; if (global$4.isBookmarkNode(node)) { if (NodeType.isTextBlock(editor, nextSibling) || !nextSibling && node.parentNode === root) { block = null; return; } } if (!block) { block = dom.create('p'); node.parentNode.insertBefore(block, node); textBlocks.push(block); } block.appendChild(node); }); return textBlocks; }; var hasCompatibleStyle = function (dom, sib, detail) { var sibStyle = dom.getStyle(sib, 'list-style-type'); var detailStyle = detail ? detail['list-style-type'] : ''; detailStyle = detailStyle === null ? '' : detailStyle; return sibStyle === detailStyle; }; var applyList = function (editor, listName, detail) { if (detail === void 0) { detail = {}; } var rng = editor.selection.getRng(true); var bookmark; var listItemName = 'LI'; var root = Selection.getClosestListRootElm(editor, editor.selection.getStart(true)); var dom = editor.dom; if (dom.getContentEditable(editor.selection.getNode()) === 'false') { return; } listName = listName.toUpperCase(); if (listName === 'DL') { listItemName = 'DT'; } bookmark = Bookmark.createBookmark(rng); global$5.each(getSelectedTextBlocks(editor, rng, root), function (block) { var listBlock, sibling; sibling = block.previousSibling; if (sibling && NodeType.isListNode(sibling) && sibling.nodeName === listName && hasCompatibleStyle(dom, sibling, detail)) { listBlock = sibling; block = dom.rename(block, listItemName); sibling.appendChild(block); } else { listBlock = dom.create(listName); block.parentNode.insertBefore(listBlock, block); listBlock.appendChild(block); block = dom.rename(block, listItemName); } removeStyles(dom, block, [ 'margin', 'margin-right', 'margin-bottom', 'margin-left', 'margin-top', 'padding', 'padding-right', 'padding-bottom', 'padding-left', 'padding-top' ]); updateListWithDetails(dom, listBlock, detail); mergeWithAdjacentLists(editor.dom, listBlock); }); editor.selection.setRng(Bookmark.resolveBookmark(bookmark)); }; var isValidLists = function (list1, list2) { return list1 && list2 && NodeType.isListNode(list1) && list1.nodeName === list2.nodeName; }; var hasSameListStyle = function (dom, list1, list2) { var targetStyle = dom.getStyle(list1, 'list-style-type', true); var style = dom.getStyle(list2, 'list-style-type', true); return targetStyle === style; }; var hasSameClasses = function (elm1, elm2) { return elm1.className === elm2.className; }; var shouldMerge = function (dom, list1, list2) { return isValidLists(list1, list2) && hasSameListStyle(dom, list1, list2) && hasSameClasses(list1, list2); }; var mergeWithAdjacentLists = function (dom, listBlock) { var sibling, node; sibling = listBlock.nextSibling; if (shouldMerge(dom, listBlock, sibling)) { while (node = sibling.firstChild) { listBlock.appendChild(node); } dom.remove(sibling); } sibling = listBlock.previousSibling; if (shouldMerge(dom, listBlock, sibling)) { while (node = sibling.lastChild) { listBlock.insertBefore(node, listBlock.firstChild); } dom.remove(sibling); } }; var updateList = function (dom, list, listName, detail) { if (list.nodeName !== listName) { var newList = dom.rename(list, listName); updateListWithDetails(dom, newList, detail); } else { updateListWithDetails(dom, list, detail); } }; var toggleMultipleLists = function (editor, parentList, lists, listName, detail) { if (parentList.nodeName === listName && !hasListStyleDetail(detail)) { flattenListSelection(editor); } else { var bookmark = Bookmark.createBookmark(editor.selection.getRng(true)); global$5.each([parentList].concat(lists), function (elm) { updateList(editor.dom, elm, listName, detail); }); editor.selection.setRng(Bookmark.resolveBookmark(bookmark)); } }; var hasListStyleDetail = function (detail) { return 'list-style-type' in detail; }; var toggleSingleList = function (editor, parentList, listName, detail) { if (parentList === editor.getBody()) { return; } if (parentList) { if (parentList.nodeName === listName && !hasListStyleDetail(detail)) { flattenListSelection(editor); } else { var bookmark = Bookmark.createBookmark(editor.selection.getRng(true)); updateListWithDetails(editor.dom, parentList, detail); mergeWithAdjacentLists(editor.dom, editor.dom.rename(parentList, listName)); editor.selection.setRng(Bookmark.resolveBookmark(bookmark)); } } else { applyList(editor, listName, detail); } }; var toggleList = function (editor, listName, detail) { var parentList = Selection.getParentList(editor); var selectedSubLists = Selection.getSelectedSubLists(editor); detail = detail ? detail : {}; if (parentList && selectedSubLists.length > 0) { toggleMultipleLists(editor, parentList, selectedSubLists, listName, detail); } else { toggleSingleList(editor, parentList, listName, detail); } }; var ToggleList = { toggleList: toggleList, mergeWithAdjacentLists: mergeWithAdjacentLists }; var DOM$2 = global$6.DOM; var normalizeList = function (dom, ul) { var sibling; var parentNode = ul.parentNode; if (parentNode.nodeName === 'LI' && parentNode.firstChild === ul) { sibling = parentNode.previousSibling; if (sibling && sibling.nodeName === 'LI') { sibling.appendChild(ul); if (NodeType.isEmpty(dom, parentNode)) { DOM$2.remove(parentNode); } } else { DOM$2.setStyle(parentNode, 'listStyleType', 'none'); } } if (NodeType.isListNode(parentNode)) { sibling = parentNode.previousSibling; if (sibling && sibling.nodeName === 'LI') { sibling.appendChild(ul); } } }; var normalizeLists = function (dom, element) { global$5.each(global$5.grep(dom.select('ol,ul', element)), function (ul) { normalizeList(dom, ul); }); }; var NormalizeLists = { normalizeList: normalizeList, normalizeLists: normalizeLists }; var findNextCaretContainer = function (editor, rng, isForward, root) { var node = rng.startContainer; var offset = rng.startOffset; var nonEmptyBlocks, walker; if (node.nodeType === 3 && (isForward ? offset < node.data.length : offset > 0)) { return node; } nonEmptyBlocks = editor.schema.getNonEmptyElements(); if (node.nodeType === 1) { node = global$1.getNode(node, offset); } walker = new global$2(node, root); if (isForward) { if (NodeType.isBogusBr(editor.dom, node)) { walker.next(); } } while (node = walker[isForward ? 'next' : 'prev2']()) { if (node.nodeName === 'LI' && !node.hasChildNodes()) { return node; } if (nonEmptyBlocks[node.nodeName]) { return node; } if (node.nodeType === 3 && node.data.length > 0) { return node; } } }; var hasOnlyOneBlockChild = function (dom, elm) { var childNodes = elm.childNodes; return childNodes.length === 1 && !NodeType.isListNode(childNodes[0]) && dom.isBlock(childNodes[0]); }; var unwrapSingleBlockChild = function (dom, elm) { if (hasOnlyOneBlockChild(dom, elm)) { dom.remove(elm.firstChild, true); } }; var moveChildren = function (dom, fromElm, toElm) { var node, targetElm; targetElm = hasOnlyOneBlockChild(dom, toElm) ? toElm.firstChild : toElm; unwrapSingleBlockChild(dom, fromElm); if (!NodeType.isEmpty(dom, fromElm, true)) { while (node = fromElm.firstChild) { targetElm.appendChild(node); } } }; var mergeLiElements = function (dom, fromElm, toElm) { var node, listNode; var ul = fromElm.parentNode; if (!NodeType.isChildOfBody(dom, fromElm) || !NodeType.isChildOfBody(dom, toElm)) { return; } if (NodeType.isListNode(toElm.lastChild)) { listNode = toElm.lastChild; } if (ul === toElm.lastChild) { if (NodeType.isBr(ul.previousSibling)) { dom.remove(ul.previousSibling); } } node = toElm.lastChild; if (node && NodeType.isBr(node) && fromElm.hasChildNodes()) { dom.remove(node); } if (NodeType.isEmpty(dom, toElm, true)) { dom.$(toElm).empty(); } moveChildren(dom, fromElm, toElm); if (listNode) { toElm.appendChild(listNode); } var contains = contains$1(Element.fromDom(toElm), Element.fromDom(fromElm)); var nestedLists = contains ? dom.getParents(fromElm, NodeType.isListNode, toElm) : []; dom.remove(fromElm); each(nestedLists, function (list) { if (NodeType.isEmpty(dom, list) && list !== dom.getRoot()) { dom.remove(list); } }); }; var mergeIntoEmptyLi = function (editor, fromLi, toLi) { editor.dom.$(toLi).empty(); mergeLiElements(editor.dom, fromLi, toLi); editor.selection.setCursorLocation(toLi); }; var mergeForward = function (editor, rng, fromLi, toLi) { var dom = editor.dom; if (dom.isEmpty(toLi)) { mergeIntoEmptyLi(editor, fromLi, toLi); } else { var bookmark = Bookmark.createBookmark(rng); mergeLiElements(dom, fromLi, toLi); editor.selection.setRng(Bookmark.resolveBookmark(bookmark)); } }; var mergeBackward = function (editor, rng, fromLi, toLi) { var bookmark = Bookmark.createBookmark(rng); mergeLiElements(editor.dom, fromLi, toLi); var resolvedBookmark = Bookmark.resolveBookmark(bookmark); editor.selection.setRng(resolvedBookmark); }; var backspaceDeleteFromListToListCaret = function (editor, isForward) { var dom = editor.dom, selection = editor.selection; var selectionStartElm = selection.getStart(); var root = Selection.getClosestListRootElm(editor, selectionStartElm); var li = dom.getParent(selection.getStart(), 'LI', root); var ul, rng, otherLi; if (li) { ul = li.parentNode; if (ul === editor.getBody() && NodeType.isEmpty(dom, ul)) { return true; } rng = Range.normalizeRange(selection.getRng(true)); otherLi = dom.getParent(findNextCaretContainer(editor, rng, isForward, root), 'LI', root); if (otherLi && otherLi !== li) { if (isForward) { mergeForward(editor, rng, otherLi, li); } else { mergeBackward(editor, rng, li, otherLi); } return true; } else if (!otherLi) { if (!isForward) { flattenListSelection(editor); return true; } } } return false; }; var removeBlock = function (dom, block, root) { var parentBlock = dom.getParent(block.parentNode, dom.isBlock, root); dom.remove(block); if (parentBlock && dom.isEmpty(parentBlock)) { dom.remove(parentBlock); } }; var backspaceDeleteIntoListCaret = function (editor, isForward) { var dom = editor.dom; var selectionStartElm = editor.selection.getStart(); var root = Selection.getClosestListRootElm(editor, selectionStartElm); var block = dom.getParent(selectionStartElm, dom.isBlock, root); if (block && dom.isEmpty(block)) { var rng = Range.normalizeRange(editor.selection.getRng(true)); var otherLi_1 = dom.getParent(findNextCaretContainer(editor, rng, isForward, root), 'LI', root); if (otherLi_1) { editor.undoManager.transact(function () { removeBlock(dom, block, root); ToggleList.mergeWithAdjacentLists(dom, otherLi_1.parentNode); editor.selection.select(otherLi_1, true); editor.selection.collapse(isForward); }); return true; } } return false; }; var backspaceDeleteCaret = function (editor, isForward) { return backspaceDeleteFromListToListCaret(editor, isForward) || backspaceDeleteIntoListCaret(editor, isForward); }; var backspaceDeleteRange = function (editor) { var selectionStartElm = editor.selection.getStart(); var root = Selection.getClosestListRootElm(editor, selectionStartElm); var startListParent = editor.dom.getParent(selectionStartElm, 'LI,DT,DD', root); if (startListParent || Selection.getSelectedListItems(editor).length > 0) { editor.undoManager.transact(function () { editor.execCommand('Delete'); NormalizeLists.normalizeLists(editor.dom, editor.getBody()); }); return true; } return false; }; var backspaceDelete = function (editor, isForward) { return editor.selection.isCollapsed() ? backspaceDeleteCaret(editor, isForward) : backspaceDeleteRange(editor); }; var setup = function (editor) { editor.on('keydown', function (e) { if (e.keyCode === global$3.BACKSPACE) { if (backspaceDelete(editor, false)) { e.preventDefault(); } } else if (e.keyCode === global$3.DELETE) { if (backspaceDelete(editor, true)) { e.preventDefault(); } } }); }; var Delete = { setup: setup, backspaceDelete: backspaceDelete }; var get = function (editor) { return { backspaceDelete: function (isForward) { Delete.backspaceDelete(editor, isForward); } }; }; var Api = { get: get }; var queryListCommandState = function (editor, listName) { return function () { var parentList = editor.dom.getParent(editor.selection.getStart(), 'UL,OL,DL'); return parentList && parentList.nodeName === listName; }; }; var register = function (editor) { editor.on('BeforeExecCommand', function (e) { var cmd = e.command.toLowerCase(); if (cmd === 'indent') { indentListSelection(editor); } else if (cmd === 'outdent') { outdentListSelection(editor); } }); editor.addCommand('InsertUnorderedList', function (ui, detail) { ToggleList.toggleList(editor, 'UL', detail); }); editor.addCommand('InsertOrderedList', function (ui, detail) { ToggleList.toggleList(editor, 'OL', detail); }); editor.addCommand('InsertDefinitionList', function (ui, detail) { ToggleList.toggleList(editor, 'DL', detail); }); editor.addCommand('RemoveList', function () { flattenListSelection(editor); }); editor.addQueryStateHandler('InsertUnorderedList', queryListCommandState(editor, 'UL')); editor.addQueryStateHandler('InsertOrderedList', queryListCommandState(editor, 'OL')); editor.addQueryStateHandler('InsertDefinitionList', queryListCommandState(editor, 'DL')); }; var Commands = { register: register }; var shouldIndentOnTab = function (editor) { return editor.getParam('lists_indent_on_tab', true); }; var Settings = { shouldIndentOnTab: shouldIndentOnTab }; var setupTabKey = function (editor) { editor.on('keydown', function (e) { if (e.keyCode !== global$3.TAB || global$3.metaKeyPressed(e)) { return; } editor.undoManager.transact(function () { if (e.shiftKey ? outdentListSelection(editor) : indentListSelection(editor)) { e.preventDefault(); } }); }); }; var setup$1 = function (editor) { if (Settings.shouldIndentOnTab(editor)) { setupTabKey(editor); } Delete.setup(editor); }; var Keyboard = { setup: setup$1 }; var findIndex = function (list, predicate) { for (var index = 0; index < list.length; index++) { var element = list[index]; if (predicate(element)) { return index; } } return -1; }; var listState = function (editor, listName) { return function (e) { var ctrl = e.control; editor.on('NodeChange', function (e) { var tableCellIndex = findIndex(e.parents, NodeType.isTableCellNode); var parents = tableCellIndex !== -1 ? e.parents.slice(0, tableCellIndex) : e.parents; var lists = global$5.grep(parents, NodeType.isListNode); ctrl.active(lists.length > 0 && lists[0].nodeName === listName); }); }; }; var register$1 = function (editor) { var hasPlugin = function (editor, plugin) { var plugins = editor.settings.plugins ? editor.settings.plugins : ''; return global$5.inArray(plugins.split(/[ ,]/), plugin) !== -1; }; if (!hasPlugin(editor, 'advlist')) { editor.addButton('numlist', { active: false, title: 'Numbered list', cmd: 'InsertOrderedList', onPostRender: listState(editor, 'OL') }); editor.addButton('bullist', { active: false, title: 'Bullet list', cmd: 'InsertUnorderedList', onPostRender: listState(editor, 'UL') }); } editor.addButton('indent', { icon: 'indent', title: 'Increase indent', cmd: 'Indent' }); }; var Buttons = { register: register$1 }; global.add('lists', function (editor) { Keyboard.setup(editor); Buttons.register(editor); Commands.register(editor); return Api.get(editor); }); function Plugin () { } return Plugin; }(window)); })(); tinymce/plugins/image/plugin.min.js000064400000036754147573120640013425 0ustar00!function(l){"use strict";var i,e=tinymce.util.Tools.resolve("tinymce.PluginManager"),d=function(e){return!1!==e.settings.image_dimensions},u=function(e){return!0===e.settings.image_advtab},m=function(e){return e.getParam("image_prepend_url","")},n=function(e){return e.getParam("image_class_list")},r=function(e){return!1!==e.settings.image_description},a=function(e){return!0===e.settings.image_title},o=function(e){return!0===e.settings.image_caption},c=function(e){return e.getParam("image_list",!1)},s=function(e){return e.getParam("images_upload_url",!1)},g=function(e){return e.getParam("images_upload_handler",!1)},f=function(e){return e.getParam("images_upload_url")},p=function(e){return e.getParam("images_upload_handler")},h=function(e){return e.getParam("images_upload_base_path")},v=function(e){return e.getParam("images_upload_credentials")},b="undefined"!=typeof l.window?l.window:Function("return this;")(),y=function(e,t){return function(e,t){for(var n=t!==undefined&&null!==t?t:b,r=0;r 0 && /^[0-9]+$/.test(value)) { value += 'px'; } return value; }; var mergeMargins = function (css) { if (css.margin) { var splitMargin = css.margin.split(' '); switch (splitMargin.length) { case 1: css['margin-top'] = css['margin-top'] || splitMargin[0]; css['margin-right'] = css['margin-right'] || splitMargin[0]; css['margin-bottom'] = css['margin-bottom'] || splitMargin[0]; css['margin-left'] = css['margin-left'] || splitMargin[0]; break; case 2: css['margin-top'] = css['margin-top'] || splitMargin[0]; css['margin-right'] = css['margin-right'] || splitMargin[1]; css['margin-bottom'] = css['margin-bottom'] || splitMargin[0]; css['margin-left'] = css['margin-left'] || splitMargin[1]; break; case 3: css['margin-top'] = css['margin-top'] || splitMargin[0]; css['margin-right'] = css['margin-right'] || splitMargin[1]; css['margin-bottom'] = css['margin-bottom'] || splitMargin[2]; css['margin-left'] = css['margin-left'] || splitMargin[1]; break; case 4: css['margin-top'] = css['margin-top'] || splitMargin[0]; css['margin-right'] = css['margin-right'] || splitMargin[1]; css['margin-bottom'] = css['margin-bottom'] || splitMargin[2]; css['margin-left'] = css['margin-left'] || splitMargin[3]; } delete css.margin; } return css; }; var createImageList = function (editor, callback) { var imageList = Settings.getImageList(editor); if (typeof imageList === 'string') { global$3.send({ url: imageList, success: function (text) { callback(JSON.parse(text)); } }); } else if (typeof imageList === 'function') { imageList(callback); } else { callback(imageList); } }; var waitLoadImage = function (editor, data, imgElm) { function selectImage() { imgElm.onload = imgElm.onerror = null; if (editor.selection) { editor.selection.select(imgElm); editor.nodeChanged(); } } imgElm.onload = function () { if (!data.width && !data.height && Settings.hasDimensions(editor)) { editor.dom.setAttribs(imgElm, { width: imgElm.clientWidth, height: imgElm.clientHeight }); } selectImage(); }; imgElm.onerror = selectImage; }; var blobToDataUri = function (blob) { return new global$1(function (resolve, reject) { var reader = FileReader(); reader.onload = function () { resolve(reader.result); }; reader.onerror = function () { reject(reader.error.message); }; reader.readAsDataURL(blob); }); }; var Utils = { getImageSize: getImageSize, buildListItems: buildListItems, removePixelSuffix: removePixelSuffix, addPixelSuffix: addPixelSuffix, mergeMargins: mergeMargins, createImageList: createImageList, waitLoadImage: waitLoadImage, blobToDataUri: blobToDataUri }; var global$4 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils'); var hasOwnProperty = Object.prototype.hasOwnProperty; var shallow = function (old, nu) { return nu; }; var baseMerge = function (merger) { return function () { var objects = new Array(arguments.length); for (var i = 0; i < objects.length; i++) { objects[i] = arguments[i]; } if (objects.length === 0) { throw new Error('Can\'t merge zero objects'); } var ret = {}; for (var j = 0; j < objects.length; j++) { var curObject = objects[j]; for (var key in curObject) { if (hasOwnProperty.call(curObject, key)) { ret[key] = merger(ret[key], curObject[key]); } } } return ret; }; }; var merge = baseMerge(shallow); var DOM = global$4.DOM; var getHspace = function (image) { if (image.style.marginLeft && image.style.marginRight && image.style.marginLeft === image.style.marginRight) { return Utils.removePixelSuffix(image.style.marginLeft); } else { return ''; } }; var getVspace = function (image) { if (image.style.marginTop && image.style.marginBottom && image.style.marginTop === image.style.marginBottom) { return Utils.removePixelSuffix(image.style.marginTop); } else { return ''; } }; var getBorder = function (image) { if (image.style.borderWidth) { return Utils.removePixelSuffix(image.style.borderWidth); } else { return ''; } }; var getAttrib = function (image, name) { if (image.hasAttribute(name)) { return image.getAttribute(name); } else { return ''; } }; var getStyle = function (image, name) { return image.style[name] ? image.style[name] : ''; }; var hasCaption = function (image) { return image.parentNode !== null && image.parentNode.nodeName === 'FIGURE'; }; var setAttrib = function (image, name, value) { image.setAttribute(name, value); }; var wrapInFigure = function (image) { var figureElm = DOM.create('figure', { class: 'image' }); DOM.insertAfter(figureElm, image); figureElm.appendChild(image); figureElm.appendChild(DOM.create('figcaption', { contentEditable: true }, 'Caption')); figureElm.contentEditable = 'false'; }; var removeFigure = function (image) { var figureElm = image.parentNode; DOM.insertAfter(image, figureElm); DOM.remove(figureElm); }; var toggleCaption = function (image) { if (hasCaption(image)) { removeFigure(image); } else { wrapInFigure(image); } }; var normalizeStyle = function (image, normalizeCss) { var attrValue = image.getAttribute('style'); var value = normalizeCss(attrValue !== null ? attrValue : ''); if (value.length > 0) { image.setAttribute('style', value); image.setAttribute('data-mce-style', value); } else { image.removeAttribute('style'); } }; var setSize = function (name, normalizeCss) { return function (image, name, value) { if (image.style[name]) { image.style[name] = Utils.addPixelSuffix(value); normalizeStyle(image, normalizeCss); } else { setAttrib(image, name, value); } }; }; var getSize = function (image, name) { if (image.style[name]) { return Utils.removePixelSuffix(image.style[name]); } else { return getAttrib(image, name); } }; var setHspace = function (image, value) { var pxValue = Utils.addPixelSuffix(value); image.style.marginLeft = pxValue; image.style.marginRight = pxValue; }; var setVspace = function (image, value) { var pxValue = Utils.addPixelSuffix(value); image.style.marginTop = pxValue; image.style.marginBottom = pxValue; }; var setBorder = function (image, value) { var pxValue = Utils.addPixelSuffix(value); image.style.borderWidth = pxValue; }; var setBorderStyle = function (image, value) { image.style.borderStyle = value; }; var getBorderStyle = function (image) { return getStyle(image, 'borderStyle'); }; var isFigure = function (elm) { return elm.nodeName === 'FIGURE'; }; var defaultData = function () { return { src: '', alt: '', title: '', width: '', height: '', class: '', style: '', caption: false, hspace: '', vspace: '', border: '', borderStyle: '' }; }; var getStyleValue = function (normalizeCss, data) { var image = domGlobals.document.createElement('img'); setAttrib(image, 'style', data.style); if (getHspace(image) || data.hspace !== '') { setHspace(image, data.hspace); } if (getVspace(image) || data.vspace !== '') { setVspace(image, data.vspace); } if (getBorder(image) || data.border !== '') { setBorder(image, data.border); } if (getBorderStyle(image) || data.borderStyle !== '') { setBorderStyle(image, data.borderStyle); } return normalizeCss(image.getAttribute('style')); }; var create = function (normalizeCss, data) { var image = domGlobals.document.createElement('img'); write(normalizeCss, merge(data, { caption: false }), image); setAttrib(image, 'alt', data.alt); if (data.caption) { var figure = DOM.create('figure', { class: 'image' }); figure.appendChild(image); figure.appendChild(DOM.create('figcaption', { contentEditable: true }, 'Caption')); figure.contentEditable = 'false'; return figure; } else { return image; } }; var read = function (normalizeCss, image) { return { src: getAttrib(image, 'src'), alt: getAttrib(image, 'alt'), title: getAttrib(image, 'title'), width: getSize(image, 'width'), height: getSize(image, 'height'), class: getAttrib(image, 'class'), style: normalizeCss(getAttrib(image, 'style')), caption: hasCaption(image), hspace: getHspace(image), vspace: getVspace(image), border: getBorder(image), borderStyle: getStyle(image, 'borderStyle') }; }; var updateProp = function (image, oldData, newData, name, set) { if (newData[name] !== oldData[name]) { set(image, name, newData[name]); } }; var normalized = function (set, normalizeCss) { return function (image, name, value) { set(image, value); normalizeStyle(image, normalizeCss); }; }; var write = function (normalizeCss, newData, image) { var oldData = read(normalizeCss, image); updateProp(image, oldData, newData, 'caption', function (image, _name, _value) { return toggleCaption(image); }); updateProp(image, oldData, newData, 'src', setAttrib); updateProp(image, oldData, newData, 'alt', setAttrib); updateProp(image, oldData, newData, 'title', setAttrib); updateProp(image, oldData, newData, 'width', setSize('width', normalizeCss)); updateProp(image, oldData, newData, 'height', setSize('height', normalizeCss)); updateProp(image, oldData, newData, 'class', setAttrib); updateProp(image, oldData, newData, 'style', normalized(function (image, value) { return setAttrib(image, 'style', value); }, normalizeCss)); updateProp(image, oldData, newData, 'hspace', normalized(setHspace, normalizeCss)); updateProp(image, oldData, newData, 'vspace', normalized(setVspace, normalizeCss)); updateProp(image, oldData, newData, 'border', normalized(setBorder, normalizeCss)); updateProp(image, oldData, newData, 'borderStyle', normalized(setBorderStyle, normalizeCss)); }; var normalizeCss = function (editor, cssText) { var css = editor.dom.styles.parse(cssText); var mergedCss = Utils.mergeMargins(css); var compressed = editor.dom.styles.parse(editor.dom.styles.serialize(mergedCss)); return editor.dom.styles.serialize(compressed); }; var getSelectedImage = function (editor) { var imgElm = editor.selection.getNode(); var figureElm = editor.dom.getParent(imgElm, 'figure.image'); if (figureElm) { return editor.dom.select('img', figureElm)[0]; } if (imgElm && (imgElm.nodeName !== 'IMG' || imgElm.getAttribute('data-mce-object') || imgElm.getAttribute('data-mce-placeholder'))) { return null; } return imgElm; }; var splitTextBlock = function (editor, figure) { var dom = editor.dom; var textBlock = dom.getParent(figure.parentNode, function (node) { return editor.schema.getTextBlockElements()[node.nodeName]; }, editor.getBody()); if (textBlock) { return dom.split(textBlock, figure); } else { return figure; } }; var readImageDataFromSelection = function (editor) { var image = getSelectedImage(editor); return image ? read(function (css) { return normalizeCss(editor, css); }, image) : defaultData(); }; var insertImageAtCaret = function (editor, data) { var elm = create(function (css) { return normalizeCss(editor, css); }, data); editor.dom.setAttrib(elm, 'data-mce-id', '__mcenew'); editor.focus(); editor.selection.setContent(elm.outerHTML); var insertedElm = editor.dom.select('*[data-mce-id="__mcenew"]')[0]; editor.dom.setAttrib(insertedElm, 'data-mce-id', null); if (isFigure(insertedElm)) { var figure = splitTextBlock(editor, insertedElm); editor.selection.select(figure); } else { editor.selection.select(insertedElm); } }; var syncSrcAttr = function (editor, image) { editor.dom.setAttrib(image, 'src', image.getAttribute('src')); }; var deleteImage = function (editor, image) { if (image) { var elm = editor.dom.is(image.parentNode, 'figure.image') ? image.parentNode : image; editor.dom.remove(elm); editor.focus(); editor.nodeChanged(); if (editor.dom.isEmpty(editor.getBody())) { editor.setContent(''); editor.selection.setCursorLocation(); } } }; var writeImageDataToSelection = function (editor, data) { var image = getSelectedImage(editor); write(function (css) { return normalizeCss(editor, css); }, data, image); syncSrcAttr(editor, image); if (isFigure(image.parentNode)) { var figure = image.parentNode; splitTextBlock(editor, figure); editor.selection.select(image.parentNode); } else { editor.selection.select(image); Utils.waitLoadImage(editor, data, image); } }; var insertOrUpdateImage = function (editor, data) { var image = getSelectedImage(editor); if (image) { if (data.src) { writeImageDataToSelection(editor, data); } else { deleteImage(editor, image); } } else if (data.src) { insertImageAtCaret(editor, data); } }; var updateVSpaceHSpaceBorder = function (editor) { return function (evt) { var dom = editor.dom; var rootControl = evt.control.rootControl; if (!Settings.hasAdvTab(editor)) { return; } var data = rootControl.toJSON(); var css = dom.parseStyle(data.style); rootControl.find('#vspace').value(''); rootControl.find('#hspace').value(''); css = Utils.mergeMargins(css); if (css['margin-top'] && css['margin-bottom'] || css['margin-right'] && css['margin-left']) { if (css['margin-top'] === css['margin-bottom']) { rootControl.find('#vspace').value(Utils.removePixelSuffix(css['margin-top'])); } else { rootControl.find('#vspace').value(''); } if (css['margin-right'] === css['margin-left']) { rootControl.find('#hspace').value(Utils.removePixelSuffix(css['margin-right'])); } else { rootControl.find('#hspace').value(''); } } if (css['border-width']) { rootControl.find('#border').value(Utils.removePixelSuffix(css['border-width'])); } else { rootControl.find('#border').value(''); } if (css['border-style']) { rootControl.find('#borderStyle').value(css['border-style']); } else { rootControl.find('#borderStyle').value(''); } rootControl.find('#style').value(dom.serializeStyle(dom.parseStyle(dom.serializeStyle(css)))); }; }; var updateStyle = function (editor, win) { win.find('#style').each(function (ctrl) { var value = getStyleValue(function (css) { return normalizeCss(editor, css); }, merge(defaultData(), win.toJSON())); ctrl.value(value); }); }; var makeTab = function (editor) { return { title: 'Advanced', type: 'form', pack: 'start', items: [ { label: 'Style', name: 'style', type: 'textbox', onchange: updateVSpaceHSpaceBorder(editor) }, { type: 'form', layout: 'grid', packV: 'start', columns: 2, padding: 0, defaults: { type: 'textbox', maxWidth: 50, onchange: function (evt) { updateStyle(editor, evt.control.rootControl); } }, items: [ { label: 'Vertical space', name: 'vspace' }, { label: 'Border width', name: 'border' }, { label: 'Horizontal space', name: 'hspace' }, { label: 'Border style', type: 'listbox', name: 'borderStyle', width: 90, maxWidth: 90, onselect: function (evt) { updateStyle(editor, evt.control.rootControl); }, values: [ { text: 'Select...', value: '' }, { text: 'Solid', value: 'solid' }, { text: 'Dotted', value: 'dotted' }, { text: 'Dashed', value: 'dashed' }, { text: 'Double', value: 'double' }, { text: 'Groove', value: 'groove' }, { text: 'Ridge', value: 'ridge' }, { text: 'Inset', value: 'inset' }, { text: 'Outset', value: 'outset' }, { text: 'None', value: 'none' }, { text: 'Hidden', value: 'hidden' } ] } ] } ] }; }; var AdvTab = { makeTab: makeTab }; var doSyncSize = function (widthCtrl, heightCtrl) { widthCtrl.state.set('oldVal', widthCtrl.value()); heightCtrl.state.set('oldVal', heightCtrl.value()); }; var doSizeControls = function (win, f) { var widthCtrl = win.find('#width')[0]; var heightCtrl = win.find('#height')[0]; var constrained = win.find('#constrain')[0]; if (widthCtrl && heightCtrl && constrained) { f(widthCtrl, heightCtrl, constrained.checked()); } }; var doUpdateSize = function (widthCtrl, heightCtrl, isContrained) { var oldWidth = widthCtrl.state.get('oldVal'); var oldHeight = heightCtrl.state.get('oldVal'); var newWidth = widthCtrl.value(); var newHeight = heightCtrl.value(); if (isContrained && oldWidth && oldHeight && newWidth && newHeight) { if (newWidth !== oldWidth) { newHeight = Math.round(newWidth / oldWidth * newHeight); if (!isNaN(newHeight)) { heightCtrl.value(newHeight); } } else { newWidth = Math.round(newHeight / oldHeight * newWidth); if (!isNaN(newWidth)) { widthCtrl.value(newWidth); } } } doSyncSize(widthCtrl, heightCtrl); }; var syncSize = function (win) { doSizeControls(win, doSyncSize); }; var updateSize = function (win) { doSizeControls(win, doUpdateSize); }; var createUi = function () { var recalcSize = function (evt) { updateSize(evt.control.rootControl); }; return { type: 'container', label: 'Dimensions', layout: 'flex', align: 'center', spacing: 5, items: [ { name: 'width', type: 'textbox', maxLength: 5, size: 5, onchange: recalcSize, ariaLabel: 'Width' }, { type: 'label', text: 'x' }, { name: 'height', type: 'textbox', maxLength: 5, size: 5, onchange: recalcSize, ariaLabel: 'Height' }, { name: 'constrain', type: 'checkbox', checked: true, text: 'Constrain proportions' } ] }; }; var SizeManager = { createUi: createUi, syncSize: syncSize, updateSize: updateSize }; var onSrcChange = function (evt, editor) { var srcURL, prependURL, absoluteURLPattern; var meta = evt.meta || {}; var control = evt.control; var rootControl = control.rootControl; var imageListCtrl = rootControl.find('#image-list')[0]; if (imageListCtrl) { imageListCtrl.value(editor.convertURL(control.value(), 'src')); } global$2.each(meta, function (value, key) { rootControl.find('#' + key).value(value); }); if (!meta.width && !meta.height) { srcURL = editor.convertURL(control.value(), 'src'); prependURL = Settings.getPrependUrl(editor); absoluteURLPattern = new RegExp('^(?:[a-z]+:)?//', 'i'); if (prependURL && !absoluteURLPattern.test(srcURL) && srcURL.substring(0, prependURL.length) !== prependURL) { srcURL = prependURL + srcURL; } control.value(srcURL); Utils.getImageSize(editor.documentBaseURI.toAbsolute(control.value()), function (data) { if (data.width && data.height && Settings.hasDimensions(editor)) { rootControl.find('#width').value(data.width); rootControl.find('#height').value(data.height); SizeManager.syncSize(rootControl); } }); } }; var onBeforeCall = function (evt) { evt.meta = evt.control.rootControl.toJSON(); }; var getGeneralItems = function (editor, imageListCtrl) { var generalFormItems = [ { name: 'src', type: 'filepicker', filetype: 'image', label: 'Source', autofocus: true, onchange: function (evt) { onSrcChange(evt, editor); }, onbeforecall: onBeforeCall }, imageListCtrl ]; if (Settings.hasDescription(editor)) { generalFormItems.push({ name: 'alt', type: 'textbox', label: 'Image description' }); } if (Settings.hasImageTitle(editor)) { generalFormItems.push({ name: 'title', type: 'textbox', label: 'Image Title' }); } if (Settings.hasDimensions(editor)) { generalFormItems.push(SizeManager.createUi()); } if (Settings.getClassList(editor)) { generalFormItems.push({ name: 'class', type: 'listbox', label: 'Class', values: Utils.buildListItems(Settings.getClassList(editor), function (item) { if (item.value) { item.textStyle = function () { return editor.formatter.getCssText({ inline: 'img', classes: [item.value] }); }; } }) }); } if (Settings.hasImageCaption(editor)) { generalFormItems.push({ name: 'caption', type: 'checkbox', label: 'Caption' }); } return generalFormItems; }; var makeTab$1 = function (editor, imageListCtrl) { return { title: 'General', type: 'form', items: getGeneralItems(editor, imageListCtrl) }; }; var MainTab = { makeTab: makeTab$1, getGeneralItems: getGeneralItems }; var url = function () { return Global$1.getOrDie('URL'); }; var createObjectURL = function (blob) { return url().createObjectURL(blob); }; var revokeObjectURL = function (u) { url().revokeObjectURL(u); }; var URL = { createObjectURL: createObjectURL, revokeObjectURL: revokeObjectURL }; var global$5 = tinymce.util.Tools.resolve('tinymce.ui.Factory'); function XMLHttpRequest () { var f = Global$1.getOrDie('XMLHttpRequest'); return new f(); } var noop = function () { }; var pathJoin = function (path1, path2) { if (path1) { return path1.replace(/\/$/, '') + '/' + path2.replace(/^\//, ''); } return path2; }; function Uploader (settings) { var defaultHandler = function (blobInfo, success, failure, progress) { var xhr, formData; xhr = XMLHttpRequest(); xhr.open('POST', settings.url); xhr.withCredentials = settings.credentials; xhr.upload.onprogress = function (e) { progress(e.loaded / e.total * 100); }; xhr.onerror = function () { failure('Image upload failed due to a XHR Transport error. Code: ' + xhr.status); }; xhr.onload = function () { var json; if (xhr.status < 200 || xhr.status >= 300) { failure('HTTP Error: ' + xhr.status); return; } json = JSON.parse(xhr.responseText); if (!json || typeof json.location !== 'string') { failure('Invalid JSON: ' + xhr.responseText); return; } success(pathJoin(settings.basePath, json.location)); }; formData = new domGlobals.FormData(); formData.append('file', blobInfo.blob(), blobInfo.filename()); xhr.send(formData); }; var uploadBlob = function (blobInfo, handler) { return new global$1(function (resolve, reject) { try { handler(blobInfo, resolve, reject, noop); } catch (ex) { reject(ex.message); } }); }; var isDefaultHandler = function (handler) { return handler === defaultHandler; }; var upload = function (blobInfo) { return !settings.url && isDefaultHandler(settings.handler) ? global$1.reject('Upload url missing from the settings.') : uploadBlob(blobInfo, settings.handler); }; settings = global$2.extend({ credentials: false, handler: defaultHandler }, settings); return { upload: upload }; } var onFileInput = function (editor) { return function (evt) { var Throbber = global$5.get('Throbber'); var rootControl = evt.control.rootControl; var throbber = new Throbber(rootControl.getEl()); var file = evt.control.value(); var blobUri = URL.createObjectURL(file); var uploader = Uploader({ url: Settings.getUploadUrl(editor), basePath: Settings.getUploadBasePath(editor), credentials: Settings.getUploadCredentials(editor), handler: Settings.getUploadHandler(editor) }); var finalize = function () { throbber.hide(); URL.revokeObjectURL(blobUri); }; throbber.show(); return Utils.blobToDataUri(file).then(function (dataUrl) { var blobInfo = editor.editorUpload.blobCache.create({ blob: file, blobUri: blobUri, name: file.name ? file.name.replace(/\.[^\.]+$/, '') : null, base64: dataUrl.split(',')[1] }); return uploader.upload(blobInfo).then(function (url) { var src = rootControl.find('#src'); src.value(url); rootControl.find('tabpanel')[0].activateTab(0); src.fire('change'); finalize(); return url; }); }).catch(function (err) { editor.windowManager.alert(err); finalize(); }); }; }; var acceptExts = '.jpg,.jpeg,.png,.gif'; var makeTab$2 = function (editor) { return { title: 'Upload', type: 'form', layout: 'flex', direction: 'column', align: 'stretch', padding: '20 20 20 20', items: [ { type: 'container', layout: 'flex', direction: 'column', align: 'center', spacing: 10, items: [ { text: 'Browse for an image', type: 'browsebutton', accept: acceptExts, onchange: onFileInput(editor) }, { text: 'OR', type: 'label' } ] }, { text: 'Drop an image here', type: 'dropzone', accept: acceptExts, height: 100, onchange: onFileInput(editor) } ] }; }; var UploadTab = { makeTab: makeTab$2 }; function curry(fn) { var initialArgs = []; for (var _i = 1; _i < arguments.length; _i++) { initialArgs[_i - 1] = arguments[_i]; } return function () { var restArgs = []; for (var _i = 0; _i < arguments.length; _i++) { restArgs[_i] = arguments[_i]; } var all = initialArgs.concat(restArgs); return fn.apply(null, all); }; } var submitForm = function (editor, evt) { var win = evt.control.getRoot(); SizeManager.updateSize(win); editor.undoManager.transact(function () { var data = merge(readImageDataFromSelection(editor), win.toJSON()); insertOrUpdateImage(editor, data); }); editor.editorUpload.uploadImagesAuto(); }; function Dialog (editor) { function showDialog(imageList) { var data = readImageDataFromSelection(editor); var win, imageListCtrl; if (imageList) { imageListCtrl = { type: 'listbox', label: 'Image list', name: 'image-list', values: Utils.buildListItems(imageList, function (item) { item.value = editor.convertURL(item.value || item.url, 'src'); }, [{ text: 'None', value: '' }]), value: data.src && editor.convertURL(data.src, 'src'), onselect: function (e) { var altCtrl = win.find('#alt'); if (!altCtrl.value() || e.lastControl && altCtrl.value() === e.lastControl.text()) { altCtrl.value(e.control.text()); } win.find('#src').value(e.control.value()).fire('change'); }, onPostRender: function () { imageListCtrl = this; } }; } if (Settings.hasAdvTab(editor) || Settings.hasUploadUrl(editor) || Settings.hasUploadHandler(editor)) { var body = [MainTab.makeTab(editor, imageListCtrl)]; if (Settings.hasAdvTab(editor)) { body.push(AdvTab.makeTab(editor)); } if (Settings.hasUploadUrl(editor) || Settings.hasUploadHandler(editor)) { body.push(UploadTab.makeTab(editor)); } win = editor.windowManager.open({ title: 'Insert/edit image', data: data, bodyType: 'tabpanel', body: body, onSubmit: curry(submitForm, editor) }); } else { win = editor.windowManager.open({ title: 'Insert/edit image', data: data, body: MainTab.getGeneralItems(editor, imageListCtrl), onSubmit: curry(submitForm, editor) }); } SizeManager.syncSize(win); } function open() { Utils.createImageList(editor, showDialog); } return { open: open }; } var register = function (editor) { editor.addCommand('mceImage', Dialog(editor).open); }; var Commands = { register: register }; var hasImageClass = function (node) { var className = node.attr('class'); return className && /\bimage\b/.test(className); }; var toggleContentEditableState = function (state) { return function (nodes) { var i = nodes.length, node; var toggleContentEditable = function (node) { node.attr('contenteditable', state ? 'true' : null); }; while (i--) { node = nodes[i]; if (hasImageClass(node)) { node.attr('contenteditable', state ? 'false' : null); global$2.each(node.getAll('figcaption'), toggleContentEditable); } } }; }; var setup = function (editor) { editor.on('preInit', function () { editor.parser.addNodeFilter('figure', toggleContentEditableState(true)); editor.serializer.addNodeFilter('figure', toggleContentEditableState(false)); }); }; var FilterContent = { setup: setup }; var register$1 = function (editor) { editor.addButton('image', { icon: 'image', tooltip: 'Insert/edit image', onclick: Dialog(editor).open, stateSelector: 'img:not([data-mce-object],[data-mce-placeholder]),figure.image' }); editor.addMenuItem('image', { icon: 'image', text: 'Image', onclick: Dialog(editor).open, context: 'insert', prependToContext: true }); }; var Buttons = { register: register$1 }; global.add('image', function (editor) { FilterContent.setup(editor); Buttons.register(editor); Commands.register(editor); }); function Plugin () { } return Plugin; }(window)); })(); tinymce/plugins/wplink/plugin.min.js000064400000021434147573120640013634 0ustar00!function(L){L.ui.Factory.add("WPLinkPreview",L.ui.Control.extend({url:"#",renderHtml:function(){return'

"},setURL:function(e){var t,n;this.url!==e&&(this.url=e,40<(e=""===(e="/"===(e=(e=-1!==(t=(e=-1!==(t=(e=(e=window.decodeURIComponent(e)).replace(/^(?:https?:)?\/\/(?:www\.)?/,"")).indexOf("?"))?e.slice(0,t):e).indexOf("#"))?e.slice(0,t):e).replace(/(?:index)?\.html$/,"")).charAt(e.length-1)?e.slice(0,-1):e)?this.url:e).length&&-1!==(t=e.indexOf("/"))&&-1!==(n=e.lastIndexOf("/"))&&n!==t&&(t+e.length-n<40&&(n=-(40-(t+1))),e=e.slice(0,t+1)+"\u2026"+e.slice(n)),L.$(this.getEl().firstChild).attr("href",this.url).text(e))}})),L.ui.Factory.add("WPLinkInput",L.ui.Control.extend({renderHtml:function(){return''},setURL:function(e){this.getEl().firstChild.nextSibling.value=e},getURL:function(){return L.trim(this.getEl().firstChild.nextSibling.value)},getLinkText:function(){var e=this.getEl().firstChild.nextSibling.nextSibling.value;return L.trim(e)?e.replace(/[\r\n\t ]+/g," "):""},reset:function(){var e=this.getEl().firstChild.nextSibling;e.value="",e.nextSibling.value=""}})),L.PluginManager.add("wplink",function(l){var a,r,d,c,i,n,t,p=window.jQuery,o=/^(mailto:)?[a-z0-9._%+-]+@[a-z0-9][a-z0-9.-]*\.[a-z]{2,63}$/i,s=/^https?:\/\/([^\s/?.#-][^\s\/?.#]*\.?)+(\/[^\s"]*)?$/i,u=/^https?:\/\/[^\/]+\.[^\/]+($|\/)/i,w=void 0!==window.wp&&window.wp.a11y&&window.wp.a11y.speak?window.wp.a11y.speak:function(){},k=!1,m=window.wp.i18n.__,f=window.wp.i18n._n,h=window.wp.i18n.sprintf;function _(){l.$("a").each(function(e,t){var n=l.$(t);"_wp_link_placeholder"===n.attr("href")?l.dom.remove(t,!0):n.attr("data-wplink-edit")&&n.attr("data-wplink-edit",null)})}function v(e,i){return e.replace(/(]+>)([\s\S]*?)<\/a>/g,function(e,t,n){return-1"})}function g(e){var e=l.$(e),t=e.attr("href");t&&void 0!==p&&(k=!1,!/^http/i.test(t)||s.test(t)&&u.test(t)?e.removeAttr("data-wplink-url-error"):(k=!0,e.attr("data-wplink-url-error","true"),w(l.translate("Warning: the link has been inserted but may have errors. Please test it."),"assertive")))}return l.on("preinit",function(){var e;l.wp&&l.wp._createToolbar&&(a=l.wp._createToolbar(["wp_link_preview","wp_link_edit","wp_link_remove"],!0),e=["wp_link_input","wp_link_apply"],void 0!==window.wpLink&&e.push("wp_link_advanced"),(r=l.wp._createToolbar(e,!0)).on("show",function(){void 0!==window.wpLink&&window.wpLink.modalOpen||window.setTimeout(function(){var e=r.$el.find("input.ui-autocomplete-input")[0],t=i&&(i.textContent||i.innerText);e&&(!e.value&&t&&void 0!==window.wpLink&&(e.value=window.wpLink.getUrlFromSelection(t)),n||(e.focus(),e.select()))})}),r.on("hide",function(){r.scrolling||l.execCommand("wp_link_cancel")}))}),l.addCommand("WP_Link",function(){var e,t,n;L.Env.ie&&L.Env.ie<10&&void 0!==window.wpLink?window.wpLink.open(l.id):(t=l.selection.getStart(),(n=l.dom.getParent(t,"a[href]"))||(e=l.selection.getContent({format:"raw"}))&&-1!==e.indexOf("")&&(n=(e=e.match(/href="([^">]+)"/))&&e[1]?l.$('a[href="'+e[1]+'"]',t)[0]:n)&&l.selection.select(n),i=n,r.tempHide=!1,i||(_(),l.execCommand("mceInsertLink",!1,{href:"_wp_link_placeholder"}),i=l.$('a[href="_wp_link_placeholder"]')[0],l.nodeChanged()),l.dom.setAttribs(i,{"data-wplink-edit":!0}))}),l.addCommand("wp_link_apply",function(){if(!r.scrolling){var e,t;if(i){e=c.getURL(),t=c.getLinkText(),l.focus();var n=document.createElement("a");if(n.href=e,!(e="javascript:"!==n.protocol&&"data:"!==n.protocol?e:""))return void l.dom.remove(i,!0);/^(?:[a-z]+:|#|\?|\.|\/)/.test(e)||o.test(e)||(e="http://"+e),l.dom.setAttribs(i,{href:e,"data-wplink-edit":null}),L.trim(i.innerHTML)||l.$(i).text(t||e),g(i)}c.reset(),l.nodeChanged(),void 0===window.wpLinkL10n||k||w(window.wpLinkL10n.linkInserted)}}),l.addCommand("wp_link_cancel",function(){c.reset(),r.tempHide||_()}),l.addCommand("wp_unlink",function(){l.execCommand("unlink"),r.tempHide=!1,l.execCommand("wp_link_cancel")}),l.addShortcut("access+a","","WP_Link"),l.addShortcut("access+s","","wp_unlink"),l.addShortcut("meta+k","","WP_Link"),l.addButton("link",{icon:"link",tooltip:"Insert/edit link",cmd:"WP_Link",stateSelector:"a[href]"}),l.addButton("unlink",{icon:"unlink",tooltip:"Remove link",cmd:"unlink"}),l.addMenuItem("link",{icon:"link",text:"Insert/edit link",cmd:"WP_Link",stateSelector:"a[href]",context:"insert",prependToContext:!0}),l.on("pastepreprocess",function(e){var t=e.content,n=/^(?:https?:)?\/\/\S+$/i;l.selection.isCollapsed()||n.test(l.selection.getContent())||(t=t.replace(/<[^>]+>/g,""),t=L.trim(t),n.test(t)&&(l.execCommand("mceInsertLink",!1,{href:l.dom.decode(t)}),e.preventDefault()))}),l.on("savecontent",function(e){e.content=v(e.content,!0)}),l.on("BeforeAddUndo",function(e){e.lastLevel&&e.lastLevel.content&&e.level.content&&e.lastLevel.content===v(e.level.content)&&e.preventDefault()}),l.on("keydown",function(e){27===e.keyCode&&l.execCommand("wp_link_cancel"),e.altKey||L.Env.mac&&(!e.metaKey||e.ctrlKey)||!L.Env.mac&&!e.ctrlKey||89!==e.keyCode&&90!==e.keyCode||(n=!0,window.clearTimeout(t),t=window.setTimeout(function(){n=!1},500))}),l.addButton("wp_link_preview",{type:"WPLinkPreview",onPostRender:function(){d=this}}),l.addButton("wp_link_input",{type:"WPLinkInput",onPostRender:function(){var n,i,o,a=this.getEl(),e=a.firstChild.nextSibling;c=this,p&&p.ui&&p.ui.autocomplete&&((n=p(e)).on("keydown",function(){n.removeAttr("aria-activedescendant")}).autocomplete({source:function(e,t){if(o===e.term)t(i);else{if(/^https?:/.test(e.term)||-1!==e.term.indexOf("."))return t();p.post(window.ajaxurl,{action:"wp-link-ajax",page:1,search:e.term,_ajax_linking_nonce:p("#_ajax_linking_nonce").val()},function(e){t(i=e)},"json"),o=e.term}},focus:function(e,t){n.attr("aria-activedescendant","mce-wp-autocomplete-"+t.item.ID),e.preventDefault()},select:function(e,t){return n.val(t.item.permalink),p(a.firstChild.nextSibling.nextSibling).val(t.item.title),9===e.keyCode&&void 0!==window.wpLinkL10n&&w(window.wpLinkL10n.linkSelected),!1},open:function(){n.attr("aria-expanded","true"),r.blockHide=!0},close:function(){n.attr("aria-expanded","false"),r.blockHide=!1},minLength:2,position:{my:"left top+2"},messages:{noResults:m("No results found."),results:function(e){return h(f("%d result found. Use up and down arrow keys to navigate.","%d results found. Use up and down arrow keys to navigate.",e),e)}}}).autocomplete("instance")._renderItem=function(e,t){var n=void 0!==window.wpLinkL10n?window.wpLinkL10n.noTitle:"",n=t.title||n;return p('
  • ').append(""+n+' '+t.info+"").appendTo(e)},n.attr({role:"combobox","aria-autocomplete":"list","aria-expanded":"false","aria-owns":n.autocomplete("widget").attr("id")}).on("focus",function(){var e=n.val();e&&!/^https?:/.test(e)&&n.autocomplete("search")}).autocomplete("widget").addClass("wplink-autocomplete").attr("role","listbox").removeAttr("tabindex").on("menufocus",function(e,t){t.item.attr("aria-selected","true")}).on("menublur",function(){p(this).find('[aria-selected="true"]').removeAttr("aria-selected")})),L.$(e).on("keydown",function(e){13===e.keyCode&&(l.execCommand("wp_link_apply"),e.preventDefault())})}}),l.on("wptoolbar",function(e){var t,n,i,o=l.dom.getParent(e.element,"a");void 0!==window.wpLink&&window.wpLink.modalOpen?r.tempHide=!0:(r.tempHide=!1,o?(n=(t=l.$(o)).attr("href"),i=t.attr("data-wplink-edit"),"_wp_link_placeholder"===n||i?("_wp_link_placeholder"===n||c.getURL()||c.setURL(n),e.element=o,e.toolbar=r):n&&!t.find("img").length&&(d.setURL(n),e.element=o,e.toolbar=a,"true"===t.attr("data-wplink-url-error")?a.$el.find(".wp-link-preview a").addClass("wplink-url-error"):(a.$el.find(".wp-link-preview a").removeClass("wplink-url-error"),k=!1))):r.visible()&&l.execCommand("wp_link_cancel"))}),l.addButton("wp_link_edit",{tooltip:"Edit|button",icon:"dashicon dashicons-edit",cmd:"WP_Link"}),l.addButton("wp_link_remove",{tooltip:"Remove link",icon:"dashicon dashicons-editor-unlink",cmd:"wp_unlink"}),l.addButton("wp_link_advanced",{tooltip:"Link options",icon:"dashicon dashicons-admin-generic",onclick:function(){var e,t;void 0!==window.wpLink&&(e=c.getURL()||null,t=c.getLinkText()||null,window.wpLink.open(l.id,e,t),r.tempHide=!0,r.hide())}}),l.addButton("wp_link_apply",{tooltip:"Apply",icon:"dashicon dashicons-editor-break",cmd:"wp_link_apply",classes:"widget btn primary"}),{close:function(){r.tempHide=!1,l.execCommand("wp_link_cancel")},checkLink:g}})}(window.tinymce);tinymce/plugins/wplink/plugin.js000064400000042606147573120640013056 0ustar00( function( tinymce ) { tinymce.ui.Factory.add( 'WPLinkPreview', tinymce.ui.Control.extend( { url: '#', renderHtml: function() { return ( '' ); }, setURL: function( url ) { var index, lastIndex; if ( this.url !== url ) { this.url = url; url = window.decodeURIComponent( url ); url = url.replace( /^(?:https?:)?\/\/(?:www\.)?/, '' ); if ( ( index = url.indexOf( '?' ) ) !== -1 ) { url = url.slice( 0, index ); } if ( ( index = url.indexOf( '#' ) ) !== -1 ) { url = url.slice( 0, index ); } url = url.replace( /(?:index)?\.html$/, '' ); if ( url.charAt( url.length - 1 ) === '/' ) { url = url.slice( 0, -1 ); } // If nothing's left (maybe the URL was just a fragment), use the whole URL. if ( url === '' ) { url = this.url; } // If the URL is longer that 40 chars, concatenate the beginning (after the domain) and ending with '...'. if ( url.length > 40 && ( index = url.indexOf( '/' ) ) !== -1 && ( lastIndex = url.lastIndexOf( '/' ) ) !== -1 && lastIndex !== index ) { // If the beginning + ending are shorter that 40 chars, show more of the ending. if ( index + url.length - lastIndex < 40 ) { lastIndex = -( 40 - ( index + 1 ) ); } url = url.slice( 0, index + 1 ) + '\u2026' + url.slice( lastIndex ); } tinymce.$( this.getEl().firstChild ).attr( 'href', this.url ).text( url ); } } } ) ); tinymce.ui.Factory.add( 'WPLinkInput', tinymce.ui.Control.extend( { renderHtml: function() { return ( '' ); }, setURL: function( url ) { this.getEl().firstChild.nextSibling.value = url; }, getURL: function() { return tinymce.trim( this.getEl().firstChild.nextSibling.value ); }, getLinkText: function() { var text = this.getEl().firstChild.nextSibling.nextSibling.value; if ( ! tinymce.trim( text ) ) { return ''; } return text.replace( /[\r\n\t ]+/g, ' ' ); }, reset: function() { var urlInput = this.getEl().firstChild.nextSibling; urlInput.value = ''; urlInput.nextSibling.value = ''; } } ) ); tinymce.PluginManager.add( 'wplink', function( editor ) { var toolbar; var editToolbar; var previewInstance; var inputInstance; var linkNode; var doingUndoRedo; var doingUndoRedoTimer; var $ = window.jQuery; var emailRegex = /^(mailto:)?[a-z0-9._%+-]+@[a-z0-9][a-z0-9.-]*\.[a-z]{2,63}$/i; var urlRegex1 = /^https?:\/\/([^\s/?.#-][^\s\/?.#]*\.?)+(\/[^\s"]*)?$/i; var urlRegex2 = /^https?:\/\/[^\/]+\.[^\/]+($|\/)/i; var speak = ( typeof window.wp !== 'undefined' && window.wp.a11y && window.wp.a11y.speak ) ? window.wp.a11y.speak : function() {}; var hasLinkError = false; var __ = window.wp.i18n.__; var _n = window.wp.i18n._n; var sprintf = window.wp.i18n.sprintf; function getSelectedLink() { var href, html, node = editor.selection.getStart(), link = editor.dom.getParent( node, 'a[href]' ); if ( ! link ) { html = editor.selection.getContent({ format: 'raw' }); if ( html && html.indexOf( '' ) !== -1 ) { href = html.match( /href="([^">]+)"/ ); if ( href && href[1] ) { link = editor.$( 'a[href="' + href[1] + '"]', node )[0]; } if ( link ) { editor.selection.select( link ); } } } return link; } function removePlaceholders() { editor.$( 'a' ).each( function( i, element ) { var $element = editor.$( element ); if ( $element.attr( 'href' ) === '_wp_link_placeholder' ) { editor.dom.remove( element, true ); } else if ( $element.attr( 'data-wplink-edit' ) ) { $element.attr( 'data-wplink-edit', null ); } }); } function removePlaceholderStrings( content, dataAttr ) { return content.replace( /(]+>)([\s\S]*?)<\/a>/g, function( all, tag, text ) { if ( tag.indexOf( ' href="_wp_link_placeholder"' ) > -1 ) { return text; } if ( dataAttr ) { tag = tag.replace( / data-wplink-edit="true"/g, '' ); } tag = tag.replace( / data-wplink-url-error="true"/g, '' ); return tag + text + ''; }); } function checkLink( node ) { var $link = editor.$( node ); var href = $link.attr( 'href' ); if ( ! href || typeof $ === 'undefined' ) { return; } hasLinkError = false; if ( /^http/i.test( href ) && ( ! urlRegex1.test( href ) || ! urlRegex2.test( href ) ) ) { hasLinkError = true; $link.attr( 'data-wplink-url-error', 'true' ); speak( editor.translate( 'Warning: the link has been inserted but may have errors. Please test it.' ), 'assertive' ); } else { $link.removeAttr( 'data-wplink-url-error' ); } } editor.on( 'preinit', function() { if ( editor.wp && editor.wp._createToolbar ) { toolbar = editor.wp._createToolbar( [ 'wp_link_preview', 'wp_link_edit', 'wp_link_remove' ], true ); var editButtons = [ 'wp_link_input', 'wp_link_apply' ]; if ( typeof window.wpLink !== 'undefined' ) { editButtons.push( 'wp_link_advanced' ); } editToolbar = editor.wp._createToolbar( editButtons, true ); editToolbar.on( 'show', function() { if ( typeof window.wpLink === 'undefined' || ! window.wpLink.modalOpen ) { window.setTimeout( function() { var element = editToolbar.$el.find( 'input.ui-autocomplete-input' )[0], selection = linkNode && ( linkNode.textContent || linkNode.innerText ); if ( element ) { if ( ! element.value && selection && typeof window.wpLink !== 'undefined' ) { element.value = window.wpLink.getUrlFromSelection( selection ); } if ( ! doingUndoRedo ) { element.focus(); element.select(); } } } ); } } ); editToolbar.on( 'hide', function() { if ( ! editToolbar.scrolling ) { editor.execCommand( 'wp_link_cancel' ); } } ); } } ); editor.addCommand( 'WP_Link', function() { if ( tinymce.Env.ie && tinymce.Env.ie < 10 && typeof window.wpLink !== 'undefined' ) { window.wpLink.open( editor.id ); return; } linkNode = getSelectedLink(); editToolbar.tempHide = false; if ( ! linkNode ) { removePlaceholders(); editor.execCommand( 'mceInsertLink', false, { href: '_wp_link_placeholder' } ); linkNode = editor.$( 'a[href="_wp_link_placeholder"]' )[0]; editor.nodeChanged(); } editor.dom.setAttribs( linkNode, { 'data-wplink-edit': true } ); } ); editor.addCommand( 'wp_link_apply', function() { if ( editToolbar.scrolling ) { return; } var href, text; if ( linkNode ) { href = inputInstance.getURL(); text = inputInstance.getLinkText(); editor.focus(); var parser = document.createElement( 'a' ); parser.href = href; if ( 'javascript:' === parser.protocol || 'data:' === parser.protocol ) { // jshint ignore:line href = ''; } if ( ! href ) { editor.dom.remove( linkNode, true ); return; } if ( ! /^(?:[a-z]+:|#|\?|\.|\/)/.test( href ) && ! emailRegex.test( href ) ) { href = 'http://' + href; } editor.dom.setAttribs( linkNode, { href: href, 'data-wplink-edit': null } ); if ( ! tinymce.trim( linkNode.innerHTML ) ) { editor.$( linkNode ).text( text || href ); } checkLink( linkNode ); } inputInstance.reset(); editor.nodeChanged(); // Audible confirmation message when a link has been inserted in the Editor. if ( typeof window.wpLinkL10n !== 'undefined' && ! hasLinkError ) { speak( window.wpLinkL10n.linkInserted ); } } ); editor.addCommand( 'wp_link_cancel', function() { inputInstance.reset(); if ( ! editToolbar.tempHide ) { removePlaceholders(); } } ); editor.addCommand( 'wp_unlink', function() { editor.execCommand( 'unlink' ); editToolbar.tempHide = false; editor.execCommand( 'wp_link_cancel' ); } ); // WP default shortcuts. editor.addShortcut( 'access+a', '', 'WP_Link' ); editor.addShortcut( 'access+s', '', 'wp_unlink' ); // The "de-facto standard" shortcut, see #27305. editor.addShortcut( 'meta+k', '', 'WP_Link' ); editor.addButton( 'link', { icon: 'link', tooltip: 'Insert/edit link', cmd: 'WP_Link', stateSelector: 'a[href]' }); editor.addButton( 'unlink', { icon: 'unlink', tooltip: 'Remove link', cmd: 'unlink' }); editor.addMenuItem( 'link', { icon: 'link', text: 'Insert/edit link', cmd: 'WP_Link', stateSelector: 'a[href]', context: 'insert', prependToContext: true }); editor.on( 'pastepreprocess', function( event ) { var pastedStr = event.content, regExp = /^(?:https?:)?\/\/\S+$/i; if ( ! editor.selection.isCollapsed() && ! regExp.test( editor.selection.getContent() ) ) { pastedStr = pastedStr.replace( /<[^>]+>/g, '' ); pastedStr = tinymce.trim( pastedStr ); if ( regExp.test( pastedStr ) ) { editor.execCommand( 'mceInsertLink', false, { href: editor.dom.decode( pastedStr ) } ); event.preventDefault(); } } } ); // Remove any remaining placeholders on saving. editor.on( 'savecontent', function( event ) { event.content = removePlaceholderStrings( event.content, true ); }); // Prevent adding undo levels on inserting link placeholder. editor.on( 'BeforeAddUndo', function( event ) { if ( event.lastLevel && event.lastLevel.content && event.level.content && event.lastLevel.content === removePlaceholderStrings( event.level.content ) ) { event.preventDefault(); } }); // When doing undo and redo with keyboard shortcuts (Ctrl|Cmd+Z, Ctrl|Cmd+Shift+Z, Ctrl|Cmd+Y), // set a flag to not focus the inline dialog. The editor has to remain focused so the users can do consecutive undo/redo. editor.on( 'keydown', function( event ) { if ( event.keyCode === 27 ) { // Esc editor.execCommand( 'wp_link_cancel' ); } if ( event.altKey || ( tinymce.Env.mac && ( ! event.metaKey || event.ctrlKey ) ) || ( ! tinymce.Env.mac && ! event.ctrlKey ) ) { return; } if ( event.keyCode === 89 || event.keyCode === 90 ) { // Y or Z doingUndoRedo = true; window.clearTimeout( doingUndoRedoTimer ); doingUndoRedoTimer = window.setTimeout( function() { doingUndoRedo = false; }, 500 ); } } ); editor.addButton( 'wp_link_preview', { type: 'WPLinkPreview', onPostRender: function() { previewInstance = this; } } ); editor.addButton( 'wp_link_input', { type: 'WPLinkInput', onPostRender: function() { var element = this.getEl(), input = element.firstChild.nextSibling, $input, cache, last; inputInstance = this; if ( $ && $.ui && $.ui.autocomplete ) { $input = $( input ); $input.on( 'keydown', function() { $input.removeAttr( 'aria-activedescendant' ); } ) .autocomplete( { source: function( request, response ) { if ( last === request.term ) { response( cache ); return; } if ( /^https?:/.test( request.term ) || request.term.indexOf( '.' ) !== -1 ) { return response(); } $.post( window.ajaxurl, { action: 'wp-link-ajax', page: 1, search: request.term, _ajax_linking_nonce: $( '#_ajax_linking_nonce' ).val() }, function( data ) { cache = data; response( data ); }, 'json' ); last = request.term; }, focus: function( event, ui ) { $input.attr( 'aria-activedescendant', 'mce-wp-autocomplete-' + ui.item.ID ); /* * Don't empty the URL input field, when using the arrow keys to * highlight items. See api.jqueryui.com/autocomplete/#event-focus */ event.preventDefault(); }, select: function( event, ui ) { $input.val( ui.item.permalink ); $( element.firstChild.nextSibling.nextSibling ).val( ui.item.title ); if ( 9 === event.keyCode && typeof window.wpLinkL10n !== 'undefined' ) { // Audible confirmation message when a link has been selected. speak( window.wpLinkL10n.linkSelected ); } return false; }, open: function() { $input.attr( 'aria-expanded', 'true' ); editToolbar.blockHide = true; }, close: function() { $input.attr( 'aria-expanded', 'false' ); editToolbar.blockHide = false; }, minLength: 2, position: { my: 'left top+2' }, messages: { noResults: __( 'No results found.' ) , results: function( number ) { return sprintf( /* translators: %d: Number of search results found. */ _n( '%d result found. Use up and down arrow keys to navigate.', '%d results found. Use up and down arrow keys to navigate.', number ), number ); } } } ).autocomplete( 'instance' )._renderItem = function( ul, item ) { var fallbackTitle = ( typeof window.wpLinkL10n !== 'undefined' ) ? window.wpLinkL10n.noTitle : '', title = item.title ? item.title : fallbackTitle; return $( '
  • ' ) .append( '' + title + ' ' + item.info + '' ) .appendTo( ul ); }; $input.attr( { 'role': 'combobox', 'aria-autocomplete': 'list', 'aria-expanded': 'false', 'aria-owns': $input.autocomplete( 'widget' ).attr( 'id' ) } ) .on( 'focus', function() { var inputValue = $input.val(); /* * Don't trigger a search if the URL field already has a link or is empty. * Also, avoids screen readers announce `No search results`. */ if ( inputValue && ! /^https?:/.test( inputValue ) ) { $input.autocomplete( 'search' ); } } ) // Returns a jQuery object containing the menu element. .autocomplete( 'widget' ) .addClass( 'wplink-autocomplete' ) .attr( 'role', 'listbox' ) .removeAttr( 'tabindex' ) // Remove the `tabindex=0` attribute added by jQuery UI. /* * Looks like Safari and VoiceOver need an `aria-selected` attribute. See ticket #33301. * The `menufocus` and `menublur` events are the same events used to add and remove * the `ui-state-focus` CSS class on the menu items. See jQuery UI Menu Widget. */ .on( 'menufocus', function( event, ui ) { ui.item.attr( 'aria-selected', 'true' ); }) .on( 'menublur', function() { /* * The `menublur` event returns an object where the item is `null` * so we need to find the active item with other means. */ $( this ).find( '[aria-selected="true"]' ).removeAttr( 'aria-selected' ); }); } tinymce.$( input ).on( 'keydown', function( event ) { if ( event.keyCode === 13 ) { editor.execCommand( 'wp_link_apply' ); event.preventDefault(); } } ); } } ); editor.on( 'wptoolbar', function( event ) { var linkNode = editor.dom.getParent( event.element, 'a' ), $linkNode, href, edit; if ( typeof window.wpLink !== 'undefined' && window.wpLink.modalOpen ) { editToolbar.tempHide = true; return; } editToolbar.tempHide = false; if ( linkNode ) { $linkNode = editor.$( linkNode ); href = $linkNode.attr( 'href' ); edit = $linkNode.attr( 'data-wplink-edit' ); if ( href === '_wp_link_placeholder' || edit ) { if ( href !== '_wp_link_placeholder' && ! inputInstance.getURL() ) { inputInstance.setURL( href ); } event.element = linkNode; event.toolbar = editToolbar; } else if ( href && ! $linkNode.find( 'img' ).length ) { previewInstance.setURL( href ); event.element = linkNode; event.toolbar = toolbar; if ( $linkNode.attr( 'data-wplink-url-error' ) === 'true' ) { toolbar.$el.find( '.wp-link-preview a' ).addClass( 'wplink-url-error' ); } else { toolbar.$el.find( '.wp-link-preview a' ).removeClass( 'wplink-url-error' ); hasLinkError = false; } } } else if ( editToolbar.visible() ) { editor.execCommand( 'wp_link_cancel' ); } } ); editor.addButton( 'wp_link_edit', { tooltip: 'Edit|button', // '|button' is not displayed, only used for context. icon: 'dashicon dashicons-edit', cmd: 'WP_Link' } ); editor.addButton( 'wp_link_remove', { tooltip: 'Remove link', icon: 'dashicon dashicons-editor-unlink', cmd: 'wp_unlink' } ); editor.addButton( 'wp_link_advanced', { tooltip: 'Link options', icon: 'dashicon dashicons-admin-generic', onclick: function() { if ( typeof window.wpLink !== 'undefined' ) { var url = inputInstance.getURL() || null, text = inputInstance.getLinkText() || null; window.wpLink.open( editor.id, url, text ); editToolbar.tempHide = true; editToolbar.hide(); } } } ); editor.addButton( 'wp_link_apply', { tooltip: 'Apply', icon: 'dashicon dashicons-editor-break', cmd: 'wp_link_apply', classes: 'widget btn primary' } ); return { close: function() { editToolbar.tempHide = false; editor.execCommand( 'wp_link_cancel' ); }, checkLink: checkLink }; } ); } )( window.tinymce ); tinymce/plugins/charmap/plugin.min.js000064400000020631147573120640013741 0ustar00!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),i=function(e,t){return e.fire("insertCustomChar",{chr:t})},l=function(e,t){var a=i(e,t).chr;e.execCommand("mceInsertContent",!1,a)},a=tinymce.util.Tools.resolve("tinymce.util.Tools"),r=function(e){return e.settings.charmap},n=function(e){return e.settings.charmap_append},o=a.isArray,c=function(e){return o(e)?[].concat((t=e,a.grep(t,function(e){return o(e)&&2===e.length}))):"function"==typeof e?e():[];var t},s=function(e){return function(e,t){var a=r(e);a&&(t=c(a));var i=n(e);return i?[].concat(t).concat(c(i)):t}(e,[["160","no-break space"],["173","soft hyphen"],["34","quotation mark"],["162","cent sign"],["8364","euro sign"],["163","pound sign"],["165","yen sign"],["169","copyright sign"],["174","registered sign"],["8482","trade mark sign"],["8240","per mille sign"],["181","micro sign"],["183","middle dot"],["8226","bullet"],["8230","three dot leader"],["8242","minutes / feet"],["8243","seconds / inches"],["167","section sign"],["182","paragraph sign"],["223","sharp s / ess-zed"],["8249","single left-pointing angle quotation mark"],["8250","single right-pointing angle quotation mark"],["171","left pointing guillemet"],["187","right pointing guillemet"],["8216","left single quotation mark"],["8217","right single quotation mark"],["8220","left double quotation mark"],["8221","right double quotation mark"],["8218","single low-9 quotation mark"],["8222","double low-9 quotation mark"],["60","less-than sign"],["62","greater-than sign"],["8804","less-than or equal to"],["8805","greater-than or equal to"],["8211","en dash"],["8212","em dash"],["175","macron"],["8254","overline"],["164","currency sign"],["166","broken bar"],["168","diaeresis"],["161","inverted exclamation mark"],["191","turned question mark"],["710","circumflex accent"],["732","small tilde"],["176","degree sign"],["8722","minus sign"],["177","plus-minus sign"],["247","division sign"],["8260","fraction slash"],["215","multiplication sign"],["185","superscript one"],["178","superscript two"],["179","superscript three"],["188","fraction one quarter"],["189","fraction one half"],["190","fraction three quarters"],["402","function / florin"],["8747","integral"],["8721","n-ary sumation"],["8734","infinity"],["8730","square root"],["8764","similar to"],["8773","approximately equal to"],["8776","almost equal to"],["8800","not equal to"],["8801","identical to"],["8712","element of"],["8713","not an element of"],["8715","contains as member"],["8719","n-ary product"],["8743","logical and"],["8744","logical or"],["172","not sign"],["8745","intersection"],["8746","union"],["8706","partial differential"],["8704","for all"],["8707","there exists"],["8709","diameter"],["8711","backward difference"],["8727","asterisk operator"],["8733","proportional to"],["8736","angle"],["180","acute accent"],["184","cedilla"],["170","feminine ordinal indicator"],["186","masculine ordinal indicator"],["8224","dagger"],["8225","double dagger"],["192","A - grave"],["193","A - acute"],["194","A - circumflex"],["195","A - tilde"],["196","A - diaeresis"],["197","A - ring above"],["256","A - macron"],["198","ligature AE"],["199","C - cedilla"],["200","E - grave"],["201","E - acute"],["202","E - circumflex"],["203","E - diaeresis"],["274","E - macron"],["204","I - grave"],["205","I - acute"],["206","I - circumflex"],["207","I - diaeresis"],["298","I - macron"],["208","ETH"],["209","N - tilde"],["210","O - grave"],["211","O - acute"],["212","O - circumflex"],["213","O - tilde"],["214","O - diaeresis"],["216","O - slash"],["332","O - macron"],["338","ligature OE"],["352","S - caron"],["217","U - grave"],["218","U - acute"],["219","U - circumflex"],["220","U - diaeresis"],["362","U - macron"],["221","Y - acute"],["376","Y - diaeresis"],["562","Y - macron"],["222","THORN"],["224","a - grave"],["225","a - acute"],["226","a - circumflex"],["227","a - tilde"],["228","a - diaeresis"],["229","a - ring above"],["257","a - macron"],["230","ligature ae"],["231","c - cedilla"],["232","e - grave"],["233","e - acute"],["234","e - circumflex"],["235","e - diaeresis"],["275","e - macron"],["236","i - grave"],["237","i - acute"],["238","i - circumflex"],["239","i - diaeresis"],["299","i - macron"],["240","eth"],["241","n - tilde"],["242","o - grave"],["243","o - acute"],["244","o - circumflex"],["245","o - tilde"],["246","o - diaeresis"],["248","o slash"],["333","o macron"],["339","ligature oe"],["353","s - caron"],["249","u - grave"],["250","u - acute"],["251","u - circumflex"],["252","u - diaeresis"],["363","u - macron"],["253","y - acute"],["254","thorn"],["255","y - diaeresis"],["563","y - macron"],["913","Alpha"],["914","Beta"],["915","Gamma"],["916","Delta"],["917","Epsilon"],["918","Zeta"],["919","Eta"],["920","Theta"],["921","Iota"],["922","Kappa"],["923","Lambda"],["924","Mu"],["925","Nu"],["926","Xi"],["927","Omicron"],["928","Pi"],["929","Rho"],["931","Sigma"],["932","Tau"],["933","Upsilon"],["934","Phi"],["935","Chi"],["936","Psi"],["937","Omega"],["945","alpha"],["946","beta"],["947","gamma"],["948","delta"],["949","epsilon"],["950","zeta"],["951","eta"],["952","theta"],["953","iota"],["954","kappa"],["955","lambda"],["956","mu"],["957","nu"],["958","xi"],["959","omicron"],["960","pi"],["961","rho"],["962","final sigma"],["963","sigma"],["964","tau"],["965","upsilon"],["966","phi"],["967","chi"],["968","psi"],["969","omega"],["8501","alef symbol"],["982","pi symbol"],["8476","real part symbol"],["978","upsilon - hook symbol"],["8472","Weierstrass p"],["8465","imaginary part"],["8592","leftwards arrow"],["8593","upwards arrow"],["8594","rightwards arrow"],["8595","downwards arrow"],["8596","left right arrow"],["8629","carriage return"],["8656","leftwards double arrow"],["8657","upwards double arrow"],["8658","rightwards double arrow"],["8659","downwards double arrow"],["8660","left right double arrow"],["8756","therefore"],["8834","subset of"],["8835","superset of"],["8836","not a subset of"],["8838","subset of or equal to"],["8839","superset of or equal to"],["8853","circled plus"],["8855","circled times"],["8869","perpendicular"],["8901","dot operator"],["8968","left ceiling"],["8969","right ceiling"],["8970","left floor"],["8971","right floor"],["9001","left-pointing angle bracket"],["9002","right-pointing angle bracket"],["9674","lozenge"],["9824","black spade suit"],["9827","black club suit"],["9829","black heart suit"],["9830","black diamond suit"],["8194","en space"],["8195","em space"],["8201","thin space"],["8204","zero width non-joiner"],["8205","zero width joiner"],["8206","left-to-right mark"],["8207","right-to-left mark"]])},t=function(t){return{getCharMap:function(){return s(t)},insertChar:function(e){l(t,e)}}},u=function(e){var t,a,i,r=Math.min(e.length,25),n=Math.ceil(e.length/r);for(t='',i=0;i",a=0;a
    '+s+"
    "}else t+="
    "}return t+=""},d=function(e){for(;e;){if("TD"===e.nodeName)return e;e=e.parentNode}},m=function(n){var o,e={type:"container",html:u(s(n)),onclick:function(e){var t=e.target;if(/^(TD|DIV)$/.test(t.nodeName)){var a=d(t).firstChild;if(a&&a.hasAttribute("data-chr")){var i=a.getAttribute("data-chr"),r=parseInt(i,10);isNaN(r)||l(n,String.fromCharCode(r)),e.ctrlKey||o.close()}}},onmouseover:function(e){var t=d(e.target);t&&t.firstChild?(o.find("#preview").text(t.firstChild.firstChild.data),o.find("#previewTitle").text(t.title)):(o.find("#preview").text(" "),o.find("#previewTitle").text(" "))}};o=n.windowManager.open({title:"Special character",spacing:10,padding:10,items:[e,{type:"container",layout:"flex",direction:"column",align:"center",spacing:5,minWidth:160,minHeight:160,items:[{type:"label",name:"preview",text:" ",style:"font-size: 40px; text-align: center",border:1,minWidth:140,minHeight:80},{type:"spacer",minHeight:20},{type:"label",name:"previewTitle",text:" ",style:"white-space: pre-wrap;",border:1,minWidth:140}]}],buttons:[{text:"Close",onclick:function(){o.close()}}]})},g=function(e){e.addCommand("mceShowCharmap",function(){m(e)})},p=function(e){e.addButton("charmap",{icon:"charmap",tooltip:"Special character",cmd:"mceShowCharmap"}),e.addMenuItem("charmap",{icon:"charmap",text:"Special character",cmd:"mceShowCharmap",context:"insert"})};e.add("charmap",function(e){return g(e),p(e),t(e)})}();tinymce/plugins/charmap/plugin.js000064400000055252147573120640013166 0ustar00(function () { var charmap = (function () { 'use strict'; var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); var fireInsertCustomChar = function (editor, chr) { return editor.fire('insertCustomChar', { chr: chr }); }; var Events = { fireInsertCustomChar: fireInsertCustomChar }; var insertChar = function (editor, chr) { var evtChr = Events.fireInsertCustomChar(editor, chr).chr; editor.execCommand('mceInsertContent', false, evtChr); }; var Actions = { insertChar: insertChar }; var global$1 = tinymce.util.Tools.resolve('tinymce.util.Tools'); var getCharMap = function (editor) { return editor.settings.charmap; }; var getCharMapAppend = function (editor) { return editor.settings.charmap_append; }; var Settings = { getCharMap: getCharMap, getCharMapAppend: getCharMapAppend }; var isArray = global$1.isArray; var getDefaultCharMap = function () { return [ [ '160', 'no-break space' ], [ '173', 'soft hyphen' ], [ '34', 'quotation mark' ], [ '162', 'cent sign' ], [ '8364', 'euro sign' ], [ '163', 'pound sign' ], [ '165', 'yen sign' ], [ '169', 'copyright sign' ], [ '174', 'registered sign' ], [ '8482', 'trade mark sign' ], [ '8240', 'per mille sign' ], [ '181', 'micro sign' ], [ '183', 'middle dot' ], [ '8226', 'bullet' ], [ '8230', 'three dot leader' ], [ '8242', 'minutes / feet' ], [ '8243', 'seconds / inches' ], [ '167', 'section sign' ], [ '182', 'paragraph sign' ], [ '223', 'sharp s / ess-zed' ], [ '8249', 'single left-pointing angle quotation mark' ], [ '8250', 'single right-pointing angle quotation mark' ], [ '171', 'left pointing guillemet' ], [ '187', 'right pointing guillemet' ], [ '8216', 'left single quotation mark' ], [ '8217', 'right single quotation mark' ], [ '8220', 'left double quotation mark' ], [ '8221', 'right double quotation mark' ], [ '8218', 'single low-9 quotation mark' ], [ '8222', 'double low-9 quotation mark' ], [ '60', 'less-than sign' ], [ '62', 'greater-than sign' ], [ '8804', 'less-than or equal to' ], [ '8805', 'greater-than or equal to' ], [ '8211', 'en dash' ], [ '8212', 'em dash' ], [ '175', 'macron' ], [ '8254', 'overline' ], [ '164', 'currency sign' ], [ '166', 'broken bar' ], [ '168', 'diaeresis' ], [ '161', 'inverted exclamation mark' ], [ '191', 'turned question mark' ], [ '710', 'circumflex accent' ], [ '732', 'small tilde' ], [ '176', 'degree sign' ], [ '8722', 'minus sign' ], [ '177', 'plus-minus sign' ], [ '247', 'division sign' ], [ '8260', 'fraction slash' ], [ '215', 'multiplication sign' ], [ '185', 'superscript one' ], [ '178', 'superscript two' ], [ '179', 'superscript three' ], [ '188', 'fraction one quarter' ], [ '189', 'fraction one half' ], [ '190', 'fraction three quarters' ], [ '402', 'function / florin' ], [ '8747', 'integral' ], [ '8721', 'n-ary sumation' ], [ '8734', 'infinity' ], [ '8730', 'square root' ], [ '8764', 'similar to' ], [ '8773', 'approximately equal to' ], [ '8776', 'almost equal to' ], [ '8800', 'not equal to' ], [ '8801', 'identical to' ], [ '8712', 'element of' ], [ '8713', 'not an element of' ], [ '8715', 'contains as member' ], [ '8719', 'n-ary product' ], [ '8743', 'logical and' ], [ '8744', 'logical or' ], [ '172', 'not sign' ], [ '8745', 'intersection' ], [ '8746', 'union' ], [ '8706', 'partial differential' ], [ '8704', 'for all' ], [ '8707', 'there exists' ], [ '8709', 'diameter' ], [ '8711', 'backward difference' ], [ '8727', 'asterisk operator' ], [ '8733', 'proportional to' ], [ '8736', 'angle' ], [ '180', 'acute accent' ], [ '184', 'cedilla' ], [ '170', 'feminine ordinal indicator' ], [ '186', 'masculine ordinal indicator' ], [ '8224', 'dagger' ], [ '8225', 'double dagger' ], [ '192', 'A - grave' ], [ '193', 'A - acute' ], [ '194', 'A - circumflex' ], [ '195', 'A - tilde' ], [ '196', 'A - diaeresis' ], [ '197', 'A - ring above' ], [ '256', 'A - macron' ], [ '198', 'ligature AE' ], [ '199', 'C - cedilla' ], [ '200', 'E - grave' ], [ '201', 'E - acute' ], [ '202', 'E - circumflex' ], [ '203', 'E - diaeresis' ], [ '274', 'E - macron' ], [ '204', 'I - grave' ], [ '205', 'I - acute' ], [ '206', 'I - circumflex' ], [ '207', 'I - diaeresis' ], [ '298', 'I - macron' ], [ '208', 'ETH' ], [ '209', 'N - tilde' ], [ '210', 'O - grave' ], [ '211', 'O - acute' ], [ '212', 'O - circumflex' ], [ '213', 'O - tilde' ], [ '214', 'O - diaeresis' ], [ '216', 'O - slash' ], [ '332', 'O - macron' ], [ '338', 'ligature OE' ], [ '352', 'S - caron' ], [ '217', 'U - grave' ], [ '218', 'U - acute' ], [ '219', 'U - circumflex' ], [ '220', 'U - diaeresis' ], [ '362', 'U - macron' ], [ '221', 'Y - acute' ], [ '376', 'Y - diaeresis' ], [ '562', 'Y - macron' ], [ '222', 'THORN' ], [ '224', 'a - grave' ], [ '225', 'a - acute' ], [ '226', 'a - circumflex' ], [ '227', 'a - tilde' ], [ '228', 'a - diaeresis' ], [ '229', 'a - ring above' ], [ '257', 'a - macron' ], [ '230', 'ligature ae' ], [ '231', 'c - cedilla' ], [ '232', 'e - grave' ], [ '233', 'e - acute' ], [ '234', 'e - circumflex' ], [ '235', 'e - diaeresis' ], [ '275', 'e - macron' ], [ '236', 'i - grave' ], [ '237', 'i - acute' ], [ '238', 'i - circumflex' ], [ '239', 'i - diaeresis' ], [ '299', 'i - macron' ], [ '240', 'eth' ], [ '241', 'n - tilde' ], [ '242', 'o - grave' ], [ '243', 'o - acute' ], [ '244', 'o - circumflex' ], [ '245', 'o - tilde' ], [ '246', 'o - diaeresis' ], [ '248', 'o slash' ], [ '333', 'o macron' ], [ '339', 'ligature oe' ], [ '353', 's - caron' ], [ '249', 'u - grave' ], [ '250', 'u - acute' ], [ '251', 'u - circumflex' ], [ '252', 'u - diaeresis' ], [ '363', 'u - macron' ], [ '253', 'y - acute' ], [ '254', 'thorn' ], [ '255', 'y - diaeresis' ], [ '563', 'y - macron' ], [ '913', 'Alpha' ], [ '914', 'Beta' ], [ '915', 'Gamma' ], [ '916', 'Delta' ], [ '917', 'Epsilon' ], [ '918', 'Zeta' ], [ '919', 'Eta' ], [ '920', 'Theta' ], [ '921', 'Iota' ], [ '922', 'Kappa' ], [ '923', 'Lambda' ], [ '924', 'Mu' ], [ '925', 'Nu' ], [ '926', 'Xi' ], [ '927', 'Omicron' ], [ '928', 'Pi' ], [ '929', 'Rho' ], [ '931', 'Sigma' ], [ '932', 'Tau' ], [ '933', 'Upsilon' ], [ '934', 'Phi' ], [ '935', 'Chi' ], [ '936', 'Psi' ], [ '937', 'Omega' ], [ '945', 'alpha' ], [ '946', 'beta' ], [ '947', 'gamma' ], [ '948', 'delta' ], [ '949', 'epsilon' ], [ '950', 'zeta' ], [ '951', 'eta' ], [ '952', 'theta' ], [ '953', 'iota' ], [ '954', 'kappa' ], [ '955', 'lambda' ], [ '956', 'mu' ], [ '957', 'nu' ], [ '958', 'xi' ], [ '959', 'omicron' ], [ '960', 'pi' ], [ '961', 'rho' ], [ '962', 'final sigma' ], [ '963', 'sigma' ], [ '964', 'tau' ], [ '965', 'upsilon' ], [ '966', 'phi' ], [ '967', 'chi' ], [ '968', 'psi' ], [ '969', 'omega' ], [ '8501', 'alef symbol' ], [ '982', 'pi symbol' ], [ '8476', 'real part symbol' ], [ '978', 'upsilon - hook symbol' ], [ '8472', 'Weierstrass p' ], [ '8465', 'imaginary part' ], [ '8592', 'leftwards arrow' ], [ '8593', 'upwards arrow' ], [ '8594', 'rightwards arrow' ], [ '8595', 'downwards arrow' ], [ '8596', 'left right arrow' ], [ '8629', 'carriage return' ], [ '8656', 'leftwards double arrow' ], [ '8657', 'upwards double arrow' ], [ '8658', 'rightwards double arrow' ], [ '8659', 'downwards double arrow' ], [ '8660', 'left right double arrow' ], [ '8756', 'therefore' ], [ '8834', 'subset of' ], [ '8835', 'superset of' ], [ '8836', 'not a subset of' ], [ '8838', 'subset of or equal to' ], [ '8839', 'superset of or equal to' ], [ '8853', 'circled plus' ], [ '8855', 'circled times' ], [ '8869', 'perpendicular' ], [ '8901', 'dot operator' ], [ '8968', 'left ceiling' ], [ '8969', 'right ceiling' ], [ '8970', 'left floor' ], [ '8971', 'right floor' ], [ '9001', 'left-pointing angle bracket' ], [ '9002', 'right-pointing angle bracket' ], [ '9674', 'lozenge' ], [ '9824', 'black spade suit' ], [ '9827', 'black club suit' ], [ '9829', 'black heart suit' ], [ '9830', 'black diamond suit' ], [ '8194', 'en space' ], [ '8195', 'em space' ], [ '8201', 'thin space' ], [ '8204', 'zero width non-joiner' ], [ '8205', 'zero width joiner' ], [ '8206', 'left-to-right mark' ], [ '8207', 'right-to-left mark' ] ]; }; var charmapFilter = function (charmap) { return global$1.grep(charmap, function (item) { return isArray(item) && item.length === 2; }); }; var getCharsFromSetting = function (settingValue) { if (isArray(settingValue)) { return [].concat(charmapFilter(settingValue)); } if (typeof settingValue === 'function') { return settingValue(); } return []; }; var extendCharMap = function (editor, charmap) { var userCharMap = Settings.getCharMap(editor); if (userCharMap) { charmap = getCharsFromSetting(userCharMap); } var userCharMapAppend = Settings.getCharMapAppend(editor); if (userCharMapAppend) { return [].concat(charmap).concat(getCharsFromSetting(userCharMapAppend)); } return charmap; }; var getCharMap$1 = function (editor) { return extendCharMap(editor, getDefaultCharMap()); }; var CharMap = { getCharMap: getCharMap$1 }; var get = function (editor) { var getCharMap = function () { return CharMap.getCharMap(editor); }; var insertChar = function (chr) { Actions.insertChar(editor, chr); }; return { getCharMap: getCharMap, insertChar: insertChar }; }; var Api = { get: get }; var getHtml = function (charmap) { var gridHtml, x, y; var width = Math.min(charmap.length, 25); var height = Math.ceil(charmap.length / width); gridHtml = ''; for (y = 0; y < height; y++) { gridHtml += ''; for (x = 0; x < width; x++) { var index = y * width + x; if (index < charmap.length) { var chr = charmap[index]; var charCode = parseInt(chr[0], 10); var chrText = chr ? String.fromCharCode(charCode) : ' '; gridHtml += ''; } else { gridHtml += ''; } gridHtml += ''; return gridHtml; }; var GridHtml = { getHtml: getHtml }; var getParentTd = function (elm) { while (elm) { if (elm.nodeName === 'TD') { return elm; } elm = elm.parentNode; } }; var open = function (editor) { var win; var charMapPanel = { type: 'container', html: GridHtml.getHtml(CharMap.getCharMap(editor)), onclick: function (e) { var target = e.target; if (/^(TD|DIV)$/.test(target.nodeName)) { var charDiv = getParentTd(target).firstChild; if (charDiv && charDiv.hasAttribute('data-chr')) { var charCodeString = charDiv.getAttribute('data-chr'); var charCode = parseInt(charCodeString, 10); if (!isNaN(charCode)) { Actions.insertChar(editor, String.fromCharCode(charCode)); } if (!e.ctrlKey) { win.close(); } } } }, onmouseover: function (e) { var td = getParentTd(e.target); if (td && td.firstChild) { win.find('#preview').text(td.firstChild.firstChild.data); win.find('#previewTitle').text(td.title); } else { win.find('#preview').text(' '); win.find('#previewTitle').text(' '); } } }; win = editor.windowManager.open({ title: 'Special character', spacing: 10, padding: 10, items: [ charMapPanel, { type: 'container', layout: 'flex', direction: 'column', align: 'center', spacing: 5, minWidth: 160, minHeight: 160, items: [ { type: 'label', name: 'preview', text: ' ', style: 'font-size: 40px; text-align: center', border: 1, minWidth: 140, minHeight: 80 }, { type: 'spacer', minHeight: 20 }, { type: 'label', name: 'previewTitle', text: ' ', style: 'white-space: pre-wrap;', border: 1, minWidth: 140 } ] } ], buttons: [{ text: 'Close', onclick: function () { win.close(); } }] }); }; var Dialog = { open: open }; var register = function (editor) { editor.addCommand('mceShowCharmap', function () { Dialog.open(editor); }); }; var Commands = { register: register }; var register$1 = function (editor) { editor.addButton('charmap', { icon: 'charmap', tooltip: 'Special character', cmd: 'mceShowCharmap' }); editor.addMenuItem('charmap', { icon: 'charmap', text: 'Special character', cmd: 'mceShowCharmap', context: 'insert' }); }; var Buttons = { register: register$1 }; global.add('charmap', function (editor) { Commands.register(editor); Buttons.register(editor); return Api.get(editor); }); function Plugin () { } return Plugin; }()); })(); tinymce/plugins/wptextpattern/plugin.min.js000064400000006061147573120640015260 0ustar00!function(u,p){function h(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}u.Env.ie&&u.Env.ie<9||u.PluginManager.add("wptextpattern",function(s){var f,d=u.util.VK,e=s.settings.wptextpattern||{},t=e.space||[{regExp:/^[*-]\s/,cmd:"InsertUnorderedList"},{regExp:/^1[.)]\s/,cmd:"InsertOrderedList"}],l=e.enter||[{start:"##",format:"h2"},{start:"###",format:"h3"},{start:"####",format:"h4"},{start:"#####",format:"h5"},{start:"######",format:"h6"},{start:">",format:"blockquote"},{regExp:/^(-){3,}$/,element:"hr"}],a=e.inline||[{delimiter:"`",format:"code"}];function c(){var r,i,o,t,d,l,e=s.selection.getRng(),n=e.startContainer,c=e.startOffset;n&&3===n.nodeType&&n.data.length&&c&&(d=n.data.slice(0,c),l=n.data.charAt(c-1),u.each(a,function(e){if(l===e.delimiter.slice(-1)){var t=h(e.delimiter),n=e.delimiter.charAt(0),t=new RegExp("(.*)"+t+".+"+t+"$"),t=d.match(t);if(t){r=t[1].length,i=c-e.delimiter.length;var t=d.charAt(r-1),a=d.charAt(r+e.delimiter.length);if(!(r&&/\S/.test(t)&&(/\s/.test(a)||t===n)||new RegExp("^[\\s"+h(n)+"]+$").test(d.slice(r,i))))return o=e,!1}}}),o)&&(e=s.formatter.get(o.format))&&e[0].inline&&(s.undoManager.add(),s.undoManager.transact(function(){n.insertData(c,"\ufeff"),n=n.splitText(r),t=n.splitText(c-r),n.deleteData(0,o.delimiter.length),n.deleteData(n.data.length-o.delimiter.length,o.delimiter.length),s.formatter.apply(o.format,{},n),s.selection.setCursorLocation(t,1)}),p(function(){f="space",s.once("selectionchange",function(){var e;t&&-1!==(e=t.data.indexOf("\ufeff"))&&t.deleteData(e,e+1)})}))}function g(e){var t,n=s.dom.getParent(e,"p");if(n){for(;(t=n.firstChild)&&3!==t.nodeType;)n=t;if(t)return t=t.data?t:t.nextSibling&&3===t.nextSibling.nodeType?t.nextSibling:null}}function m(){var n,a,r=s.selection.getRng(),i=r.startContainer;i&&g(i)===i&&(n=i.parentNode,a=i.data,u.each(t,function(e){var t=a.match(e.regExp);if(t&&r.startOffset===t[0].length)return s.undoManager.add(),s.undoManager.transact(function(){i.deleteData(0,t[0].length),n.innerHTML||n.appendChild(document.createElement("br")),s.selection.setCursorLocation(n),s.execCommand(e.cmd)}),p(function(){f="space"}),!1}))}s.on("selectionchange",function(){f=null}),s.on("keydown",function(e){if((f&&27===e.keyCode||"space"===f&&e.keyCode===d.BACKSPACE)&&(s.undoManager.undo(),e.preventDefault(),e.stopImmediatePropagation()),!d.metaKeyPressed(e))if(e.keyCode===d.ENTER){var t,n,a,r=s.selection.getRng().startContainer,i=g(r),o=l.length;if(i){for(t=i.data;o--;)if(l[o].start){if(0===t.indexOf(l[o].start)){n=l[o];break}}else if(l[o].regExp&&l[o].regExp.test(t)){n=l[o];break}!n||i===r&&u.trim(t)===n.start||s.once("keyup",function(){s.undoManager.add(),s.undoManager.transact(function(){var e;n.format?(s.formatter.apply(n.format,{},i),i.replaceData(0,i.data.length,(e=i.data.slice(n.start.length))?e.replace(/^\s+/,""):"")):n.element&&(a=i.parentNode&&i.parentNode.parentNode)&&a.replaceChild(document.createElement(n.element),i.parentNode)}),p(function(){f="enter"})})}}else e.keyCode===d.SPACEBAR?p(m):47 ). * - hr (---). * * Inline patterns: * - (`) (backtick). * * If the transformation in unwanted, the user can undo the change by pressing backspace, * using the undo shortcut, or the undo button in the toolbar. * * Setting for the patterns can be overridden by plugins by using the `tiny_mce_before_init` PHP filter. * The setting name is `wptextpattern` and the value is an object containing override arrays for each * patterns group. There are three groups: "space", "enter", and "inline". Example (PHP): * * add_filter( 'tiny_mce_before_init', 'my_mce_init_wptextpattern' ); * function my_mce_init_wptextpattern( $init ) { * $init['wptextpattern'] = wp_json_encode( array( * 'inline' => array( * array( 'delimiter' => '**', 'format' => 'bold' ), * array( 'delimiter' => '__', 'format' => 'italic' ), * ), * ) ); * * return $init; * } * * Note that setting this will override the default text patterns. You will need to include them * in your settings array if you want to keep them working. */ ( function( tinymce, setTimeout ) { if ( tinymce.Env.ie && tinymce.Env.ie < 9 ) { return; } /** * Escapes characters for use in a Regular Expression. * * @param {String} string Characters to escape * * @return {String} Escaped characters */ function escapeRegExp( string ) { return string.replace( /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&' ); } tinymce.PluginManager.add( 'wptextpattern', function( editor ) { var VK = tinymce.util.VK; var settings = editor.settings.wptextpattern || {}; var spacePatterns = settings.space || [ { regExp: /^[*-]\s/, cmd: 'InsertUnorderedList' }, { regExp: /^1[.)]\s/, cmd: 'InsertOrderedList' } ]; var enterPatterns = settings.enter || [ { start: '##', format: 'h2' }, { start: '###', format: 'h3' }, { start: '####', format: 'h4' }, { start: '#####', format: 'h5' }, { start: '######', format: 'h6' }, { start: '>', format: 'blockquote' }, { regExp: /^(-){3,}$/, element: 'hr' } ]; var inlinePatterns = settings.inline || [ { delimiter: '`', format: 'code' } ]; var canUndo; editor.on( 'selectionchange', function() { canUndo = null; } ); editor.on( 'keydown', function( event ) { if ( ( canUndo && event.keyCode === 27 /* ESCAPE */ ) || ( canUndo === 'space' && event.keyCode === VK.BACKSPACE ) ) { editor.undoManager.undo(); event.preventDefault(); event.stopImmediatePropagation(); } if ( VK.metaKeyPressed( event ) ) { return; } if ( event.keyCode === VK.ENTER ) { enter(); // Wait for the browser to insert the character. } else if ( event.keyCode === VK.SPACEBAR ) { setTimeout( space ); } else if ( event.keyCode > 47 && ! ( event.keyCode >= 91 && event.keyCode <= 93 ) ) { setTimeout( inline ); } }, true ); function inline() { var rng = editor.selection.getRng(); var node = rng.startContainer; var offset = rng.startOffset; var startOffset; var endOffset; var pattern; var format; var zero; // We need a non-empty text node with an offset greater than zero. if ( ! node || node.nodeType !== 3 || ! node.data.length || ! offset ) { return; } var string = node.data.slice( 0, offset ); var lastChar = node.data.charAt( offset - 1 ); tinymce.each( inlinePatterns, function( p ) { // Character before selection should be delimiter. if ( lastChar !== p.delimiter.slice( -1 ) ) { return; } var escDelimiter = escapeRegExp( p.delimiter ); var delimiterFirstChar = p.delimiter.charAt( 0 ); var regExp = new RegExp( '(.*)' + escDelimiter + '.+' + escDelimiter + '$' ); var match = string.match( regExp ); if ( ! match ) { return; } startOffset = match[1].length; endOffset = offset - p.delimiter.length; var before = string.charAt( startOffset - 1 ); var after = string.charAt( startOffset + p.delimiter.length ); // test*test* => format applied. // test *test* => applied. // test* test* => not applied. if ( startOffset && /\S/.test( before ) ) { if ( /\s/.test( after ) || before === delimiterFirstChar ) { return; } } // Do not replace when only whitespace and delimiter characters. if ( ( new RegExp( '^[\\s' + escapeRegExp( delimiterFirstChar ) + ']+$' ) ).test( string.slice( startOffset, endOffset ) ) ) { return; } pattern = p; return false; } ); if ( ! pattern ) { return; } format = editor.formatter.get( pattern.format ); if ( format && format[0].inline ) { editor.undoManager.add(); editor.undoManager.transact( function() { node.insertData( offset, '\uFEFF' ); node = node.splitText( startOffset ); zero = node.splitText( offset - startOffset ); node.deleteData( 0, pattern.delimiter.length ); node.deleteData( node.data.length - pattern.delimiter.length, pattern.delimiter.length ); editor.formatter.apply( pattern.format, {}, node ); editor.selection.setCursorLocation( zero, 1 ); } ); // We need to wait for native events to be triggered. setTimeout( function() { canUndo = 'space'; editor.once( 'selectionchange', function() { var offset; if ( zero ) { offset = zero.data.indexOf( '\uFEFF' ); if ( offset !== -1 ) { zero.deleteData( offset, offset + 1 ); } } } ); } ); } } function firstTextNode( node ) { var parent = editor.dom.getParent( node, 'p' ), child; if ( ! parent ) { return; } while ( child = parent.firstChild ) { if ( child.nodeType !== 3 ) { parent = child; } else { break; } } if ( ! child ) { return; } if ( ! child.data ) { if ( child.nextSibling && child.nextSibling.nodeType === 3 ) { child = child.nextSibling; } else { child = null; } } return child; } function space() { var rng = editor.selection.getRng(), node = rng.startContainer, parent, text; if ( ! node || firstTextNode( node ) !== node ) { return; } parent = node.parentNode; text = node.data; tinymce.each( spacePatterns, function( pattern ) { var match = text.match( pattern.regExp ); if ( ! match || rng.startOffset !== match[0].length ) { return; } editor.undoManager.add(); editor.undoManager.transact( function() { node.deleteData( 0, match[0].length ); if ( ! parent.innerHTML ) { parent.appendChild( document.createElement( 'br' ) ); } editor.selection.setCursorLocation( parent ); editor.execCommand( pattern.cmd ); } ); // We need to wait for native events to be triggered. setTimeout( function() { canUndo = 'space'; } ); return false; } ); } function enter() { var rng = editor.selection.getRng(), start = rng.startContainer, node = firstTextNode( start ), i = enterPatterns.length, text, pattern, parent; if ( ! node ) { return; } text = node.data; while ( i-- ) { if ( enterPatterns[ i ].start ) { if ( text.indexOf( enterPatterns[ i ].start ) === 0 ) { pattern = enterPatterns[ i ]; break; } } else if ( enterPatterns[ i ].regExp ) { if ( enterPatterns[ i ].regExp.test( text ) ) { pattern = enterPatterns[ i ]; break; } } } if ( ! pattern ) { return; } if ( node === start && tinymce.trim( text ) === pattern.start ) { return; } editor.once( 'keyup', function() { editor.undoManager.add(); editor.undoManager.transact( function() { if ( pattern.format ) { editor.formatter.apply( pattern.format, {}, node ); node.replaceData( 0, node.data.length, ltrim( node.data.slice( pattern.start.length ) ) ); } else if ( pattern.element ) { parent = node.parentNode && node.parentNode.parentNode; if ( parent ) { parent.replaceChild( document.createElement( pattern.element ), node.parentNode ); } } } ); // We need to wait for native events to be triggered. setTimeout( function() { canUndo = 'enter'; } ); } ); } function ltrim( text ) { return text ? text.replace( /^\s+/, '' ) : ''; } } ); } )( window.tinymce, window.setTimeout ); tinymce/plugins/colorpicker/plugin.min.js000064400000002505147573120640014642 0ustar00!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),l=tinymce.util.Tools.resolve("tinymce.util.Color"),a=function(e,n){e.find("#preview")[0].getEl().style.background=n},o=function(e,n){var i=l(n),t=i.toRgb();e.fromJSON({r:t.r,g:t.g,b:t.b,hex:i.toHex().substr(1)}),a(e,i.toHex())},t=function(e,n,i){var t=e.windowManager.open({title:"Color",items:{type:"container",layout:"flex",direction:"row",align:"stretch",padding:5,spacing:10,items:[{type:"colorpicker",value:i,onchange:function(){var e=this.rgb();t&&(t.find("#r").value(e.r),t.find("#g").value(e.g),t.find("#b").value(e.b),t.find("#hex").value(this.value().substr(1)),a(t,this.value()))}},{type:"form",padding:0,labelGap:5,defaults:{type:"textbox",size:7,value:"0",flex:1,spellcheck:!1,onchange:function(){var e,n,i=t.find("colorpicker")[0];if(e=this.name(),n=this.value(),"hex"===e)return o(t,n="#"+n),void i.value(n);n={r:t.find("#r").value(),g:t.find("#g").value(),b:t.find("#b").value()},i.value(n),o(t,n)}},items:[{name:"r",label:"R",autofocus:1},{name:"g",label:"G"},{name:"b",label:"B"},{name:"hex",label:"#",value:"000000"},{name:"preview",type:"container",border:1}]}]},onSubmit:function(){n("#"+t.toJSON().hex)}});o(t,i)};e.add("colorpicker",function(i){i.settings.color_picker_callback||(i.settings.color_picker_callback=function(e,n){t(i,e,n)})})}();tinymce/plugins/colorpicker/plugin.js000064400000006751147573120640014067 0ustar00(function () { var colorpicker = (function () { 'use strict'; var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); var global$1 = tinymce.util.Tools.resolve('tinymce.util.Color'); var showPreview = function (win, hexColor) { win.find('#preview')[0].getEl().style.background = hexColor; }; var setColor = function (win, value) { var color = global$1(value), rgb = color.toRgb(); win.fromJSON({ r: rgb.r, g: rgb.g, b: rgb.b, hex: color.toHex().substr(1) }); showPreview(win, color.toHex()); }; var open = function (editor, callback, value) { var win = editor.windowManager.open({ title: 'Color', items: { type: 'container', layout: 'flex', direction: 'row', align: 'stretch', padding: 5, spacing: 10, items: [ { type: 'colorpicker', value: value, onchange: function () { var rgb = this.rgb(); if (win) { win.find('#r').value(rgb.r); win.find('#g').value(rgb.g); win.find('#b').value(rgb.b); win.find('#hex').value(this.value().substr(1)); showPreview(win, this.value()); } } }, { type: 'form', padding: 0, labelGap: 5, defaults: { type: 'textbox', size: 7, value: '0', flex: 1, spellcheck: false, onchange: function () { var colorPickerCtrl = win.find('colorpicker')[0]; var name, value; name = this.name(); value = this.value(); if (name === 'hex') { value = '#' + value; setColor(win, value); colorPickerCtrl.value(value); return; } value = { r: win.find('#r').value(), g: win.find('#g').value(), b: win.find('#b').value() }; colorPickerCtrl.value(value); setColor(win, value); } }, items: [ { name: 'r', label: 'R', autofocus: 1 }, { name: 'g', label: 'G' }, { name: 'b', label: 'B' }, { name: 'hex', label: '#', value: '000000' }, { name: 'preview', type: 'container', border: 1 } ] } ] }, onSubmit: function () { callback('#' + win.toJSON().hex); } }); setColor(win, value); }; var Dialog = { open: open }; global.add('colorpicker', function (editor) { if (!editor.settings.color_picker_callback) { editor.settings.color_picker_callback = function (callback, value) { Dialog.open(editor, callback, value); }; } }); function Plugin () { } return Plugin; }()); })(); tinymce/tiny_mce_popup.js000064400000037164147573120640011630 0ustar00/** * tinymce_mce_popup.js * * Released under LGPL License. * Copyright (c) 1999-2017 Ephox Corp. All rights reserved * * License: http://www.tinymce.com/license * Contributing: http://www.tinymce.com/contributing */ var tinymce, tinyMCE; /** * TinyMCE popup/dialog helper class. This gives you easy access to the * parent editor instance and a bunch of other things. It's higly recommended * that you load this script into your dialogs. * * @static * @class tinyMCEPopup */ var tinyMCEPopup = { /** * Initializes the popup this will be called automatically. * * @method init */ init: function () { var self = this, parentWin, settings, uiWindow; // Find window & API parentWin = self.getWin(); tinymce = tinyMCE = parentWin.tinymce; self.editor = tinymce.EditorManager.activeEditor; self.params = self.editor.windowManager.getParams(); uiWindow = self.editor.windowManager.windows[self.editor.windowManager.windows.length - 1]; self.features = uiWindow.features; self.uiWindow = uiWindow; settings = self.editor.settings; // Setup popup CSS path(s) if (settings.popup_css !== false) { if (settings.popup_css) { settings.popup_css = self.editor.documentBaseURI.toAbsolute(settings.popup_css); } else { settings.popup_css = self.editor.baseURI.toAbsolute("plugins/compat3x/css/dialog.css"); } } if (settings.popup_css_add) { settings.popup_css += ',' + self.editor.documentBaseURI.toAbsolute(settings.popup_css_add); } // Setup local DOM self.dom = self.editor.windowManager.createInstance('tinymce.dom.DOMUtils', document, { ownEvents: true, proxy: tinyMCEPopup._eventProxy }); self.dom.bind(window, 'ready', self._onDOMLoaded, self); // Enables you to skip loading the default css if (self.features.popup_css !== false) { self.dom.loadCSS(self.features.popup_css || self.editor.settings.popup_css); } // Setup on init listeners self.listeners = []; /** * Fires when the popup is initialized. * * @event onInit * @param {tinymce.Editor} editor Editor instance. * @example * // Alerts the selected contents when the dialog is loaded * tinyMCEPopup.onInit.add(function(ed) { * alert(ed.selection.getContent()); * }); * * // Executes the init method on page load in some object using the SomeObject scope * tinyMCEPopup.onInit.add(SomeObject.init, SomeObject); */ self.onInit = { add: function (func, scope) { self.listeners.push({ func: func, scope: scope }); } }; self.isWindow = !self.getWindowArg('mce_inline'); self.id = self.getWindowArg('mce_window_id'); }, /** * Returns the reference to the parent window that opened the dialog. * * @method getWin * @return {Window} Reference to the parent window that opened the dialog. */ getWin: function () { // Added frameElement check to fix bug: #2817583 return (!window.frameElement && window.dialogArguments) || opener || parent || top; }, /** * Returns a window argument/parameter by name. * * @method getWindowArg * @param {String} name Name of the window argument to retrieve. * @param {String} defaultValue Optional default value to return. * @return {String} Argument value or default value if it wasn't found. */ getWindowArg: function (name, defaultValue) { var value = this.params[name]; return tinymce.is(value) ? value : defaultValue; }, /** * Returns a editor parameter/config option value. * * @method getParam * @param {String} name Name of the editor config option to retrieve. * @param {String} defaultValue Optional default value to return. * @return {String} Parameter value or default value if it wasn't found. */ getParam: function (name, defaultValue) { return this.editor.getParam(name, defaultValue); }, /** * Returns a language item by key. * * @method getLang * @param {String} name Language item like mydialog.something. * @param {String} defaultValue Optional default value to return. * @return {String} Language value for the item like "my string" or the default value if it wasn't found. */ getLang: function (name, defaultValue) { return this.editor.getLang(name, defaultValue); }, /** * Executed a command on editor that opened the dialog/popup. * * @method execCommand * @param {String} cmd Command to execute. * @param {Boolean} ui Optional boolean value if the UI for the command should be presented or not. * @param {Object} val Optional value to pass with the comman like an URL. * @param {Object} a Optional arguments object. */ execCommand: function (cmd, ui, val, args) { args = args || {}; args.skip_focus = 1; this.restoreSelection(); return this.editor.execCommand(cmd, ui, val, args); }, /** * Resizes the dialog to the inner size of the window. This is needed since various browsers * have different border sizes on windows. * * @method resizeToInnerSize */ resizeToInnerSize: function () { /*var self = this; // Detach it to workaround a Chrome specific bug // https://sourceforge.net/tracker/?func=detail&atid=635682&aid=2926339&group_id=103281 setTimeout(function() { var vp = self.dom.getViewPort(window); self.editor.windowManager.resizeBy( self.getWindowArg('mce_width') - vp.w, self.getWindowArg('mce_height') - vp.h, self.id || window ); }, 10);*/ }, /** * Will executed the specified string when the page has been loaded. This function * was added for compatibility with the 2.x branch. * * @method executeOnLoad * @param {String} evil String to evalutate on init. */ executeOnLoad: function (evil) { this.onInit.add(function () { eval(evil); }); }, /** * Stores the current editor selection for later restoration. This can be useful since some browsers * looses it's selection if a control element is selected/focused inside the dialogs. * * @method storeSelection */ storeSelection: function () { this.editor.windowManager.bookmark = tinyMCEPopup.editor.selection.getBookmark(1); }, /** * Restores any stored selection. This can be useful since some browsers * looses it's selection if a control element is selected/focused inside the dialogs. * * @method restoreSelection */ restoreSelection: function () { var self = tinyMCEPopup; if (!self.isWindow && tinymce.isIE) { self.editor.selection.moveToBookmark(self.editor.windowManager.bookmark); } }, /** * Loads a specific dialog language pack. If you pass in plugin_url as a argument * when you open the window it will load the /langs/_dlg.js lang pack file. * * @method requireLangPack */ requireLangPack: function () { var self = this, url = self.getWindowArg('plugin_url') || self.getWindowArg('theme_url'), settings = self.editor.settings, lang; if (settings.language !== false) { lang = settings.language || "en"; } if (url && lang && self.features.translate_i18n !== false && settings.language_load !== false) { url += '/langs/' + lang + '_dlg.js'; if (!tinymce.ScriptLoader.isDone(url)) { document.write(''); tinymce.ScriptLoader.markDone(url); } } }, /** * Executes a color picker on the specified element id. When the user * then selects a color it will be set as the value of the specified element. * * @method pickColor * @param {DOMEvent} e DOM event object. * @param {string} element_id Element id to be filled with the color value from the picker. */ pickColor: function (e, element_id) { var el = document.getElementById(element_id), colorPickerCallback = this.editor.settings.color_picker_callback; if (colorPickerCallback) { colorPickerCallback.call( this.editor, function (value) { el.value = value; try { el.onchange(); } catch (ex) { // Try fire event, ignore errors } }, el.value ); } }, /** * Opens a filebrowser/imagebrowser this will set the output value from * the browser as a value on the specified element. * * @method openBrowser * @param {string} element_id Id of the element to set value in. * @param {string} type Type of browser to open image/file/flash. * @param {string} option Option name to get the file_broswer_callback function name from. */ openBrowser: function (element_id, type) { tinyMCEPopup.restoreSelection(); this.editor.execCallback('file_browser_callback', element_id, document.getElementById(element_id).value, type, window); }, /** * Creates a confirm dialog. Please don't use the blocking behavior of this * native version use the callback method instead then it can be extended. * * @method confirm * @param {String} t Title for the new confirm dialog. * @param {function} cb Callback function to be executed after the user has selected ok or cancel. * @param {Object} s Optional scope to execute the callback in. */ confirm: function (t, cb, s) { this.editor.windowManager.confirm(t, cb, s, window); }, /** * Creates a alert dialog. Please don't use the blocking behavior of this * native version use the callback method instead then it can be extended. * * @method alert * @param {String} tx Title for the new alert dialog. * @param {function} cb Callback function to be executed after the user has selected ok. * @param {Object} s Optional scope to execute the callback in. */ alert: function (tx, cb, s) { this.editor.windowManager.alert(tx, cb, s, window); }, /** * Closes the current window. * * @method close */ close: function () { var t = this; // To avoid domain relaxing issue in Opera function close() { t.editor.windowManager.close(window); tinymce = tinyMCE = t.editor = t.params = t.dom = t.dom.doc = null; // Cleanup } if (tinymce.isOpera) { t.getWin().setTimeout(close, 0); } else { close(); } }, // Internal functions _restoreSelection: function () { var e = window.event.srcElement; if (e.nodeName == 'INPUT' && (e.type == 'submit' || e.type == 'button')) { tinyMCEPopup.restoreSelection(); } }, /* _restoreSelection : function() { var e = window.event.srcElement; // If user focus a non text input or textarea if ((e.nodeName != 'INPUT' && e.nodeName != 'TEXTAREA') || e.type != 'text') tinyMCEPopup.restoreSelection(); },*/ _onDOMLoaded: function () { var t = tinyMCEPopup, ti = document.title, h, nv; // Translate page if (t.features.translate_i18n !== false) { var map = { "update": "Ok", "insert": "Ok", "cancel": "Cancel", "not_set": "--", "class_name": "Class name", "browse": "Browse" }; var langCode = (tinymce.settings ? tinymce.settings : t.editor.settings).language || 'en'; for (var key in map) { tinymce.i18n.data[langCode + "." + key] = tinymce.i18n.translate(map[key]); } h = document.body.innerHTML; // Replace a=x with a="x" in IE if (tinymce.isIE) { h = h.replace(/ (value|title|alt)=([^"][^\s>]+)/gi, ' $1="$2"'); } document.dir = t.editor.getParam('directionality', ''); if ((nv = t.editor.translate(h)) && nv != h) { document.body.innerHTML = nv; } if ((nv = t.editor.translate(ti)) && nv != ti) { document.title = ti = nv; } } if (!t.editor.getParam('browser_preferred_colors', false) || !t.isWindow) { t.dom.addClass(document.body, 'forceColors'); } document.body.style.display = ''; // Restore selection in IE when focus is placed on a non textarea or input element of the type text if (tinymce.Env.ie) { if (tinymce.Env.ie < 11) { document.attachEvent('onmouseup', tinyMCEPopup._restoreSelection); // Add base target element for it since it would fail with modal dialogs t.dom.add(t.dom.select('head')[0], 'base', { target: '_self' }); } else { document.addEventListener('mouseup', tinyMCEPopup._restoreSelection, false); } } t.restoreSelection(); t.resizeToInnerSize(); // Set inline title if (!t.isWindow) { t.editor.windowManager.setTitle(window, ti); } else { window.focus(); } if (!tinymce.isIE && !t.isWindow) { t.dom.bind(document, 'focus', function () { t.editor.windowManager.focus(t.id); }); } // Patch for accessibility tinymce.each(t.dom.select('select'), function (e) { e.onkeydown = tinyMCEPopup._accessHandler; }); // Call onInit // Init must be called before focus so the selection won't get lost by the focus call tinymce.each(t.listeners, function (o) { o.func.call(o.scope, t.editor); }); // Move focus to window if (t.getWindowArg('mce_auto_focus', true)) { window.focus(); // Focus element with mceFocus class tinymce.each(document.forms, function (f) { tinymce.each(f.elements, function (e) { if (t.dom.hasClass(e, 'mceFocus') && !e.disabled) { e.focus(); return false; // Break loop } }); }); } document.onkeyup = tinyMCEPopup._closeWinKeyHandler; if ('textContent' in document) { t.uiWindow.getEl('head').firstChild.textContent = document.title; } else { t.uiWindow.getEl('head').firstChild.innerText = document.title; } }, _accessHandler: function (e) { e = e || window.event; if (e.keyCode == 13 || e.keyCode == 32) { var elm = e.target || e.srcElement; if (elm.onchange) { elm.onchange(); } return tinymce.dom.Event.cancel(e); } }, _closeWinKeyHandler: function (e) { e = e || window.event; if (e.keyCode == 27) { tinyMCEPopup.close(); } }, _eventProxy: function (id) { return function (evt) { tinyMCEPopup.dom.events.callNativeHandler(id, evt); }; } }; tinyMCEPopup.init(); tinymce.util.Dispatcher = function (scope) { this.scope = scope || this; this.listeners = []; this.add = function (callback, scope) { this.listeners.push({ cb: callback, scope: scope || this.scope }); return callback; }; this.addToTop = function (callback, scope) { var self = this, listener = { cb: callback, scope: scope || self.scope }; // Create new listeners if addToTop is executed in a dispatch loop if (self.inDispatch) { self.listeners = [listener].concat(self.listeners); } else { self.listeners.unshift(listener); } return callback; }; this.remove = function (callback) { var listeners = this.listeners, output = null; tinymce.each(listeners, function (listener, i) { if (callback == listener.cb) { output = listener; listeners.splice(i, 1); return false; } }); return output; }; this.dispatch = function () { var self = this, returnValue, args = arguments, i, listeners = self.listeners, listener; self.inDispatch = true; // Needs to be a real loop since the listener count might change while looping // And this is also more efficient for (i = 0; i < listeners.length; i++) { listener = listeners[i]; returnValue = listener.cb.apply(listener.scope, args.length > 0 ? args : [listener.scope]); if (returnValue === false) { break; } } self.inDispatch = false; return returnValue; }; }; tinymce/wp-tinymce.php000064400000002022147573120640011026 0ustar00+~]|"+at+")"+at+"*"),mt=new RegExp("="+at+"*([^\\]'\"]*?)"+at+"*\\]","g"),gt=new RegExp(ct),pt=new RegExp("^"+ut+"$"),ht={ID:new RegExp("^#("+ut+")"),CLASS:new RegExp("^\\.("+ut+")"),TAG:new RegExp("^("+ut+"|[*])"),ATTR:new RegExp("^"+st),PSEUDO:new RegExp("^"+ct),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+at+"*(even|odd|(([+-]|)(\\d*)n|)"+at+"*(?:([+-]|)"+at+"*(\\d+)|))"+at+"*\\)|)","i"),bool:new RegExp("^(?:checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped)$","i"),needsContext:new RegExp("^"+at+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+at+"*((?:-\\d)?\\d*)"+at+"*\\)|)(?=[^-]|$)","i")},vt=/^(?:input|select|textarea|button)$/i,yt=/^h\d$/i,bt=/^[^{]+\{\s*\[native \w/,Ct=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,xt=/[+~]/,wt=/'|\\/g,Nt=new RegExp("\\\\([\\da-f]{1,6}"+at+"?|("+at+")|.)","ig"),Et=function(e,t,n){var r="0x"+t-65536;return r!=r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)};try{rt.apply(et=ot.call($e.childNodes),$e.childNodes),et[$e.childNodes.length].nodeType}catch(iE){rt={apply:et.length?function(e,t){nt.apply(e,ot.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}var St=function(e,t,n,r){var o,i,a,u,s,c,l,f,d,m;if((t?t.ownerDocument||t:$e)!==Me&&Fe(t),n=n||[],!e||"string"!=typeof e)return n;if(1!==(u=(t=t||Me).nodeType)&&9!==u)return[];if(Ue&&!r){if(o=Ct.exec(e))if(a=o[1]){if(9===u){if(!(i=t.getElementById(a))||!i.parentNode)return n;if(i.id===a)return n.push(i),n}else if(t.ownerDocument&&(i=t.ownerDocument.getElementById(a))&&He(t,i)&&i.id===a)return n.push(i),n}else{if(o[2])return rt.apply(n,t.getElementsByTagName(e)),n;if((a=o[3])&&ke.getElementsByClassName)return rt.apply(n,t.getElementsByClassName(a)),n}if(ke.qsa&&(!je||!je.test(e))){if(f=l=qe,d=t,m=9===u&&e,1===u&&"object"!==t.nodeName.toLowerCase()){for(c=De(e),(l=t.getAttribute("id"))?f=l.replace(wt,"\\$&"):t.setAttribute("id",f),f="[id='"+f+"'] ",s=c.length;s--;)c[s]=f+Pt(c[s]);d=xt.test(e)&&Ot(t.parentNode)||t,m=c.join(",")}if(m)try{return rt.apply(n,d.querySelectorAll(m)),n}catch(g){}finally{l||t.removeAttribute("id")}}}return Be(e.replace(lt,"$1"),t,n,r)};function Tt(){var r=[];return function e(t,n){return r.push(t+" ")>_e.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function kt(e){return e[qe]=!0,e}function _t(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||1<<31)-(~e.sourceIndex||1<<31);if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function At(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function Rt(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function Dt(a){return kt(function(i){return i=+i,kt(function(e,t){for(var n,r=a([],e.length,i),o=r.length;o--;)e[n=r[o]]&&(e[n]=!(t[n]=e[n]))})})}function Ot(e){return e&&typeof e.getElementsByTagName!==Qe&&e}for(Te in ke=St.support={},Re=St.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},Fe=St.setDocument=function(e){var t,s=e?e.ownerDocument||e:$e,n=s.defaultView;return s!==Me&&9===s.nodeType&&s.documentElement?(ze=(Me=s).documentElement,Ue=!Re(s),n&&n!==function(e){try{return e.top}catch(t){}return null}(n)&&(n.addEventListener?n.addEventListener("unload",function(){Fe()},!1):n.attachEvent&&n.attachEvent("onunload",function(){Fe()})),ke.attributes=!0,ke.getElementsByTagName=!0,ke.getElementsByClassName=bt.test(s.getElementsByClassName),ke.getById=!0,_e.find.ID=function(e,t){if(typeof t.getElementById!==Qe&&Ue){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},_e.filter.ID=function(e){var t=e.replace(Nt,Et);return function(e){return e.getAttribute("id")===t}},_e.find.TAG=ke.getElementsByTagName?function(e,t){if(typeof t.getElementsByTagName!==Qe)return t.getElementsByTagName(e)}:function(e,t){var n,r=[],o=0,i=t.getElementsByTagName(e);if("*"===e){for(;n=i[o++];)1===n.nodeType&&r.push(n);return r}return i},_e.find.CLASS=ke.getElementsByClassName&&function(e,t){if(Ue)return t.getElementsByClassName(e)},Ve=[],je=[],ke.disconnectedMatch=!0,je=je.length&&new RegExp(je.join("|")),Ve=Ve.length&&new RegExp(Ve.join("|")),t=bt.test(ze.compareDocumentPosition),He=t||bt.test(ze.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},Je=t?function(e,t){if(e===t)return Le=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!ke.sortDetached&&t.compareDocumentPosition(e)===n?e===s||e.ownerDocument===$e&&He($e,e)?-1:t===s||t.ownerDocument===$e&&He($e,t)?1:Ie?it.call(Ie,e)-it.call(Ie,t):0:4&n?-1:1)}:function(e,t){if(e===t)return Le=!0,0;var n,r=0,o=e.parentNode,i=t.parentNode,a=[e],u=[t];if(!o||!i)return e===s?-1:t===s?1:o?-1:i?1:Ie?it.call(Ie,e)-it.call(Ie,t):0;if(o===i)return _t(e,t);for(n=e;n=n.parentNode;)a.unshift(n);for(n=t;n=n.parentNode;)u.unshift(n);for(;a[r]===u[r];)r++;return r?_t(a[r],u[r]):a[r]===$e?-1:u[r]===$e?1:0},s):Me},St.matches=function(e,t){return St(e,null,null,t)},St.matchesSelector=function(e,t){if((e.ownerDocument||e)!==Me&&Fe(e),t=t.replace(mt,"='$1']"),ke.matchesSelector&&Ue&&(!Ve||!Ve.test(t))&&(!je||!je.test(t)))try{var n=(void 0).call(e,t);if(n||ke.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(iE){}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(Nt,Et),e[3]=(e[3]||e[4]||e[5]||"").replace(Nt,Et),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||St.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&St.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return ht.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&>.test(n)&&(t=De(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(Nt,Et).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=Xe[e+" "];return t||(t=new RegExp("(^|"+at+")"+e+"("+at+"|$)"))&&Xe(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==Qe&&e.getAttribute("class")||"")})},ATTR:function(n,r,o){return function(e){var t=St.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===o:"!="===r?t!==o:"^="===r?o&&0===t.indexOf(o):"*="===r?o&&-1)[^>]*$|#([\w\-]*)$)/,Zt=Se.Event,en=Xt.makeMap("children,contents,next,prev"),tn=function(e){return void 0!==e},nn=function(e){return"string"==typeof e},rn=function(e,t){var n,r,o;for(o=(t=t||Yt).createElement("div"),n=t.createDocumentFragment(),o.innerHTML=e;r=o.firstChild;)n.appendChild(r);return n},on=function(e,t,n,r){var o;if(nn(t))t=rn(t,bn(e[0]));else if(t.length&&!t.nodeType){if(t=gn.makeArray(t),r)for(o=t.length-1;0<=o;o--)on(e,t[o],n,r);else for(o=0;o"===e.charAt(e.length-1)&&3<=e.length?[null,e,null]:Qt.exec(e)))return gn(t).find(e);if(n[1])for(r=rn(e,bn(t)).firstChild;r;)Gt.call(o,r),r=r.nextSibling;else{if(!(r=bn(t).getElementById(n[2])))return o;if(r.id!==n[2])return o.find(e);o.length=1,o[0]=r}}else this.add(e,!1);return o},toArray:function(){return Xt.toArray(this)},add:function(e,t){var n,r,o=this;if(nn(e))return o.add(gn(e));if(!1!==t)for(n=gn.unique(o.toArray().concat(gn.makeArray(e))),o.length=n.length,r=0;r=a.length&&r(o)}))})})},co=function(e){return so(e,uo.nu)},lo=function(n){return{is:function(e){return n===e},isValue:C,isError:b,getOr:q(n),getOrThunk:q(n),getOrDie:q(n),or:function(e){return lo(n)},orThunk:function(e){return lo(n)},fold:function(e,t){return t(n)},map:function(e){return lo(e(n))},mapError:function(e){return lo(n)},each:function(e){e(n)},bind:function(e){return e(n)},exists:function(e){return e(n)},forall:function(e){return e(n)},toOption:function(){return _.some(n)}}},fo=function(n){return{is:b,isValue:b,isError:C,getOr:$,getOrThunk:function(e){return e()},getOrDie:function(){return e=String(n),function(){throw new Error(e)}();var e},or:function(e){return e},orThunk:function(e){return e()},fold:function(e,t){return e(n)},map:function(e){return fo(n)},mapError:function(e){return fo(e(n))},each:o,bind:function(e){return fo(n)},exists:b,forall:C,toOption:_.none}},mo={value:lo,error:fo,fromOption:function(e,t){return e.fold(function(){return fo(t)},lo)}};function go(e,u){var t=e,n=function(e,t,n,r){var o,i;if(e){if(!r&&e[t])return e[t];if(e!==u){if(o=e[n])return o;for(i=e.parentNode;i&&i!==u;i=i.parentNode)if(o=i[n])return o}}};this.current=function(){return t},this.next=function(e){return t=n(t,"firstChild","nextSibling",e)},this.prev=function(e){return t=n(t,"lastChild","previousSibling",e)},this.prev2=function(e){return t=function(e,t,n,r){var o,i,a;if(e){if(o=e[n],u&&o===u)return;if(o){if(!r)for(a=o[t];a;a=a[t])if(!a[t])return a;return o}if((i=e.parentNode)&&i!==u)return i}}(t,"lastChild","previousSibling",e)}}var po,ho,vo,yo=function(t){var n;return function(e){return(n=n||function(e,t){for(var n={},r=0,o=e.length;r\"\u0060\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,Ko=/[<>&\u007E-\uD7FF\uE000-\uFFEF]|[\uD800-\uDBFF][\uDC00-\uDFFF]/g,Xo=/[<>&\"\']/g,Yo=/&#([a-z0-9]+);?|&([a-z0-9]+);/gi,Go={128:"\u20ac",130:"\u201a",131:"\u0192",132:"\u201e",133:"\u2026",134:"\u2020",135:"\u2021",136:"\u02c6",137:"\u2030",138:"\u0160",139:"\u2039",140:"\u0152",142:"\u017d",145:"\u2018",146:"\u2019",147:"\u201c",148:"\u201d",149:"\u2022",150:"\u2013",151:"\u2014",152:"\u02dc",153:"\u2122",154:"\u0161",155:"\u203a",156:"\u0153",158:"\u017e",159:"\u0178"};ho={'"':""","'":"'","<":"<",">":">","&":"&","`":"`"},vo={"<":"<",">":">","&":"&",""":'"',"'":"'"};var Jo=function(e,t){var n,r,o,i={};if(e){for(e=e.split(","),t=t||10,n=0;n>10),56320+(1023&t))):Go[t]||String.fromCharCode(t):vo[e]||po[e]||(n=e,(r=ar.fromTag("div").dom()).innerHTML=n,r.textContent||r.innerText||n);var n,r})}},ni={},ri={},oi=Xt.makeMap,ii=Xt.each,ai=Xt.extend,ui=Xt.explode,si=Xt.inArray,ci=function(e,t){return(e=Xt.trim(e))?e.split(t||" "):[]},li=function(e){var u,t,n,r,o,i,s={},a=function(e,t,n){var r,o,i,a=function(e,t){var n,r,o={};for(n=0,r=e.length;n
  • "+a+"
  • "),(i=Nl(t))&&t.schema.isValidChild(n.nodeName.toLowerCase(),i.toLowerCase())?(r=a,r=t.dom.createHTML(i,t.settings.forced_root_block_attrs,r)):r||(r='
    '),qw(t,r),t.fire("SetContent",o)):("raw"!==o.format&&(r=al({validate:t.validate},t.schema).serialize(t.parser.parse(r,{isRootContent:!0,insert:!0}))),o.content=Ao(ar.fromDom(n))?r:Xt.trim(r),qw(t,o.content),o.no_events||t.fire("SetContent",o)),o.content);var t,n,r,o,i,a})},Ww=Si.DOM,Kw=function(e){return _.from(e).each(function(e){return e.destroy()})},Xw=function(e){if(!e.removed){var t=e._selectionOverrides,n=e.editorUpload,r=e.getBody(),o=e.getElement();r&&e.save({is_removing:!0}),e.removed=!0,e.unbindAllNativeEvents(),e.hasHiddenInput&&o&&Ww.remove(o.nextSibling),Np(e),e.editorManager.remove(e),!e.inline&&r&&(i=e,Ww.setStyle(i.id,"display",i.orgDisplay)),Ep(e),Ww.remove(e.getContainer()),Kw(t),Kw(n),e.destroy()}var i},Yw=function(e,t){var n,r,o,i=e.selection,a=e.dom;e.destroyed||(t||e.removed?(t||(e.editorManager.off("beforeunload",e._beforeUnload),e.theme&&e.theme.destroy&&e.theme.destroy(),Kw(i),Kw(a)),(r=(n=e).formElement)&&(r._mceOldSubmit&&(r.submit=r._mceOldSubmit,r._mceOldSubmit=null),Ww.unbind(r,"submit reset",n.formEventDelegate)),(o=e).contentAreaContainer=o.formElement=o.container=o.editorContainer=null,o.bodyElement=o.contentDocument=o.contentWindow=null,o.iframeElement=o.targetElm=null,o.selection&&(o.selection=o.selection.win=o.selection.dom=o.selection.dom.doc=null),e.destroyed=!0):e.remove())},Gw=Si.DOM,Jw=Xt.extend,Qw=Xt.each,Zw=Xt.resolve,eN=fe.ie,tN=function(e,t,n){var r,o,i,a,u,s,c,l=this,f=l.documentBaseUrl=n.documentBaseURL,d=n.baseURI;r=l,o=e,i=f,a=n.defaultSettings,u=t,c={id:o,theme:"modern",delta_width:0,delta_height:0,popup_css:"",plugins:"",document_base_url:i,add_form_submit_trigger:!0,submit_patch:!0,add_unload_trigger:!0,convert_urls:!0,relative_urls:!0,remove_script_host:!0,object_resizing:!0,doctype:"",visual:!0,font_size_style_values:"xx-small,x-small,small,medium,large,x-large,xx-large",font_size_legacy_values:"xx-small,small,medium,large,x-large,xx-large,300%",forced_root_block:"p",hidden_input:!0,render_ui:!0,indentation:"40px",inline_styles:!0,convert_fonts_to_spans:!0,indent:"simple",indent_before:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,tfoot,tbody,tr,section,summary,article,hgroup,aside,figure,figcaption,option,optgroup,datalist",indent_after:"p,h1,h2,h3,h4,h5,h6,blockquote,div,title,style,pre,script,td,th,ul,ol,li,dl,dt,dd,area,table,thead,tfoot,tbody,tr,section,summary,article,hgroup,aside,figure,figcaption,option,optgroup,datalist",entity_encoding:"named",url_converter:(s=r).convertURL,url_converter_scope:s,ie7_compat:!0},t=$p(zp,c,a,u),l.settings=t,Bi.language=t.language||"en",Bi.languageLoad=t.language_load,Bi.baseURL=n.baseURL,l.id=e,l.setDirty(!1),l.plugins={},l.documentBaseURI=new zw(t.document_base_url,{base_uri:d}),l.baseURI=d,l.contentCSS=[],l.contentStyles=[],l.shortcuts=new Qp(l),l.loadedCSS={},l.editorCommands=new pp(l),l.suffix=n.suffix,l.editorManager=n,l.inline=t.inline,l.buttons={},l.menuItems={},t.cache_suffix&&(fe.cacheSuffix=t.cache_suffix.replace(/^[\?\&]+/,"")),!1===t.override_viewport&&(fe.overrideViewPort=!1),n.fire("SetupEditor",{editor:l}),l.execCallback("setup",l),l.$=gn.overrideDefaults(function(){return{context:l.inline?l.getBody():l.getDoc(),element:l.getBody()}})};Jw(tN.prototype={render:function(){Bw(this)},focus:function(e){uh(this,e)},hasFocus:function(){return sh(this)},execCallback:function(e){for(var t=[],n=1;n=n.x&&o.x+o.w<=n.w+n.x&&o.y>=n.y&&o.y+o.h<=n.h+n.y)return r[i];return null},intersect:function(e,t){var n,r,o,i;return n=ON(e.x,t.x),r=ON(e.y,t.y),o=DN(e.x+e.w,t.x+t.w),i=DN(e.y+e.h,t.y+t.h),o-n<0||i-r<0?null:IN(n,r,o-n,i-r)},clamp:function(e,t,n){var r,o,i,a,u,s,c,l,f,d;return u=e.x,s=e.y,c=e.x+e.w,l=e.y+e.h,f=t.x+t.w,d=t.y+t.h,r=ON(0,t.x-u),o=ON(0,t.y-s),i=ON(0,c-f),a=ON(0,l-d),u+=r,s+=o,n&&(c+=r,l+=o,u-=i,s-=a),IN(u,s,(c-=i)-u,(l-=a)-s)},create:IN,fromClientRect:function(e){return IN(e.left,e.top,e.width,e.height)}},FN={},MN={add:function(e,t){FN[e.toLowerCase()]=t},has:function(e){return!!FN[e.toLowerCase()]},get:function(e){var t=e.toLowerCase(),n=FN.hasOwnProperty(t)?FN[t]:null;if(null===n)throw new Error("Could not find module for type: "+e);return n},create:function(e,t){var n;if("string"==typeof e?(t=t||{}).type=e:e=(t=e).type,e=e.toLowerCase(),!(n=FN[e]))throw new Error("Could not find control by type: "+e);return(n=new n(t)).type=e,n}},zN=Xt.each,UN=Xt.extend,jN=function(){};jN.extend=_N=function(n){var e,t,r,o=this.prototype,i=function(){var e,t,n;if(!AN&&(this.init&&this.init.apply(this,arguments),t=this.Mixins))for(e=t.length;e--;)(n=t[e]).init&&n.init.apply(this,arguments)},a=function(){return this},u=function(n,r){return function(){var e,t=this._super;return this._super=o[n],e=r.apply(this,arguments),this._super=t,e}};for(t in AN=!0,e=new this,AN=!1,n.Mixins&&(zN(n.Mixins,function(e){for(var t in e)"init"!==t&&(n[t]=e[t])}),o.Mixins&&(n.Mixins=o.Mixins.concat(n.Mixins))),n.Methods&&zN(n.Methods.split(","),function(e){n[e]=a}),n.Properties&&zN(n.Properties.split(","),function(e){var t="_"+e;n[e]=function(e){return e!==undefined?(this[t]=e,this):this[t]}}),n.Statics&&zN(n.Statics,function(e,t){i[t]=e}),n.Defaults&&o.Defaults&&(n.Defaults=UN({},o.Defaults,n.Defaults)),n)"function"==typeof(r=n[t])&&o[t]?e[t]=u(t,r):e[t]=r;return i.prototype=e,(i.constructor=i).extend=_N,i};var VN=Math.min,HN=Math.max,qN=Math.round,$N=function(e,n){var r,o,t,i;if(n=n||'"',null===e)return"null";if("string"==(t=typeof e))return o="\bb\tt\nn\ff\rr\"\"''\\\\",n+e.replace(/([\u0080-\uFFFF\x00-\x1f\"\'\\])/g,function(e,t){return'"'===n&&"'"===e?e:(r=o.indexOf(t))+1?"\\"+o.charAt(r+1):(e=t.charCodeAt().toString(16),"\\u"+"0000".substring(e.length)+e)})+n;if("object"===t){if(e.hasOwnProperty&&"[object Array]"===Object.prototype.toString.call(e)){for(r=0,o="[";rTiny']),u=t.getParam("branding",!0,"boolean")?{type:"label",classes:"branding",html:" "+l}:null;i.add({type:"panel",name:"statusbar",classes:"statusbar",layout:"flow",border:"1 0 0 0",ariaRoot:!0,items:[{type:"elementpath",editor:t},r,u]})}return x(t),t.on("SwitchMode",(a=i,function(e){a.find("*").disabled("readonly"===e.mode)})),i.renderBefore(n.targetNode).reflow(),t.getParam("readonly",!1,"boolean")&&t.setMode("readonly"),n.width&&pe.setStyle(i.getEl(),"width",n.width),t.on("remove",function(){i.remove(),i=null}),R(t,i),F(t),{iframeContainer:i.find("#iframe")[0].getEl(),editorContainer:i.getEl()}},ye=tinymce.util.Tools.resolve("tinymce.dom.DomQuery"),xe=0,we={id:function(){return"mceu_"+xe++},create:function(e,t,n){var i=_.document.createElement(e);return p.DOM.setAttribs(i,t),"string"==typeof n?i.innerHTML=n:w.each(n,function(e){e.nodeType&&i.appendChild(e)}),i},createFragment:function(e){return p.DOM.createFragment(e)},getWindowSize:function(){return p.DOM.getViewPort()},getSize:function(e){var t,n;if(e.getBoundingClientRect){var i=e.getBoundingClientRect();t=Math.max(i.width||i.right-i.left,e.offsetWidth),n=Math.max(i.height||i.bottom-i.bottom,e.offsetHeight)}else t=e.offsetWidth,n=e.offsetHeight;return{width:t,height:n}},getPos:function(e,t){return p.DOM.getPos(e,t||we.getContainer())},getContainer:function(){return ce.container?ce.container:_.document.body},getViewPort:function(e){return p.DOM.getViewPort(e)},get:function(e){return _.document.getElementById(e)},addClass:function(e,t){return p.DOM.addClass(e,t)},removeClass:function(e,t){return p.DOM.removeClass(e,t)},hasClass:function(e,t){return p.DOM.hasClass(e,t)},toggleClass:function(e,t,n){return p.DOM.toggleClass(e,t,n)},css:function(e,t,n){return p.DOM.setStyle(e,t,n)},getRuntimeStyle:function(e,t){return p.DOM.getStyle(e,t,!0)},on:function(e,t,n,i){return p.DOM.bind(e,t,n,i)},off:function(e,t,n){return p.DOM.unbind(e,t,n)},fire:function(e,t,n){return p.DOM.fire(e,t,n)},innerHtml:function(e,t){p.DOM.setHTML(e,t)}},_e=function(e){return"static"===we.getRuntimeStyle(e,"position")},Re=function(e){return e.state.get("fixed")};function Ce(e,t,n){var i,r,o,s,a,l,u,c,d,f;return d=Ee(),o=(r=we.getPos(t,W.getUiContainer(e))).x,s=r.y,Re(e)&&_e(_.document.body)&&(o-=d.x,s-=d.y),i=e.getEl(),a=(f=we.getSize(i)).width,l=f.height,u=(f=we.getSize(t)).width,c=f.height,"b"===(n=(n||"").split(""))[0]&&(s+=c),"r"===n[1]&&(o+=u),"c"===n[0]&&(s+=Math.round(c/2)),"c"===n[1]&&(o+=Math.round(u/2)),"b"===n[3]&&(s-=l),"r"===n[4]&&(o-=a),"c"===n[3]&&(s-=Math.round(l/2)),"c"===n[4]&&(o-=Math.round(a/2)),{x:o,y:s,w:a,h:l}}var Ee=function(){var e=_.window;return{x:Math.max(e.pageXOffset,_.document.body.scrollLeft,_.document.documentElement.scrollLeft),y:Math.max(e.pageYOffset,_.document.body.scrollTop,_.document.documentElement.scrollTop),w:e.innerWidth||_.document.documentElement.clientWidth,h:e.innerHeight||_.document.documentElement.clientHeight}},ke=function(e){var t,n=W.getUiContainer(e);return n&&!Re(e)?{x:0,y:0,w:(t=n).scrollWidth-1,h:t.scrollHeight-1}:Ee()},He={testMoveRel:function(e,t){for(var n=ke(this),i=0;in.x&&r.x+r.wn.y&&r.y+r.h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,ze=/^\s*|\s*$/g,Ie=Se.extend({init:function(e){var o=this.match;function s(e,t,n){var i;function r(e){e&&t.push(e)}return r(function(t){if(t)return t=t.toLowerCase(),function(e){return"*"===t||e.type===t}}((i=Be.exec(e.replace(ze,"")))[1])),r(function(t){if(t)return function(e){return e._name===t}}(i[2])),r(function(n){if(n)return n=n.split("."),function(e){for(var t=n.length;t--;)if(!e.classes.contains(n[t]))return!1;return!0}}(i[3])),r(function(n,i,r){if(n)return function(e){var t=e[n]?e[n]():"";return i?"="===i?t===r:"*="===i?0<=t.indexOf(r):"~="===i?0<=(" "+t+" ").indexOf(" "+r+" "):"!="===i?t!==r:"^="===i?0===t.indexOf(r):"$="===i&&t.substr(t.length-r.length)===r:!!r}}(i[4],i[5],i[6])),r(function(i){var t;if(i)return(i=/(?:not\((.+)\))|(.+)/i.exec(i))[1]?(t=a(i[1],[]),function(e){return!o(e,t)}):(i=i[2],function(e,t,n){return"first"===i?0===t:"last"===i?t===n-1:"even"===i?t%2==0:"odd"===i?t%2==1:!!e[i]&&e[i]()})}(i[7])),t.pseudo=!!i[7],t.direct=n,t}function a(e,t){var n,i,r,o=[];do{if(Le.exec(""),(i=Le.exec(e))&&(e=i[3],o.push(i[1]),i[2])){n=i[3];break}}while(i);for(n&&a(n,t),e=[],r=0;r"!==o[r]&&e.push(s(o[r],[],">"===o[r-1]));return t.push(e),t}this._selectors=a(e,[])},match:function(e,t){var n,i,r,o,s,a,l,u,c,d,f,h,m;for(n=0,i=(t=t||this._selectors).length;na.maxW?a.maxW:n,a.w=n,a.innerW=n-i),(n=e.h)!==undefined&&(n=(n=na.maxH?a.maxH:n,a.h=n,a.innerH=n-r),(n=e.innerW)!==undefined&&(n=(n=na.maxW-i?a.maxW-i:n,a.innerW=n,a.w=n+i),(n=e.innerH)!==undefined&&(n=(n=na.maxH-r?a.maxH-r:n,a.innerH=n,a.h=n+r),e.contentW!==undefined&&(a.contentW=e.contentW),e.contentH!==undefined&&(a.contentH=e.contentH),(t=s._lastLayoutRect).x===a.x&&t.y===a.y&&t.w===a.w&&t.h===a.h||((o=je.repaintControls)&&o.map&&!o.map[s._id]&&(o.push(s),o.map[s._id]=!0),t.x=a.x,t.y=a.y,t.w=a.w,t.h=a.h),s):a},repaint:function(){var e,t,n,i,r,o,s,a,l,u,c=this;l=_.document.createRange?function(e){return e}:Math.round,e=c.getEl().style,i=c._layoutRect,a=c._lastRepaintRect||{},o=(r=c.borderBox).left+r.right,s=r.top+r.bottom,i.x!==a.x&&(e.left=l(i.x)+"px",a.x=i.x),i.y!==a.y&&(e.top=l(i.y)+"px",a.y=i.y),i.w!==a.w&&(u=l(i.w-o),e.width=(0<=u?u:0)+"px",a.w=i.w),i.h!==a.h&&(u=l(i.h-s),e.height=(0<=u?u:0)+"px",a.h=i.h),c._hasBody&&i.innerW!==a.innerW&&(u=l(i.innerW),(n=c.getEl("body"))&&((t=n.style).width=(0<=u?u:0)+"px"),a.innerW=i.innerW),c._hasBody&&i.innerH!==a.innerH&&(u=l(i.innerH),(n=n||c.getEl("body"))&&((t=t||n.style).height=(0<=u?u:0)+"px"),a.innerH=i.innerH),c._lastRepaintRect=a,c.fire("repaint",{},!1)},updateLayoutRect:function(){var e=this;e.parent()._lastRect=null,we.css(e.getEl(),{width:"",height:""}),e._layoutRect=e._lastRepaintRect=e._lastLayoutRect=null,e.initLayoutRect()},on:function(e,t){var n,i,r,o=this;return nt(o).on(e,"string"!=typeof(n=t)?n:function(e){return i||o.parentsAndSelf().each(function(e){var t=e.settings.callbacks;if(t&&(i=t[n]))return r=e,!1}),i?i.call(r,e):(e.action=n,void this.fire("execute",e))}),o},off:function(e,t){return nt(this).off(e,t),this},fire:function(e,t,n){if((t=t||{}).control||(t.control=this),t=nt(this).fire(e,t),!1!==n&&this.parent)for(var i=this.parent();i&&!t.isPropagationStopped();)i.fire(e,t,!1),i=i.parent();return t},hasEventListeners:function(e){return nt(this).has(e)},parents:function(e){var t,n=new Ve;for(t=this.parent();t;t=t.parent())n.add(t);return e&&(n=n.filter(e)),n},parentsAndSelf:function(e){return new Ve(this).add(this.parents(e))},next:function(){var e=this.parent().items();return e[e.indexOf(this)+1]},prev:function(){var e=this.parent().items();return e[e.indexOf(this)-1]},innerHtml:function(e){return this.$el.html(e),this},getEl:function(e){var t=e?this._id+"-"+e:this._id;return this._elmCache[t]||(this._elmCache[t]=ye("#"+t)[0]),this._elmCache[t]},show:function(){return this.visible(!0)},hide:function(){return this.visible(!1)},focus:function(){try{this.getEl().focus()}catch(e){}return this},blur:function(){return this.getEl().blur(),this},aria:function(e,t){var n=this,i=n.getEl(n.ariaTarget);return void 0===t?n._aria[e]:(n._aria[e]=t,n.state.get("rendered")&&i.setAttribute("role"===e?e:"aria-"+e,t),n)},encode:function(e,t){return!1!==t&&(e=this.translate(e)),(e||"").replace(/[&<>"]/g,function(e){return"&#"+e.charCodeAt(0)+";"})},translate:function(e){return je.translate?je.translate(e):e},before:function(e){var t=this.parent();return t&&t.insert(e,t.items().indexOf(this),!0),this},after:function(e){var t=this.parent();return t&&t.insert(e,t.items().indexOf(this)),this},remove:function(){var t,e,n=this,i=n.getEl(),r=n.parent();if(n.items){var o=n.items().toArray();for(e=o.length;e--;)o[e].remove()}r&&r.items&&(t=[],r.items().each(function(e){e!==n&&t.push(e)}),r.items().set(t),r._lastRect=null),n._eventsRoot&&n._eventsRoot===n&&ye(i).off();var s=n.getRoot().controlIdLookup;return s&&delete s[n._id],i&&i.parentNode&&i.parentNode.removeChild(i),n.state.set("rendered",!1),n.state.destroy(),n.fire("remove"),n},renderBefore:function(e){return ye(e).before(this.renderHtml()),this.postRender(),this},renderTo:function(e){return ye(e||this.getContainerElm()).append(this.renderHtml()),this.postRender(),this},preRender:function(){},render:function(){},renderHtml:function(){return'
    '},postRender:function(){var e,t,n,i,r,o=this,s=o.settings;for(i in o.$el=ye(o.getEl()),o.state.set("rendered",!0),s)0===i.indexOf("on")&&o.on(i.substr(2),s[i]);if(o._eventsRoot){for(n=o.parent();!r&&n;n=n.parent())r=n._eventsRoot;if(r)for(i in r._nativeEvents)o._nativeEvents[i]=!0}it(o),s.style&&(e=o.getEl())&&(e.setAttribute("style",s.style),e.style.cssText=s.style),o.settings.border&&(t=o.borderBox,o.$el.css({"border-top-width":t.top,"border-right-width":t.right,"border-bottom-width":t.bottom,"border-left-width":t.left}));var a=o.getRoot();for(var l in a.controlIdLookup||(a.controlIdLookup={}),(a.controlIdLookup[o._id]=o)._aria)o.aria(l,o._aria[l]);!1===o.state.get("visible")&&(o.getEl().style.display="none"),o.bindStates(),o.state.on("change:visible",function(e){var t,n=e.value;o.state.get("rendered")&&(o.getEl().style.display=!1===n?"none":"",o.getEl().getBoundingClientRect()),(t=o.parent())&&(t._lastRect=null),o.fire(n?"show":"hide"),Ke.add(o)}),o.fire("postrender",{},!1)},bindStates:function(){},scrollIntoView:function(e){var t,n,i,r,o,s,a=this.getEl(),l=a.parentNode,u=function(e,t){var n,i,r=e;for(n=i=0;r&&r!==t&&r.nodeType;)n+=r.offsetLeft||0,i+=r.offsetTop||0,r=r.offsetParent;return{x:n,y:i}}(a,l);return t=u.x,n=u.y,i=a.offsetWidth,r=a.offsetHeight,o=l.clientWidth,s=l.clientHeight,"end"===e?(t-=o-i,n-=s-r):"center"===e&&(t-=o/2-i/2,n-=s/2-r/2),l.scrollLeft=t,l.scrollTop=n,this},getRoot:function(){for(var e,t=this,n=[];t;){if(t.rootControl){e=t.rootControl;break}n.push(t),t=(e=t).parent()}e||(e=this);for(var i=n.length;i--;)n[i].rootControl=e;return e},reflow:function(){Ke.remove(this);var e=this.parent();return e&&e._layout&&!e._layout.isNative()&&e.reflow(),this}};function nt(n){return n._eventDispatcher||(n._eventDispatcher=new Te({scope:n,toggleEvent:function(e,t){t&&Te.isNative(e)&&(n._nativeEvents||(n._nativeEvents={}),n._nativeEvents[e]=!0,n.state.get("rendered")&&it(n))}})),n._eventDispatcher}function it(a){var e,t,n,l,i,r;function o(e){var t=a.getParentCtrl(e.target);t&&t.fire(e.type,e)}function s(){var e=l._lastHoverCtrl;e&&(e.fire("mouseleave",{target:e.getEl()}),e.parents().each(function(e){e.fire("mouseleave",{target:e.getEl()})}),l._lastHoverCtrl=null)}function u(e){var t,n,i,r=a.getParentCtrl(e.target),o=l._lastHoverCtrl,s=0;if(r!==o){if((n=(l._lastHoverCtrl=r).parents().toArray().reverse()).push(r),o){for((i=o.parents().toArray().reverse()).push(o),s=0;s=t.length&&(e=0),t[e]&&t[e].focus(),e}function h(e,t){var n=-1,i=d();t=t||c(i.getEl());for(var r=0;r
    '+(e.settings.html||"")+t.renderHtml(e)+"
    "},postRender:function(){var e,t=this;return t.items().exec("postRender"),t._super(),t._layout.postRender(t),t.state.set("rendered",!0),t.settings.style&&t.$el.css(t.settings.style),t.settings.border&&(e=t.borderBox,t.$el.css({"border-top-width":e.top,"border-right-width":e.right,"border-bottom-width":e.bottom,"border-left-width":e.left})),t.parent()||(t.keyboardNav=st({root:t})),t},initLayoutRect:function(){var e=this._super();return this._layout.recalc(this),e},recalc:function(){var e=this,t=e._layoutRect,n=e._lastRect;if(!n||n.w!==t.w||n.h!==t.h)return e._layout.recalc(e),t=e.layoutRect(),e._lastRect={x:t.x,y:t.y,w:t.w,h:t.h},!0},reflow:function(){var e;if(Ke.remove(this),this.visible()){for(rt.repaintControls=[],rt.repaintControls.map={},this.recalc(),e=rt.repaintControls.length;e--;)rt.repaintControls[e].repaint();"flow"!==this.settings.layout&&"stack"!==this.settings.layout&&this.repaint(),rt.repaintControls=[]}return this}});function ut(e){var t,n;if(e.changedTouches)for(t="screenX screenY pageX pageY clientX clientY".split(" "),n=0;n").css({position:"absolute",top:0,left:0,width:f.width,height:f.height,zIndex:2147483647,opacity:1e-4,cursor:d}).appendTo(x.body),ye(x).on("mousemove touchmove",v).on("mouseup touchend",p),h.start(e)},v=function(e){if(ut(e),e.button!==g)return p(e);e.deltaX=e.screenX-b,e.deltaY=e.screenY-y,e.preventDefault(),h.drag(e)},p=function(e){ut(e),ye(x).off("mousemove touchmove",v).off("mouseup touchend",p),m.remove(),h.stop&&h.stop(e)},this.destroy=function(){ye(w).off()},ye(w).on("mousedown touchstart",t)}var dt,ft,ht,mt,gt={init:function(){this.on("repaint",this.renderScroll)},renderScroll:function(){var p=this,v=2;function n(){var m,g,e;function t(e,t,n,i,r,o){var s,a,l,u,c,d,f,h;if(a=p.getEl("scroll"+e)){if(f=t.toLowerCase(),h=n.toLowerCase(),ye(p.getEl("absend")).css(f,p.layoutRect()[i]-1),!r)return void ye(a).css("display","none");ye(a).css("display","block"),s=p.getEl("body"),l=p.getEl("scroll"+e+"t"),u=s["client"+n]-2*v,c=(u-=m&&g?a["client"+o]:0)/s["scroll"+n],(d={})[f]=s["offset"+t]+v,d[h]=u,ye(a).css(d),(d={})[f]=s["scroll"+t]*c,d[h]=u*c,ye(l).css(d)}}e=p.getEl("body"),m=e.scrollWidth>e.clientWidth,g=e.scrollHeight>e.clientHeight,t("h","Left","Width","contentW",m,"Height"),t("v","Top","Height","contentH",g,"Width")}p.settings.autoScroll&&(p._hasScroll||(p._hasScroll=!0,function(){function e(s,a,l,u,c){var d,e=p._id+"-scroll"+s,t=p.classPrefix;ye(p.getEl()).append('
    '),p.draghelper=new ct(e+"t",{start:function(){d=p.getEl("body")["scroll"+a],ye("#"+e).addClass(t+"active")},drag:function(e){var t,n,i,r,o=p.layoutRect();n=o.contentW>o.innerW,i=o.contentH>o.innerH,r=p.getEl("body")["client"+l]-2*v,t=(r-=n&&i?p.getEl("scroll"+s)["client"+c]:0)/p.getEl("body")["scroll"+l],p.getEl("body")["scroll"+a]=d+e["delta"+u]/t},stop:function(){ye("#"+e).removeClass(t+"active")}})}p.classes.add("scroll"),e("v","Top","Height","Y","Width"),e("h","Left","Width","X","Height")}(),p.on("wheel",function(e){var t=p.getEl("body");t.scrollLeft+=10*(e.deltaX||0),t.scrollTop+=10*e.deltaY,n()}),ye(p.getEl("body")).on("scroll",n)),n())}},pt=lt.extend({Defaults:{layout:"fit",containerCls:"panel"},Mixins:[gt],renderHtml:function(){var e=this,t=e._layout,n=e.settings.html;return e.preRender(),t.preRender(e),void 0===n?n='
    '+t.renderHtml(e)+"
    ":("function"==typeof n&&(n=n.call(e)),e._hasBody=!1),'
    '+(e._preBodyHtml||"")+n+"
    "}}),vt={resizeToContent:function(){this._layoutRect.autoResize=!0,this._lastRect=null,this.reflow()},resizeTo:function(e,t){if(e<=1||t<=1){var n=we.getWindowSize();e=e<=1?e*n.w:e,t=t<=1?t*n.h:t}return this._layoutRect.autoResize=!1,this.layoutRect({minW:e,minH:t,w:e,h:t}).reflow()},resizeBy:function(e,t){var n=this.layoutRect();return this.resizeTo(n.w+e,n.h+t)}},bt=[],yt=[];function xt(e,t){for(;e;){if(e===t)return!0;e=e.parent()}}function wt(){dt||(dt=function(e){2!==e.button&&function(e){for(var t=bt.length;t--;){var n=bt[t],i=n.getParentCtrl(e.target);if(n.settings.autohide){if(i&&(xt(i,n)||n.parent()===i))continue;(e=n.fire("autohide",{target:e.target})).isDefaultPrevented()||n.hide()}}}(e)},ye(_.document).on("click touchstart",dt))}function _t(r){var e=we.getViewPort().y;function t(e,t){for(var n,i=0;ie&&(r.fixed(!1).layoutRect({y:r._autoFixY}).repaint(),t(!1,r._autoFixY-e)):(r._autoFixY=r.layoutRect().y,r._autoFixY').appendTo(i.getContainerElm())),u.setTimeout(function(){t.addClass(n+"in"),ye(i.getEl()).addClass(n+"in")}),mt=!0),Rt(!0,i)}}),i.on("show",function(){i.parents().each(function(e){if(e.state.get("fixed"))return i.fixed(!0),!1})}),e.popover&&(i._preBodyHtml='
    ',i.classes.add("popover").add("bottom").add(i.isRtl()?"end":"start")),i.aria("label",e.ariaLabel),i.aria("labelledby",i._id),i.aria("describedby",i.describedBy||i._id+"-none")},fixed:function(e){var t=this;if(t.state.get("fixed")!==e){if(t.state.get("rendered")){var n=we.getViewPort();e?t.layoutRect().y-=n.y:t.layoutRect().y+=n.y}t.classes.toggle("fixed",e),t.state.set("fixed",e)}return t},show:function(){var e,t=this._super();for(e=bt.length;e--&&bt[e]!==this;);return-1===e&&bt.push(this),t},hide:function(){return Et(this),Rt(!1,this),this._super()},hideAll:function(){Ct.hideAll()},close:function(){return this.fire("close").isDefaultPrevented()||(this.remove(),Rt(!1,this)),this},remove:function(){Et(this),this._super()},postRender:function(){return this.settings.bodyRole&&this.getEl("body").setAttribute("role",this.settings.bodyRole),this._super()}});function Et(e){var t;for(t=bt.length;t--;)bt[t]===e&&bt.splice(t,1);for(t=yt.length;t--;)yt[t]===e&&yt.splice(t,1)}Ct.hideAll=function(){for(var e=bt.length;e--;){var t=bt[e];t&&t.settings.autohide&&(t.hide(),bt.splice(e,1))}};var kt=function(s,n,e){var a,i,l=p.DOM,t=s.getParam("fixed_toolbar_container");t&&(i=l.select(t)[0]);var r=function(){if(a&&a.moveRel&&a.visible()&&!a._fixed){var e=s.selection.getScrollContainer(),t=s.getBody(),n=0,i=0;if(e){var r=l.getPos(t),o=l.getPos(e);n=Math.max(0,o.x-r.x),i=Math.max(0,o.y-r.y)}a.fixed(!1).moveRel(t,s.rtl?["tr-br","br-tr"]:["tl-bl","bl-tl","tr-br"]).moveBy(n,i)}},o=function(){a&&(a.show(),r(),l.addClass(s.getBody(),"mce-edit-focus"))},u=function(){a&&(a.hide(),Ct.hideAll(),l.removeClass(s.getBody(),"mce-edit-focus"))},c=function(){var e,t;a?a.visible()||o():(a=n.panel=v.create({type:i?"panel":"floatpanel",role:"application",classes:"tinymce tinymce-inline",layout:"flex",direction:"column",align:"stretch",autohide:!1,autofix:!0,fixed:(e=i,t=s,!(!e||t.settings.ui_container)),border:1,items:[!1===d(s)?null:{type:"menubar",border:"0 0 1 0",items:re(s)},A(s,f(s))]}),W.setUiContainer(s,a),x(s),i?a.renderTo(i).reflow():a.renderTo().reflow(),R(s,a),o(),F(s),s.on("nodeChange",r),s.on("ResizeWindow",r),s.on("activate",o),s.on("deactivate",u),s.nodeChanged())};return s.settings.content_editable=!0,s.on("focus",function(){!1===m(s)&&e.skinUiCss?l.styleSheetLoader.load(e.skinUiCss,c,c):c()}),s.on("blur hide",u),s.on("remove",function(){a&&(a.remove(),a=null)}),!1===m(s)&&e.skinUiCss?l.styleSheetLoader.load(e.skinUiCss,ge(s)):ge(s)(),{}};function Ht(i,r){var o,s,a=this,l=rt.classPrefix;a.show=function(e,t){function n(){o&&(ye(i).append('
    '),t&&t())}return a.hide(),o=!0,e?s=u.setTimeout(n,e):n(),a},a.hide=function(){var e=i.lastChild;return u.clearTimeout(s),e&&-1!==e.className.indexOf("throbber")&&e.parentNode.removeChild(e),o=!1,a}}var St=function(e,t){var n;e.on("ProgressState",function(e){n=n||new Ht(t.panel.getEl("body")),e.state?n.show(e.time):n.hide()})},Tt=function(e,t,n){var i=function(e){var t=e.settings,n=t.skin,i=t.skin_url;if(!1!==n){var r=n||"lightgray";i=i?e.documentBaseURI.toAbsolute(i):l.baseURL+"/skins/"+r}return i}(e);return i&&(n.skinUiCss=i+"/skin.min.css",e.contentCSS.push(i+"/content"+(e.inline?".inline":"")+".min.css")),St(e,t),e.getParam("inline",!1,"boolean")?kt(e,t,n):be(e,t,n)},Mt=rt.extend({Mixins:[He],Defaults:{classes:"widget tooltip tooltip-n"},renderHtml:function(){var e=this,t=e.classPrefix;return'"},bindStates:function(){var t=this;return t.state.on("change:text",function(e){t.getEl().lastChild.innerHTML=t.encode(e.value)}),t._super()},repaint:function(){var e,t;e=this.getEl().style,t=this._layoutRect,e.left=t.x+"px",e.top=t.y+"px",e.zIndex=131070}}),Nt=rt.extend({init:function(i){var r=this;r._super(i),i=r.settings,r.canFocus=!0,i.tooltip&&!1!==Nt.tooltips&&(r.on("mouseenter",function(e){var t=r.tooltip().moveTo(-65535);if(e.control===r){var n=t.text(i.tooltip).show().testMoveRel(r.getEl(),["bc-tc","bc-tl","bc-tr"]);t.classes.toggle("tooltip-n","bc-tc"===n),t.classes.toggle("tooltip-nw","bc-tl"===n),t.classes.toggle("tooltip-ne","bc-tr"===n),t.moveRel(r.getEl(),n)}else t.hide()}),r.on("mouseleave mousedown click",function(){r.tooltip().remove(),r._tooltip=null})),r.aria("label",i.ariaLabel||i.tooltip)},tooltip:function(){return this._tooltip||(this._tooltip=new Mt({type:"tooltip"}),W.inheritUiContainer(this,this._tooltip),this._tooltip.renderTo()),this._tooltip},postRender:function(){var e=this,t=e.settings;e._super(),e.parent()||!t.width&&!t.height||(e.initLayoutRect(),e.repaint()),t.autofocus&&e.focus()},bindStates:function(){var t=this;function n(e){t.aria("disabled",e),t.classes.toggle("disabled",e)}function i(e){t.aria("pressed",e),t.classes.toggle("active",e)}return t.state.on("change:disabled",function(e){n(e.value)}),t.state.on("change:active",function(e){i(e.value)}),t.state.get("disabled")&&n(!0),t.state.get("active")&&i(!0),t._super()},remove:function(){this._super(),this._tooltip&&(this._tooltip.remove(),this._tooltip=null)}}),Pt=Nt.extend({Defaults:{value:0},init:function(e){this._super(e),this.classes.add("progress"),this.settings.filter||(this.settings.filter=function(e){return Math.round(e)})},renderHtml:function(){var e=this._id,t=this.classPrefix;return'
    0%
    '},postRender:function(){return this._super(),this.value(this.settings.value),this},bindStates:function(){var t=this;function n(e){e=t.settings.filter(e),t.getEl().lastChild.innerHTML=e+"%",t.getEl().firstChild.firstChild.style.width=e+"%"}return t.state.on("change:value",function(e){n(e.value)}),n(t.state.get("value")),t._super()}}),Wt=function(e,t){e.getEl().lastChild.textContent=t+(e.progressBar?" "+e.progressBar.value()+"%":"")},Dt=rt.extend({Mixins:[He],Defaults:{classes:"widget notification"},init:function(e){var t=this;t._super(e),t.maxWidth=e.maxWidth,e.text&&t.text(e.text),e.icon&&(t.icon=e.icon),e.color&&(t.color=e.color),e.type&&t.classes.add("notification-"+e.type),e.timeout&&(e.timeout<0||0'),e=' style="max-width: '+t.maxWidth+"px;"+(t.color?"background-color: "+t.color+';"':'"'),t.closeButton&&(r=''),t.progressBar&&(o=t.progressBar.renderHtml()),''},postRender:function(){var e=this;return u.setTimeout(function(){e.$el.addClass(e.classPrefix+"in"),Wt(e,e.state.get("text"))},100),e._super()},bindStates:function(){var t=this;return t.state.on("change:text",function(e){t.getEl().firstChild.innerHTML=e.value,Wt(t,e.value)}),t.progressBar&&(t.progressBar.bindStates(),t.progressBar.state.on("change:value",function(e){Wt(t,t.state.get("text"))})),t._super()},close:function(){return this.fire("close").isDefaultPrevented()||this.remove(),this},repaint:function(){var e,t;e=this.getEl().style,t=this._layoutRect,e.left=t.x+"px",e.top=t.y+"px",e.zIndex=65534}});function Ot(o){var s=function(e){return e.inline?e.getElement():e.getContentAreaContainer()};return{open:function(e,t){var n,i=w.extend(e,{maxWidth:(n=s(o),we.getSize(n).width)}),r=new Dt(i);return 0<(r.args=i).timeout&&(r.timer=setTimeout(function(){r.close(),t()},i.timeout)),r.on("close",function(){t()}),r.renderTo(),r},close:function(e){e.close()},reposition:function(e){K(e,function(e){e.moveTo(0,0)}),function(n){if(0e.w&&(n=e.x-Math.max(0,t/2),r.layoutRect({w:t,x:n}),i=!0),o&&(o.layoutRect({w:r.layoutRect().innerW}).recalc(),(t=o.layoutRect().minW+e.deltaW)>e.w&&(n=e.x-Math.max(0,t-e.w),r.layoutRect({w:t,x:n}),i=!0)),i&&r.recalc()},initLayoutRect:function(){var e,t=this,n=t._super(),i=0;if(t.settings.title&&!t._fullscreen){e=t.getEl("head");var r=we.getSize(e);n.headerW=r.width,n.headerH=r.height,i+=n.headerH}t.statusbar&&(i+=t.statusbar.layoutRect().h),n.deltaH+=i,n.minH+=i,n.h+=i;var o=we.getWindowSize();return n.x=t.settings.x||Math.max(0,o.w/2-n.w/2),n.y=t.settings.y||Math.max(0,o.h/2-n.h/2),n},renderHtml:function(){var e=this,t=e._layout,n=e._id,i=e.classPrefix,r=e.settings,o="",s="",a=r.html;return e.preRender(),t.preRender(e),r.title&&(o='
    '+e.encode(r.title)+'
    '),r.url&&(a=''),void 0===a&&(a=t.renderHtml(e)),e.statusbar&&(s=e.statusbar.renderHtml()),'
    '+o+'
    '+a+"
    "+s+"
    "},fullscreen:function(e){var n,t,i=this,r=_.document.documentElement,o=i.classPrefix;if(e!==i._fullscreen)if(ye(_.window).on("resize",function(){var e;if(i._fullscreen)if(n)i._timer||(i._timer=u.setTimeout(function(){var e=we.getWindowSize();i.moveTo(0,0).resizeTo(e.w,e.h),i._timer=0},50));else{e=(new Date).getTime();var t=we.getWindowSize();i.moveTo(0,0).resizeTo(t.w,t.h),50<(new Date).getTime()-e&&(n=!0)}}),t=i.layoutRect(),i._fullscreen=e){i._initial={x:t.x,y:t.y,w:t.w,h:t.h},i.borderBox=Me("0"),i.getEl("head").style.display="none",t.deltaH-=t.headerH+2,ye([r,_.document.body]).addClass(o+"fullscreen"),i.classes.add("fullscreen");var s=we.getWindowSize();i.moveTo(0,0).resizeTo(s.w,s.h)}else i.borderBox=Me(i.settings.border),i.getEl("head").style.display="",t.deltaH+=t.headerH,ye([r,_.document.body]).removeClass(o+"fullscreen"),i.classes.remove("fullscreen"),i.moveTo(i._initial.x,i._initial.y).resizeTo(i._initial.w,i._initial.h);return i.reflow()},postRender:function(){var t,n=this;setTimeout(function(){n.classes.add("in"),n.fire("open")},0),n._super(),n.statusbar&&n.statusbar.postRender(),n.focus(),this.dragHelper=new ct(n._id+"-dragh",{start:function(){t={x:n.layoutRect().x,y:n.layoutRect().y}},drag:function(e){n.moveTo(t.x+e.deltaX,t.y+e.deltaY)}}),n.on("submit",function(e){e.isDefaultPrevented()||n.close()}),At.push(n),Lt(!0)},submit:function(){return this.fire("submit",{data:this.toJSON()})},remove:function(){var e,t=this;for(t.dragHelper.destroy(),t._super(),t.statusbar&&this.statusbar.remove(),zt(t.classPrefix,!1),e=At.length;e--;)At[e]===t&&At.splice(e,1);Lt(0'+this._super(e)}}),jt=Nt.extend({Defaults:{classes:"widget btn",role:"button"},init:function(e){var t,n=this;n._super(e),e=n.settings,t=n.settings.size,n.on("click mousedown",function(e){e.preventDefault()}),n.on("touchstart",function(e){n.fire("click",e),e.preventDefault()}),e.subtype&&n.classes.add(e.subtype),t&&n.classes.add("btn-"+t),e.icon&&n.icon(e.icon)},icon:function(e){return arguments.length?(this.state.set("icon",e),this):this.state.get("icon")},repaint:function(){var e,t=this.getEl().firstChild;t&&((e=t.style).width=e.height="100%"),this._super()},renderHtml:function(){var e,t,n=this,i=n._id,r=n.classPrefix,o=n.state.get("icon"),s=n.state.get("text"),a="",l=n.settings;return(e=l.image)?(o="none","string"!=typeof e&&(e=_.window.getSelection?e[0]:e[1]),e=" style=\"background-image: url('"+e+"')\""):e="",s&&(n.classes.add("btn-has-text"),a=''+n.encode(s)+""),o=o?r+"ico "+r+"i-"+o:"",t="boolean"==typeof l.active?' aria-pressed="'+l.active+'"':"",'
    "},bindStates:function(){var o=this,n=o.$,i=o.classPrefix+"txt";function s(e){var t=n("span."+i,o.getEl());e?(t[0]||(n("button:first",o.getEl()).append(''),t=n("span."+i,o.getEl())),t.html(o.encode(e))):t.remove(),o.classes.toggle("btn-has-text",!!e)}return o.state.on("change:text",function(e){s(e.value)}),o.state.on("change:icon",function(e){var t=e.value,n=o.classPrefix;t=(o.settings.icon=t)?n+"ico "+n+"i-"+o.settings.icon:"";var i=o.getEl().firstChild,r=i.getElementsByTagName("i")[0];t?(r&&r===i.firstChild||(r=_.document.createElement("i"),i.insertBefore(r,i.firstChild)),r.className=t):r&&i.removeChild(r),s(o.state.get("text"))}),o._super()}}),Jt=jt.extend({init:function(e){e=w.extend({text:"Browse...",multiple:!1,accept:null},e),this._super(e),this.classes.add("browsebutton"),e.multiple&&this.classes.add("multiple")},postRender:function(){var n=this,t=we.create("input",{type:"file",id:n._id+"-browse",accept:n.settings.accept});n._super(),ye(t).on("change",function(e){var t=e.target.files;n.value=function(){return t.length?n.settings.multiple?t:t[0]:null},e.preventDefault(),t.length&&n.fire("change",e)}),ye(t).on("click",function(e){e.stopPropagation()}),ye(n.getEl("button")).on("click touchstart",function(e){e.stopPropagation(),t.click(),e.preventDefault()}),n.getEl().appendChild(t)},remove:function(){ye(this.getEl("button")).off(),ye(this.getEl("input")).off(),this._super()}}),Gt=lt.extend({Defaults:{defaultType:"button",role:"group"},renderHtml:function(){var e=this,t=e._layout;return e.classes.add("btn-group"),e.preRender(),t.preRender(e),'
    '+(e.settings.html||"")+t.renderHtml(e)+"
    "}}),Kt=Nt.extend({Defaults:{classes:"checkbox",role:"checkbox",checked:!1},init:function(e){var t=this;t._super(e),t.on("click mousedown",function(e){e.preventDefault()}),t.on("click",function(e){e.preventDefault(),t.disabled()||t.checked(!t.checked())}),t.checked(t.settings.checked)},checked:function(e){return arguments.length?(this.state.set("checked",e),this):this.state.get("checked")},value:function(e){return arguments.length?this.checked(e):this.checked()},renderHtml:function(){var e=this,t=e._id,n=e.classPrefix;return'
    '+e.encode(e.state.get("text"))+"
    "},bindStates:function(){var o=this;function t(e){o.classes.toggle("checked",e),o.aria("checked",e)}return o.state.on("change:text",function(e){o.getEl("al").firstChild.data=o.translate(e.value)}),o.state.on("change:checked change:value",function(e){o.fire("change"),t(e.value)}),o.state.on("change:icon",function(e){var t=e.value,n=o.classPrefix;if(void 0===t)return o.settings.icon;t=(o.settings.icon=t)?n+"ico "+n+"i-"+o.settings.icon:"";var i=o.getEl().firstChild,r=i.getElementsByTagName("i")[0];t?(r&&r===i.firstChild||(r=_.document.createElement("i"),i.insertBefore(r,i.firstChild)),r.className=t):r&&i.removeChild(r)}),o.state.get("checked")&&t(!0),o._super()}}),Zt=tinymce.util.Tools.resolve("tinymce.util.VK"),Qt=Nt.extend({init:function(i){var r=this;r._super(i),i=r.settings,r.classes.add("combobox"),r.subinput=!0,r.ariaTarget="inp",i.menu=i.menu||i.values,i.menu&&(i.icon="caret"),r.on("click",function(e){var t=e.target,n=r.getEl();if(ye.contains(n,t)||t===n)for(;t&&t!==n;)t.id&&-1!==t.id.indexOf("-open")&&(r.fire("action"),i.menu&&(r.showMenu(),e.aria&&r.menu.items()[0].focus())),t=t.parentNode}),r.on("keydown",function(e){var t;13===e.keyCode&&"INPUT"===e.target.nodeName&&(e.preventDefault(),r.parents().reverse().each(function(e){if(e.toJSON)return t=e,!1}),r.fire("submit",{data:t.toJSON()}))}),r.on("keyup",function(e){if("INPUT"===e.target.nodeName){var t=r.state.get("value"),n=e.target.value;n!==t&&(r.state.set("value",n),r.fire("autocomplete",e))}}),r.on("mouseover",function(e){var t=r.tooltip().moveTo(-65535);if(r.statusLevel()&&-1!==e.target.className.indexOf(r.classPrefix+"status")){var n=r.statusMessage()||"Ok",i=t.text(n).show().testMoveRel(e.target,["bc-tc","bc-tl","bc-tr"]);t.classes.toggle("tooltip-n","bc-tc"===i),t.classes.toggle("tooltip-nw","bc-tl"===i),t.classes.toggle("tooltip-ne","bc-tr"===i),t.moveRel(e.target,i)}})},statusLevel:function(e){return 0
    "),'
    '},postRender:function(){var t=this,n=t.settings.onclick;return t.on("click",function(e){e.aria&&"down"===e.aria.key||e.control!==t||nn.getParent(e.target,"."+t.classPrefix+"open")||(e.stopImmediatePropagation(),n.call(t,e))}),delete t.settings.onclick,t._super()}}),on=tinymce.util.Tools.resolve("tinymce.util.Color"),sn=Nt.extend({Defaults:{classes:"widget colorpicker"},init:function(e){this._super(e)},postRender:function(){var n,i,r,o,s,a=this,l=a.color();function u(e,t){var n,i,r=we.getPos(e);return n=t.pageX-r.x,i=t.pageY-r.y,{x:n=Math.max(0,Math.min(n/e.clientWidth,1)),y:i=Math.max(0,Math.min(i/e.clientHeight,1))}}function c(e,t){var n=(360-e.h)/360;we.css(r,{top:100*n+"%"}),t||we.css(s,{left:e.s+"%",top:100-e.v+"%"}),o.style.background=on({s:100,v:100,h:e.h}).toHex(),a.color().parse({s:e.s,v:e.v,h:e.h})}function e(e){var t;t=u(o,e),n.s=100*t.x,n.v=100*(1-t.y),c(n),a.fire("change")}function t(e){var t;t=u(i,e),(n=l.toHsv()).h=360*(1-t.y),c(n,!0),a.fire("change")}i=a.getEl("h"),r=a.getEl("hp"),o=a.getEl("sv"),s=a.getEl("svp"),a._repaint=function(){c(n=l.toHsv())},a._super(),a._svdraghelper=new ct(a._id+"-sv",{start:e,drag:e}),a._hdraghelper=new ct(a._id+"-h",{start:t,drag:t}),a._repaint()},rgb:function(){return this.color().toRgb()},value:function(e){if(!arguments.length)return this.color().toHex();this.color().parse(e),this._rendered&&this._repaint()},color:function(){return this._color||(this._color=on()),this._color},renderHtml:function(){var e,t=this._id,o=this.classPrefix,s="#ff0000,#ff0080,#ff00ff,#8000ff,#0000ff,#0080ff,#00ffff,#00ff80,#00ff00,#80ff00,#ffff00,#ff8000,#ff0000";return e='
    '+function(){var e,t,n,i,r="";for(n="filter:progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr=",e=0,t=(i=s.split(",")).length-1;e
    ';return r}()+'
    ','
    '+e+"
    "}}),an=Nt.extend({init:function(e){e=w.extend({height:100,text:"Drop an image here",multiple:!1,accept:null},e),this._super(e),this.classes.add("dropzone"),e.multiple&&this.classes.add("multiple")},renderHtml:function(){var e,t,n=this.settings;return e={id:this._id,hidefocus:"1"},t=we.create("div",e,""+this.translate(n.text)+""),n.height&&we.css(t,"height",n.height+"px"),n.width&&we.css(t,"width",n.width+"px"),t.className=this.classes,t.outerHTML},postRender:function(){var i=this,e=function(e){e.preventDefault(),i.classes.toggle("dragenter"),i.getEl().className=i.classes};i._super(),i.$el.on("dragover",function(e){e.preventDefault()}),i.$el.on("dragenter",e),i.$el.on("dragleave",e),i.$el.on("drop",function(e){if(e.preventDefault(),!i.state.get("disabled")){var t=function(e){var t=i.settings.accept;if("string"!=typeof t)return e;var n=new RegExp("("+t.split(/\s*,\s*/).join("|")+")$","i");return w.grep(e,function(e){return n.test(e.name)})}(e.dataTransfer.files);i.value=function(){return t.length?i.settings.multiple?t:t[0]:null},t.length&&i.fire("change",e)}})},remove:function(){this.$el.off(),this._super()}}),ln=Nt.extend({init:function(e){var n=this;e.delimiter||(e.delimiter="\xbb"),n._super(e),n.classes.add("path"),n.canFocus=!0,n.on("click",function(e){var t;(t=e.target.getAttribute("data-index"))&&n.fire("select",{value:n.row()[t],index:t})}),n.row(n.settings.row)},focus:function(){return this.getEl().firstChild.focus(),this},row:function(e){return arguments.length?(this.state.set("row",e),this):this.state.get("row")},renderHtml:function(){return'
    '+this._getDataPathHtml(this.state.get("row"))+"
    "},bindStates:function(){var t=this;return t.state.on("change:row",function(e){t.innerHtml(t._getDataPathHtml(e.value))}),t._super()},_getDataPathHtml:function(e){var t,n,i=e||[],r="",o=this.classPrefix;for(t=0,n=i.length;t
    "),r=t.settings.icon?i+"ico "+i+"i-"+r:"",t.aria("role",t.parent()instanceof tr?"menuitem":"button"),'
    '},postRender:function(){var r=this;return r.on("click",function(e){e.control===r&&function(e,t){for(;e;){if(t===e)return!0;e=e.parentNode}return!1}(e.target,r.getEl())&&(r.focus(),r.showMenu(!e.aria),e.aria&&r.menu.items().filter(":visible")[0].focus())}),r.on("mouseenter",function(e){var t,n=e.control,i=r.parent();n&&i&&n instanceof nr&&n.parent()===i&&(i.items().filter("MenuButton").each(function(e){e.hideMenu&&e!==n&&(e.menu&&e.menu.visible()&&(t=!0),e.hideMenu())}),t&&(n.focus(),n.showMenu()))}),r._super()},bindStates:function(){var e=this;return e.state.on("change:menu",function(){e.menu&&e.menu.remove(),e.menu=null}),e._super()},remove:function(){this._super(),this.menu&&this.menu.remove()}}),ir=Ct.extend({Defaults:{defaultType:"menuitem",border:1,layout:"stack",role:"application",bodyRole:"menu",ariaRoot:!0},init:function(e){if(e.autohide=!0,e.constrainToViewport=!0,"function"==typeof e.items&&(e.itemsFactory=e.items,e.items=[]),e.itemDefaults)for(var t=e.items,n=t.length;n--;)t[n]=w.extend({},e.itemDefaults,t[n]);this._super(e),this.classes.add("menu"),e.animate&&11!==ce.ie&&this.classes.add("animate")},repaint:function(){return this.classes.toggle("menu-align",!0),this._super(),this.getEl().style.height="",this.getEl("body").style.height="",this},cancel:function(){this.hideAll(),this.fire("select")},load:function(){var t,n=this;function i(){n.throbber&&(n.throbber.hide(),n.throbber=null)}n.settings.itemsFactory&&(n.throbber||(n.throbber=new Ht(n.getEl("body"),!0),0===n.items().length?(n.throbber.show(),n.fire("loading")):n.throbber.show(100,function(){n.items().remove(),n.fire("loading")}),n.on("hide close",i)),n.requestTime=t=(new Date).getTime(),n.settings.itemsFactory(function(e){0!==e.length?n.requestTime===t&&(n.getEl().style.width="",n.getEl("body").style.width="",i(),n.items().remove(),n.getEl("body").innerHTML="",n.add(e),n.renderNew(),n.fire("loaded")):n.hide()}))},hideAll:function(){return this.find("menuitem").exec("hideMenu"),this._super()},preRender:function(){var n=this;return n.items().each(function(e){var t=e.settings;if(t.icon||t.image||t.selectable)return!(n._hasIcons=!0)}),n.settings.itemsFactory&&n.on("postrender",function(){n.settings.itemsFactory&&n.load()}),n.on("show hide",function(e){e.control===n&&("show"===e.type?u.setTimeout(function(){n.classes.add("in")},0):n.classes.remove("in"))}),n._super()}}),rr=nr.extend({init:function(i){var t,r,o,n,s=this;s._super(i),i=s.settings,s._values=t=i.values,t&&("undefined"!=typeof i.value&&function e(t){for(var n=0;n").replace(new RegExp(c("]mce~match!"),"g"),"")}return s&&t.parent().classes.add("menu-has-icons"),i.image&&(a=" style=\"background-image: url('"+i.image+"')\""),l&&(l=function(e){var t,n,i={};for(i=ce.mac?{alt:"⌥",ctrl:"⌘",shift:"⇧",meta:"⌘"}:{meta:"Ctrl"},e=e.split("+"),t=0;t\xa0":"",o=f(t.encode(d(o))),u=f(t.encode(d(u))),'
    '+e+("-"!==o?''+o+"":"")+(l?'
    '+l+"
    ":"")+(i.menu?'
    ':"")+(u?'":"")+"
    "},postRender:function(){var t=this,n=t.settings,e=n.textStyle;if("function"==typeof e&&(e=e.call(this)),e){var i=t.getEl("text");i&&(i.setAttribute("style",e),t._textStyle=e)}return t.on("mouseenter click",function(e){e.control===t&&(n.menu||"click"!==e.type?(t.showMenu(),e.aria&&t.menu.focus(!0)):(t.fire("select"),u.requestAnimationFrame(function(){t.parent().hideAll()})))}),t._super(),t},hover:function(){return this.parent().items().each(function(e){e.classes.remove("selected")}),this.classes.toggle("selected",!0),this},active:function(e){return function(e,t){var n=e._textStyle;if(n){var i=e.getEl("text");i.setAttribute("style",n),t&&(i.style.color="",i.style.backgroundColor="")}}(this,e),void 0!==e&&this.aria("checked",e),this._super(e)},remove:function(){this._super(),this.menu&&this.menu.remove()}}),sr=Kt.extend({Defaults:{classes:"radio",role:"radio"}}),ar=Nt.extend({renderHtml:function(){var e=this,t=e.classPrefix;return e.classes.add("resizehandle"),"both"===e.settings.direction&&e.classes.add("resizehandle-both"),e.canFocus=!1,'
    '},postRender:function(){var t=this;t._super(),t.resizeDragHelper=new ct(this._id,{start:function(){t.fire("ResizeStart")},drag:function(e){"both"!==t.settings.direction&&(e.deltaX=0),t.fire("Resize",e)},stop:function(){t.fire("ResizeEnd")}})},remove:function(){return this.resizeDragHelper&&this.resizeDragHelper.destroy(),this._super()}});function lr(e){var t="";if(e)for(var n=0;n'+e[n]+"";return t}var ur=Nt.extend({Defaults:{classes:"selectbox",role:"selectbox",options:[]},init:function(e){var n=this;n._super(e),n.settings.size&&(n.size=n.settings.size),n.settings.options&&(n._options=n.settings.options),n.on("keydown",function(e){var t;13===e.keyCode&&(e.preventDefault(),n.parents().reverse().each(function(e){if(e.toJSON)return t=e,!1}),n.fire("submit",{data:t.toJSON()}))})},options:function(e){return arguments.length?(this.state.set("options",e),this):this.state.get("options")},renderHtml:function(){var e,t=this,n="";return e=lr(t._options),t.size&&(n=' size = "'+t.size+'"'),'"},bindStates:function(){var t=this;return t.state.on("change:options",function(e){t.getEl().innerHTML=lr(e.value)}),t._super()}});function cr(e,t,n){return e
    '},reset:function(){this.value(this._initValue).repaint()},postRender:function(){var e,t,n,i,r,o,s,a,l,u,c,d,f,h,m=this;e=m._minValue,t=m._maxValue,"v"===m.settings.orientation?(n="screenY",i="top",r="height",o="h"):(n="screenX",i="left",r="width",o="w"),m._super(),function(o,s){function t(e){var t,n,i,r;t=cr(t=(((t=m.value())+(r=n=o))/((i=s)-r)+.05*e)*(i-n)-n,o,s),m.value(t),m.fire("dragstart",{value:t}),m.fire("drag",{value:t}),m.fire("dragend",{value:t})}m.on("keydown",function(e){switch(e.keyCode){case 37:case 38:t(-1);break;case 39:case 40:t(1)}})}(e,t),s=e,a=t,l=m.getEl("handle"),m._dragHelper=new ct(m._id,{handle:m._id+"-handle",start:function(e){u=e[n],c=parseInt(m.getEl("handle").style[i],10),d=(m.layoutRect()[o]||100)-we.getSize(l)[r],m.fire("dragstart",{value:h})},drag:function(e){var t=e[n]-u;f=cr(c+t,0,d),l.style[i]=f+"px",h=s+f/d*(a-s),m.value(h),m.tooltip().text(""+m.settings.previewFilter(h)).show().moveRel(l,"bc tc"),m.fire("drag",{value:h})},stop:function(){m.tooltip().hide(),m.fire("dragend",{value:h})}})},repaint:function(){this._super(),fr(this,this.value())},bindStates:function(){var t=this;return t.state.on("change:value",function(e){fr(t,e.value)}),t._super()}}),mr=Nt.extend({renderHtml:function(){return this.classes.add("spacer"),this.canFocus=!1,'
    '}}),gr=nr.extend({Defaults:{classes:"widget btn splitbtn",role:"button"},repaint:function(){var e,t,n=this.getEl(),i=this.layoutRect();return this._super(),e=n.firstChild,t=n.lastChild,ye(e).css({width:i.w-we.getSize(t).width,height:i.h-2}),ye(t).css({height:i.h-2}),this},activeMenu:function(e){ye(this.getEl().lastChild).toggleClass(this.classPrefix+"active",e)},renderHtml:function(){var e,t,n=this,i=n._id,r=n.classPrefix,o=n.state.get("icon"),s=n.state.get("text"),a=n.settings,l="";return(e=a.image)?(o="none","string"!=typeof e&&(e=_.window.getSelection?e[0]:e[1]),e=" style=\"background-image: url('"+e+"')\""):e="",o=a.icon?r+"ico "+r+"i-"+o:"",s&&(n.classes.add("btn-has-text"),l=''+n.encode(s)+""),t="boolean"==typeof a.active?' aria-pressed="'+a.active+'"':"",'
    '},postRender:function(){var n=this.settings.onclick;return this.on("click",function(e){var t=e.target;if(e.control===this)for(;t;){if(e.aria&&"down"!==e.aria.key||"BUTTON"===t.nodeName&&-1===t.className.indexOf("open"))return e.stopImmediatePropagation(),void(n&&n.call(this,e));t=t.parentNode}}),delete this.settings.onclick,this._super()}}),pr=xi.extend({Defaults:{containerClass:"stack-layout",controlClass:"stack-layout-item",endClass:"break"},isNative:function(){return!0}}),vr=pt.extend({Defaults:{layout:"absolute",defaults:{type:"panel"}},activateTab:function(n){var e;this.activeTabId&&(e=this.getEl(this.activeTabId),ye(e).removeClass(this.classPrefix+"active"),e.setAttribute("aria-selected","false")),this.activeTabId="t"+n,(e=this.getEl("t"+n)).setAttribute("aria-selected","true"),ye(e).addClass(this.classPrefix+"active"),this.items()[n].show().fire("showtab"),this.reflow(),this.items().each(function(e,t){n!==t&&e.hide()})},renderHtml:function(){var i=this,e=i._layout,r="",o=i.classPrefix;return i.preRender(),e.preRender(i),i.items().each(function(e,t){var n=i._id+"-t"+t;e.aria("role","tabpanel"),e.aria("labelledby",n),r+='"}),'
    '+r+'
    '+e.renderHtml(i)+"
    "},postRender:function(){var i=this;i._super(),i.settings.activeTab=i.settings.activeTab||0,i.activateTab(i.settings.activeTab),this.on("click",function(e){var t=e.target.parentNode;if(t&&t.id===i._id+"-head")for(var n=t.childNodes.length;n--;)t.childNodes[n]===e.target&&i.activateTab(n)})},initLayoutRect:function(){var e,t,n,i=this;t=(t=we.getSize(i.getEl("head")).width)<0?0:t,n=0,i.items().each(function(e){t=Math.max(t,e.layoutRect().minW),n=Math.max(n,e.layoutRect().minH)}),i.items().each(function(e){e.settings.x=0,e.settings.y=0,e.settings.w=t,e.settings.h=n,e.layoutRect({x:0,y:0,w:t,h:n})});var r=we.getSize(i.getEl("head")).height;return i.settings.minWidth=t,i.settings.minHeight=n+r,(e=i._super()).deltaH+=r,e.innerH=e.h-e.deltaH,e}}),br=Nt.extend({init:function(e){var n=this;n._super(e),n.classes.add("textbox"),e.multiline?n.classes.add("multiline"):(n.on("keydown",function(e){var t;13===e.keyCode&&(e.preventDefault(),n.parents().reverse().each(function(e){if(e.toJSON)return t=e,!1}),n.fire("submit",{data:t.toJSON()}))}),n.on("keyup",function(e){n.state.set("value",e.target.value)}))},repaint:function(){var e,t,n,i,r,o=this,s=0;e=o.getEl().style,t=o._layoutRect,r=o._lastRepaintRect||{};var a=_.document;return!o.settings.multiline&&a.all&&(!a.documentMode||a.documentMode<=8)&&(e.lineHeight=t.h-s+"px"),i=(n=o.borderBox).left+n.right+8,s=n.top+n.bottom+(o.settings.multiline?8:0),t.x!==r.x&&(e.left=t.x+"px",r.x=t.x),t.y!==r.y&&(e.top=t.y+"px",r.y=t.y),t.w!==r.w&&(e.width=t.w-i+"px",r.w=t.w),t.h!==r.h&&(e.height=t.h-s+"px",r.h=t.h),o._lastRepaintRect=r,o.fire("repaint",{},!1),o},renderHtml:function(){var t,e,n=this,i=n.settings;return t={id:n._id,hidefocus:"1"},w.each(["rows","spellcheck","maxLength","size","readonly","min","max","step","list","pattern","placeholder","required","multiple"],function(e){t[e]=i[e]}),n.disabled()&&(t.disabled="disabled"),i.subtype&&(t.type=i.subtype),(e=we.create(i.multiline?"textarea":"input",t)).value=n.state.get("value"),e.className=n.classes.toString(),e.outerHTML},value:function(e){return arguments.length?(this.state.set("value",e),this):(this.state.get("rendered")&&this.state.set("value",this.getEl().value),this.state.get("value"))},postRender:function(){var t=this;t.getEl().value=t.state.get("value"),t._super(),t.$el.on("change",function(e){t.state.set("value",e.target.value),t.fire("change",e)})},bindStates:function(){var t=this;return t.state.on("change:value",function(e){t.getEl().value!==e.value&&(t.getEl().value=e.value)}),t.state.on("change:disabled",function(e){t.getEl().disabled=e.value}),t._super()},remove:function(){this.$el.off(),this._super()}}),yr=function(){return{Selector:Ie,Collection:Ve,ReflowQueue:Ke,Control:rt,Factory:v,KeyboardNavigation:st,Container:lt,DragHelper:ct,Scrollable:gt,Panel:pt,Movable:He,Resizable:vt,FloatPanel:Ct,Window:It,MessageBox:Yt,Tooltip:Mt,Widget:Nt,Progress:Pt,Notification:Dt,Layout:qt,AbsoluteLayout:Xt,Button:jt,ButtonGroup:Gt,Checkbox:Kt,ComboBox:Qt,ColorBox:en,PanelButton:tn,ColorButton:rn,ColorPicker:sn,Path:ln,ElementPath:un,FormItem:cn,Form:dn,FieldSet:fn,FilePicker:vi,FitLayout:bi,FlexLayout:yi,FlowLayout:xi,FormatControls:Ji,GridLayout:Gi,Iframe:Ki,InfoBox:Zi,Label:Qi,Toolbar:er,MenuBar:tr,MenuButton:nr,MenuItem:or,Throbber:Ht,Menu:ir,ListBox:rr,Radio:sr,ResizeHandle:ar,SelectBox:ur,Slider:hr,Spacer:mr,SplitButton:gr,StackLayout:pr,TabPanel:vr,TextBox:br,DropZone:an,BrowseButton:Jt}},xr=function(n){n.ui?w.each(yr(),function(e,t){n.ui[t]=e}):n.ui=yr()};w.each(yr(),function(e,t){v.add(t,e)}),xr(window.tinymce?window.tinymce:{}),r.add("modern",function(e){return Ji.setup(e),$t(e)})}(window); // Source: wp-includes/js/tinymce/plugins/charmap/plugin.min.js !function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),i=function(e,t){return e.fire("insertCustomChar",{chr:t})},l=function(e,t){var a=i(e,t).chr;e.execCommand("mceInsertContent",!1,a)},a=tinymce.util.Tools.resolve("tinymce.util.Tools"),r=function(e){return e.settings.charmap},n=function(e){return e.settings.charmap_append},o=a.isArray,c=function(e){return o(e)?[].concat((t=e,a.grep(t,function(e){return o(e)&&2===e.length}))):"function"==typeof e?e():[];var t},s=function(e){return function(e,t){var a=r(e);a&&(t=c(a));var i=n(e);return i?[].concat(t).concat(c(i)):t}(e,[["160","no-break space"],["173","soft hyphen"],["34","quotation mark"],["162","cent sign"],["8364","euro sign"],["163","pound sign"],["165","yen sign"],["169","copyright sign"],["174","registered sign"],["8482","trade mark sign"],["8240","per mille sign"],["181","micro sign"],["183","middle dot"],["8226","bullet"],["8230","three dot leader"],["8242","minutes / feet"],["8243","seconds / inches"],["167","section sign"],["182","paragraph sign"],["223","sharp s / ess-zed"],["8249","single left-pointing angle quotation mark"],["8250","single right-pointing angle quotation mark"],["171","left pointing guillemet"],["187","right pointing guillemet"],["8216","left single quotation mark"],["8217","right single quotation mark"],["8220","left double quotation mark"],["8221","right double quotation mark"],["8218","single low-9 quotation mark"],["8222","double low-9 quotation mark"],["60","less-than sign"],["62","greater-than sign"],["8804","less-than or equal to"],["8805","greater-than or equal to"],["8211","en dash"],["8212","em dash"],["175","macron"],["8254","overline"],["164","currency sign"],["166","broken bar"],["168","diaeresis"],["161","inverted exclamation mark"],["191","turned question mark"],["710","circumflex accent"],["732","small tilde"],["176","degree sign"],["8722","minus sign"],["177","plus-minus sign"],["247","division sign"],["8260","fraction slash"],["215","multiplication sign"],["185","superscript one"],["178","superscript two"],["179","superscript three"],["188","fraction one quarter"],["189","fraction one half"],["190","fraction three quarters"],["402","function / florin"],["8747","integral"],["8721","n-ary sumation"],["8734","infinity"],["8730","square root"],["8764","similar to"],["8773","approximately equal to"],["8776","almost equal to"],["8800","not equal to"],["8801","identical to"],["8712","element of"],["8713","not an element of"],["8715","contains as member"],["8719","n-ary product"],["8743","logical and"],["8744","logical or"],["172","not sign"],["8745","intersection"],["8746","union"],["8706","partial differential"],["8704","for all"],["8707","there exists"],["8709","diameter"],["8711","backward difference"],["8727","asterisk operator"],["8733","proportional to"],["8736","angle"],["180","acute accent"],["184","cedilla"],["170","feminine ordinal indicator"],["186","masculine ordinal indicator"],["8224","dagger"],["8225","double dagger"],["192","A - grave"],["193","A - acute"],["194","A - circumflex"],["195","A - tilde"],["196","A - diaeresis"],["197","A - ring above"],["256","A - macron"],["198","ligature AE"],["199","C - cedilla"],["200","E - grave"],["201","E - acute"],["202","E - circumflex"],["203","E - diaeresis"],["274","E - macron"],["204","I - grave"],["205","I - acute"],["206","I - circumflex"],["207","I - diaeresis"],["298","I - macron"],["208","ETH"],["209","N - tilde"],["210","O - grave"],["211","O - acute"],["212","O - circumflex"],["213","O - tilde"],["214","O - diaeresis"],["216","O - slash"],["332","O - macron"],["338","ligature OE"],["352","S - caron"],["217","U - grave"],["218","U - acute"],["219","U - circumflex"],["220","U - diaeresis"],["362","U - macron"],["221","Y - acute"],["376","Y - diaeresis"],["562","Y - macron"],["222","THORN"],["224","a - grave"],["225","a - acute"],["226","a - circumflex"],["227","a - tilde"],["228","a - diaeresis"],["229","a - ring above"],["257","a - macron"],["230","ligature ae"],["231","c - cedilla"],["232","e - grave"],["233","e - acute"],["234","e - circumflex"],["235","e - diaeresis"],["275","e - macron"],["236","i - grave"],["237","i - acute"],["238","i - circumflex"],["239","i - diaeresis"],["299","i - macron"],["240","eth"],["241","n - tilde"],["242","o - grave"],["243","o - acute"],["244","o - circumflex"],["245","o - tilde"],["246","o - diaeresis"],["248","o slash"],["333","o macron"],["339","ligature oe"],["353","s - caron"],["249","u - grave"],["250","u - acute"],["251","u - circumflex"],["252","u - diaeresis"],["363","u - macron"],["253","y - acute"],["254","thorn"],["255","y - diaeresis"],["563","y - macron"],["913","Alpha"],["914","Beta"],["915","Gamma"],["916","Delta"],["917","Epsilon"],["918","Zeta"],["919","Eta"],["920","Theta"],["921","Iota"],["922","Kappa"],["923","Lambda"],["924","Mu"],["925","Nu"],["926","Xi"],["927","Omicron"],["928","Pi"],["929","Rho"],["931","Sigma"],["932","Tau"],["933","Upsilon"],["934","Phi"],["935","Chi"],["936","Psi"],["937","Omega"],["945","alpha"],["946","beta"],["947","gamma"],["948","delta"],["949","epsilon"],["950","zeta"],["951","eta"],["952","theta"],["953","iota"],["954","kappa"],["955","lambda"],["956","mu"],["957","nu"],["958","xi"],["959","omicron"],["960","pi"],["961","rho"],["962","final sigma"],["963","sigma"],["964","tau"],["965","upsilon"],["966","phi"],["967","chi"],["968","psi"],["969","omega"],["8501","alef symbol"],["982","pi symbol"],["8476","real part symbol"],["978","upsilon - hook symbol"],["8472","Weierstrass p"],["8465","imaginary part"],["8592","leftwards arrow"],["8593","upwards arrow"],["8594","rightwards arrow"],["8595","downwards arrow"],["8596","left right arrow"],["8629","carriage return"],["8656","leftwards double arrow"],["8657","upwards double arrow"],["8658","rightwards double arrow"],["8659","downwards double arrow"],["8660","left right double arrow"],["8756","therefore"],["8834","subset of"],["8835","superset of"],["8836","not a subset of"],["8838","subset of or equal to"],["8839","superset of or equal to"],["8853","circled plus"],["8855","circled times"],["8869","perpendicular"],["8901","dot operator"],["8968","left ceiling"],["8969","right ceiling"],["8970","left floor"],["8971","right floor"],["9001","left-pointing angle bracket"],["9002","right-pointing angle bracket"],["9674","lozenge"],["9824","black spade suit"],["9827","black club suit"],["9829","black heart suit"],["9830","black diamond suit"],["8194","en space"],["8195","em space"],["8201","thin space"],["8204","zero width non-joiner"],["8205","zero width joiner"],["8206","left-to-right mark"],["8207","right-to-left mark"]])},t=function(t){return{getCharMap:function(){return s(t)},insertChar:function(e){l(t,e)}}},u=function(e){var t,a,i,r=Math.min(e.length,25),n=Math.ceil(e.length/r);for(t='',i=0;i",a=0;a
    '+s+"
    "}else t+="
    "}return t+=""},d=function(e){for(;e;){if("TD"===e.nodeName)return e;e=e.parentNode}},m=function(n){var o,e={type:"container",html:u(s(n)),onclick:function(e){var t=e.target;if(/^(TD|DIV)$/.test(t.nodeName)){var a=d(t).firstChild;if(a&&a.hasAttribute("data-chr")){var i=a.getAttribute("data-chr"),r=parseInt(i,10);isNaN(r)||l(n,String.fromCharCode(r)),e.ctrlKey||o.close()}}},onmouseover:function(e){var t=d(e.target);t&&t.firstChild?(o.find("#preview").text(t.firstChild.firstChild.data),o.find("#previewTitle").text(t.title)):(o.find("#preview").text(" "),o.find("#previewTitle").text(" "))}};o=n.windowManager.open({title:"Special character",spacing:10,padding:10,items:[e,{type:"container",layout:"flex",direction:"column",align:"center",spacing:5,minWidth:160,minHeight:160,items:[{type:"label",name:"preview",text:" ",style:"font-size: 40px; text-align: center",border:1,minWidth:140,minHeight:80},{type:"spacer",minHeight:20},{type:"label",name:"previewTitle",text:" ",style:"white-space: pre-wrap;",border:1,minWidth:140}]}],buttons:[{text:"Close",onclick:function(){o.close()}}]})},g=function(e){e.addCommand("mceShowCharmap",function(){m(e)})},p=function(e){e.addButton("charmap",{icon:"charmap",tooltip:"Special character",cmd:"mceShowCharmap"}),e.addMenuItem("charmap",{icon:"charmap",text:"Special character",cmd:"mceShowCharmap",context:"insert"})};e.add("charmap",function(e){return g(e),p(e),t(e)})}(); // Source: wp-includes/js/tinymce/plugins/colorpicker/plugin.min.js !function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),l=tinymce.util.Tools.resolve("tinymce.util.Color"),a=function(e,n){e.find("#preview")[0].getEl().style.background=n},o=function(e,n){var i=l(n),t=i.toRgb();e.fromJSON({r:t.r,g:t.g,b:t.b,hex:i.toHex().substr(1)}),a(e,i.toHex())},t=function(e,n,i){var t=e.windowManager.open({title:"Color",items:{type:"container",layout:"flex",direction:"row",align:"stretch",padding:5,spacing:10,items:[{type:"colorpicker",value:i,onchange:function(){var e=this.rgb();t&&(t.find("#r").value(e.r),t.find("#g").value(e.g),t.find("#b").value(e.b),t.find("#hex").value(this.value().substr(1)),a(t,this.value()))}},{type:"form",padding:0,labelGap:5,defaults:{type:"textbox",size:7,value:"0",flex:1,spellcheck:!1,onchange:function(){var e,n,i=t.find("colorpicker")[0];if(e=this.name(),n=this.value(),"hex"===e)return o(t,n="#"+n),void i.value(n);n={r:t.find("#r").value(),g:t.find("#g").value(),b:t.find("#b").value()},i.value(n),o(t,n)}},items:[{name:"r",label:"R",autofocus:1},{name:"g",label:"G"},{name:"b",label:"B"},{name:"hex",label:"#",value:"000000"},{name:"preview",type:"container",border:1}]}]},onSubmit:function(){n("#"+t.toJSON().hex)}});o(t,i)};e.add("colorpicker",function(i){i.settings.color_picker_callback||(i.settings.color_picker_callback=function(e,n){t(i,e,n)})})}(); // Source: wp-includes/js/tinymce/plugins/compat3x/plugin.min.js !function(u){var t;function l(){}function f(e){!t&&window&&window.console&&(t=!0,console.log("Deprecated TinyMCE API call: "+e))}function i(i,a,d,s){i=i||this;var c=[];a?(this.add=function(o,r,e){function t(e){var t=[];if("string"==typeof d&&(d=d.split(" ")),d&&"function"!=typeof d)for(var n=0;n.on"+a+".add(..)"),i.on(a,t,e);var n={original:o,patched:t};return c.push(n),t},this.addToTop=function(e,t){this.add(e,t,!0)},this.remove=function(n){return c.forEach(function(e,t){if(e.original===n)return c.splice(t,1),i.off(a,e.patched)}),i.off(a,n)},this.dispatch=function(){return i.fire(a),!0}):this.add=this.addToTop=this.remove=this.dispatch=l}function n(s){function e(e,t){u.each(e.split(" "),function(e){s["on"+e]=new i(s,e,t)})}function n(e,t,n){return[t.level,n]}function o(n){return function(e,t){if(!t.selection&&!n||t.selection==n)return[t]}}if(!s.controlManager){s.controlManager={buttons:{},setDisabled:function(e,t){f("controlManager.setDisabled(..)"),this.buttons[e]&&this.buttons[e].disabled(t)},setActive:function(e,t){f("controlManager.setActive(..)"),this.buttons[e]&&this.buttons[e].active(t)},onAdd:new i,onPostRender:new i,add:function(e){return e},createButton:r,createColorSplitButton:r,createControl:r,createDropMenu:r,createListBox:r,createMenuButton:r,createSeparator:r,createSplitButton:r,createToolbar:r,createToolbarGroup:r,destroy:l,get:l,setControlType:r},e("PreInit BeforeRenderUI PostRender Load Init Remove Activate Deactivate","editor"),e("Click MouseUp MouseDown DblClick KeyDown KeyUp KeyPress ContextMenu Paste Submit Reset"),e("BeforeExecCommand ExecCommand","command ui value args"),e("PreProcess PostProcess LoadContent SaveContent Change"),e("BeforeSetContent BeforeGetContent SetContent GetContent",o(!1)),e("SetProgressState","state time"),e("VisualAid","element hasVisual"),e("Undo Redo",n),e("NodeChange",function(e,t){return[s.controlManager,t.element,s.selection.isCollapsed(),t]});var c=s.addButton;s.addButton=function(e,t){var n,o,r,i;function a(){if(s.controlManager.buttons[e]=this,n)return n.apply(this,arguments)}for(var d in t)"onpostrender"===d.toLowerCase()&&(n=t[d],t.onPostRender=a);return n||(t.onPostRender=a),t.title&&(t.title=(o=t.title,r=[s.settings.language||"en",o].join("."),i=u.i18n.translate(r),r!==i?i:u.i18n.translate(o))),c.call(this,e,t)},s.on("init",function(){var e=s.undoManager,t=s.selection;e.onUndo=new i(s,"Undo",n,null,e),e.onRedo=new i(s,"Redo",n,null,e),e.onBeforeAdd=new i(s,"BeforeAddUndo",null,e),e.onAdd=new i(s,"AddUndo",null,e),t.onBeforeGetContent=new i(s,"BeforeGetContent",o(!0),t),t.onGetContent=new i(s,"GetContent",o(!0),t),t.onBeforeSetContent=new i(s,"BeforeSetContent",o(!0),t),t.onSetContent=new i(s,"SetContent",o(!0),t)}),s.on("BeforeRenderUI",function(){var e=s.windowManager;e.onOpen=new i,e.onClose=new i,e.createInstance=function(e,t,n,o,r,i){return f("windowManager.createInstance(..)"),new(u.resolve(e))(t,n,o,r,i)}})}function r(){var t={};function n(){return r()}return f("editor.controlManager.*"),u.each("add addMenu addSeparator collapse createMenu destroy displayColor expand focus getLength hasMenus hideMenu isActive isCollapsed isDisabled isRendered isSelected mark postRender remove removeAll renderHTML renderMenu renderNode renderTo select selectByIndex setActive setAriaProperty setColor setDisabled setSelected setState showMenu update".split(" "),function(e){t[e]=n}),t}}u.util.Dispatcher=i,u.onBeforeUnload=new i(u,"BeforeUnload"),u.onAddEditor=new i(u,"AddEditor","editor"),u.onRemoveEditor=new i(u,"RemoveEditor","editor"),u.util.Cookie={get:l,getHash:l,remove:l,set:l,setHash:l},u.on("SetupEditor",function(e){n(e.editor)}),u.PluginManager.add("compat3x",n),u.addI18n=function(n,e){var r=u.util.I18n,t=u.each;"string"!=typeof n||-1!==n.indexOf(".")?u.is(n,"string")?t(e,function(e,t){r.data[n+"."+t]=e}):t(n,function(e,o){t(e,function(e,n){t(e,function(e,t){"common"===n?r.data[o+"."+t]=e:r.data[o+"."+n+"."+t]=e})})}):r.add(n,e)}}(tinymce); // Source: wp-includes/js/tinymce/plugins/directionality/plugin.min.js !function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager"),c=tinymce.util.Tools.resolve("tinymce.util.Tools"),e=function(t,e){var i,n=t.dom,o=t.selection.getSelectedBlocks();o.length&&(i=n.getAttrib(o[0],"dir"),c.each(o,function(t){n.getParent(t.parentNode,'*[dir="'+e+'"]',n.getRoot())||n.setAttrib(t,"dir",i!==e?e:null)}),t.nodeChanged())},i=function(t){t.addCommand("mceDirectionLTR",function(){e(t,"ltr")}),t.addCommand("mceDirectionRTL",function(){e(t,"rtl")})},n=function(e){var i=[];return c.each("h1 h2 h3 h4 h5 h6 div p".split(" "),function(t){i.push(t+"[dir="+e+"]")}),i.join(",")},o=function(t){t.addButton("ltr",{title:"Left to right",cmd:"mceDirectionLTR",stateSelector:n("ltr")}),t.addButton("rtl",{title:"Right to left",cmd:"mceDirectionRTL",stateSelector:n("rtl")})};t.add("directionality",function(t){i(t),o(t)})}(); // Source: wp-includes/js/tinymce/plugins/fullscreen/plugin.min.js !function(m){"use strict";var i=function(e){var n=e,t=function(){return n};return{get:t,set:function(e){n=e},clone:function(){return i(t())}}},e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=function(e){return{isFullscreen:function(){return null!==e.get()}}},n=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),g=function(e,n){e.fire("FullscreenStateChanged",{state:n})},w=n.DOM,r=function(e,n){var t,r,l,i,o,c,s=m.document.body,u=m.document.documentElement,d=n.get(),a=function(){var e,n,t,i;w.setStyle(l,"height",(t=m.window,i=m.document.body,i.offsetWidth&&(e=i.offsetWidth,n=i.offsetHeight),t.innerWidth&&t.innerHeight&&(e=t.innerWidth,n=t.innerHeight),{w:e,h:n}).h-(r.clientHeight-l.clientHeight))},h=function(){w.unbind(m.window,"resize",a)};if(t=(r=e.getContainer()).style,i=(l=e.getContentAreaContainer().firstChild).style,d)i.width=d.iframeWidth,i.height=d.iframeHeight,d.containerWidth&&(t.width=d.containerWidth),d.containerHeight&&(t.height=d.containerHeight),w.removeClass(s,"mce-fullscreen"),w.removeClass(u,"mce-fullscreen"),w.removeClass(r,"mce-fullscreen"),o=d.scrollPos,m.window.scrollTo(o.x,o.y),w.unbind(m.window,"resize",d.resizeHandler),e.off("remove",d.removeHandler),n.set(null),g(e,!1);else{var f={scrollPos:(c=w.getViewPort(),{x:c.x,y:c.y}),containerWidth:t.width,containerHeight:t.height,iframeWidth:i.width,iframeHeight:i.height,resizeHandler:a,removeHandler:h};i.width=i.height="100%",t.width=t.height="",w.addClass(s,"mce-fullscreen"),w.addClass(u,"mce-fullscreen"),w.addClass(r,"mce-fullscreen"),w.bind(m.window,"resize",a),e.on("remove",h),a(),n.set(f),g(e,!0)}},l=function(e,n){e.addCommand("mceFullScreen",function(){r(e,n)})},o=function(t){return function(e){var n=e.control;t.on("FullscreenStateChanged",function(e){n.active(e.state)})}},c=function(e){e.addMenuItem("fullscreen",{text:"Fullscreen",shortcut:"Ctrl+Shift+F",selectable:!0,cmd:"mceFullScreen",onPostRender:o(e),context:"view"}),e.addButton("fullscreen",{active:!1,tooltip:"Fullscreen",cmd:"mceFullScreen",onPostRender:o(e)})};e.add("fullscreen",function(e){var n=i(null);return e.settings.inline||(l(e,n),c(e),e.addShortcut("Ctrl+Shift+F","","mceFullScreen")),t(n)})}(window); // Source: wp-includes/js/tinymce/plugins/hr/plugin.min.js !function(){"use strict";var n=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=function(n){n.addCommand("InsertHorizontalRule",function(){n.execCommand("mceInsertContent",!1,"
    ")})},o=function(n){n.addButton("hr",{icon:"hr",tooltip:"Horizontal line",cmd:"InsertHorizontalRule"}),n.addMenuItem("hr",{icon:"hr",text:"Horizontal line",cmd:"InsertHorizontalRule",context:"insert"})};n.add("hr",function(n){t(n),o(n)})}(); // Source: wp-includes/js/tinymce/plugins/image/plugin.min.js !function(l){"use strict";var i,e=tinymce.util.Tools.resolve("tinymce.PluginManager"),d=function(e){return!1!==e.settings.image_dimensions},u=function(e){return!0===e.settings.image_advtab},m=function(e){return e.getParam("image_prepend_url","")},n=function(e){return e.getParam("image_class_list")},r=function(e){return!1!==e.settings.image_description},a=function(e){return!0===e.settings.image_title},o=function(e){return!0===e.settings.image_caption},c=function(e){return e.getParam("image_list",!1)},s=function(e){return e.getParam("images_upload_url",!1)},g=function(e){return e.getParam("images_upload_handler",!1)},f=function(e){return e.getParam("images_upload_url")},p=function(e){return e.getParam("images_upload_handler")},h=function(e){return e.getParam("images_upload_base_path")},v=function(e){return e.getParam("images_upload_credentials")},b="undefined"!=typeof l.window?l.window:Function("return this;")(),y=function(e,t){return function(e,t){for(var n=t!==undefined&&null!==t?t:b,r=0;r'),i.close()}}var r,a},A=tinymce.util.Tools.resolve("tinymce.util.Tools"),f=function(t,e){var n,o,i=["noopener"],r=t?t.split(/\s+/):[],a=function(t){return t.filter(function(t){return-1===A.inArray(i,t)})};return(r=e?(n=a(n=r)).length?n.concat(i):i:a(r)).length?(o=r,A.trim(o.sort().join(" "))):null},d=function(t,e){return e=e||t.selection.getNode(),v(e)?t.dom.select("a[href]",e)[0]:t.dom.getParent(e,"a[href]")},m=function(t){return t&&"A"===t.nodeName&&t.href},v=function(t){return t&&"FIGURE"===t.nodeName&&/\bimage\b/i.test(t.className)},g=function(t,e){var n,o;(o=t.dom.select("img",e)[0])&&(n=t.dom.getParents(o,"a[href]",e)[0])&&(n.parentNode.insertBefore(o,n),t.dom.remove(n))},h=function(t,e,n){var o,i;(i=t.dom.select("img",e)[0])&&(o=t.dom.create("a",n),i.parentNode.insertBefore(o,i),o.appendChild(i))},L=function(i,r){return function(o){i.undoManager.transact(function(){var t=i.selection.getNode(),e=d(i,t),n={href:o.href,target:o.target?o.target:null,rel:o.rel?o.rel:null,"class":o["class"]?o["class"]:null,title:o.title?o.title:null};C(i.settings)||!1!==N(i.settings)||(n.rel=f(n.rel,"_blank"===n.target)),o.href===r.href&&(r.attach(),r={}),e?(i.focus(),o.hasOwnProperty("text")&&("innerText"in e?e.innerText=o.text:e.textContent=o.text),i.dom.setAttribs(e,n),i.selection.select(e),i.undoManager.add()):v(t)?h(i,t,n):o.hasOwnProperty("text")?i.insertContent(i.dom.createHTML("a",n,i.dom.encode(o.text))):i.execCommand("mceInsertLink",!1,n)})}},P=function(e){return function(){e.undoManager.transact(function(){var t=e.selection.getNode();v(t)?g(e,t):e.execCommand("unlink")})}},x=m,E=function(t){return 0]+>[^<]+<\/a>$/.test(t)||-1===t.indexOf("href=")))},I=d,K=function(t,e){var n=e?e.innerText||e.textContent:t.getContent({format:"text"});return n.replace(/\uFEFF/g,"")},U=f,D=tinymce.util.Tools.resolve("tinymce.util.Delay"),B=tinymce.util.Tools.resolve("tinymce.util.XHR"),F={},q=function(t,o,e){var i=function(t,n){return n=n||[],A.each(t,function(t){var e={text:t.text||t.title};t.menu?e.menu=i(t.menu):(e.value=t.value,o&&o(e)),n.push(e)}),n};return i(t,e||[])},V=function(e,t,n){var o=e.selection.getRng();D.setEditorTimeout(e,function(){e.windowManager.confirm(t,function(t){e.selection.setRng(o),n(t)})})},z=function(a,t){var e,l,o,u,n,i,r,c,s,f,d,m={},v=a.selection,g=a.dom,h=function(t){var e=o.find("#text");(!e.value()||t.lastControl&&e.value()===t.lastControl.text())&&e.value(t.control.text()),o.find("#href").value(t.control.value())},x=function(){l||!u||m.text||this.parent().parent().find("#text")[0].value(this.value())};u=S(v.getContent()),e=I(a),m.text=l=K(a.selection,e),m.href=e?g.getAttrib(e,"href"):"",e?m.target=g.getAttrib(e,"target"):k(a.settings)&&(m.target=y(a.settings)),(d=g.getAttrib(e,"rel"))&&(m.rel=d),(d=g.getAttrib(e,"class"))&&(m["class"]=d),(d=g.getAttrib(e,"title"))&&(m.title=d),u&&(n={name:"text",type:"textbox",size:40,label:"Text to display",onchange:function(){m.text=this.value()}}),t&&(i={type:"listbox",label:"Link list",values:q(t,function(t){t.value=a.convertURL(t.value||t.url,"href")},[{text:"None",value:""}]),onselect:h,value:a.convertURL(m.href,"href"),onPostRender:function(){i=this}}),w(a.settings)&&(b(a.settings)===undefined&&_(a,[{text:"None",value:""},{text:"New window",value:"_blank"}]),c={name:"target",type:"listbox",label:"Target",values:q(b(a.settings))}),C(a.settings)&&(r={name:"rel",type:"listbox",label:"Rel",values:q(T(a.settings),function(t){!1===N(a.settings)&&(t.value=U(t.value,"_blank"===m.target))})}),O(a.settings)&&(s={name:"class",type:"listbox",label:"Class",values:q(M(a.settings),function(t){t.value&&(t.textStyle=function(){return a.formatter.getCssText({inline:"a",classes:[t.value]})})})}),R(a.settings)&&(f={name:"title",type:"textbox",label:"Title",value:m.title}),o=a.windowManager.open({title:"Insert link",data:m,body:[{name:"href",type:"filepicker",filetype:"file",size:40,autofocus:!0,label:"Url",onchange:function(t){var e=t.meta||{};i&&i.value(a.convertURL(this.value(),"href")),A.each(t.meta,function(t,e){var n=o.find("#"+e);"text"===e?0===l.length&&(n.value(t),m.text=t):n.value(t)}),e.attach&&(F={href:this.value(),attach:e.attach}),e.text||x.call(this)},onkeyup:x,onpaste:x,onbeforecall:function(t){t.meta=o.toJSON()}},n,f,function(n){var o=[];if(A.each(a.dom.select("a:not([href])"),function(t){var e=t.name||t.id;e&&o.push({text:e,value:"#"+e,selected:-1!==n.indexOf("#"+e)})}),o.length)return o.unshift({text:"None",value:""}),{name:"anchor",type:"listbox",label:"Anchors",values:o,onselect:h}}(m.href),i,r,c,s],onSubmit:function(t){var e=p(a.settings),n=L(a,F),o=P(a),i=A.extend({},m,t.data),r=i.href;r?(u&&i.text!==l||delete i.text,0=e.childNodes.length?t.data.length:0}:t.previousSibling&&y(t.previousSibling)?{container:t.previousSibling,offset:t.previousSibling.data.length}:t.nextSibling&&y(t.nextSibling)?{container:t.nextSibling,offset:0}:{container:e,offset:n}},x=function(e){var n=e.cloneRange(),t=A(e.startContainer,e.startOffset);n.setStart(t.container,t.offset);var r=A(e.endContainer,e.endOffset);return n.setEnd(r.container,r.offset),n},R=g.DOM,I=function(o){var i={},e=function(e){var n,t,r;t=o[e?"startContainer":"endContainer"],r=o[e?"startOffset":"endOffset"],1===t.nodeType&&(n=R.create("span",{"data-mce-type":"bookmark"}),t.hasChildNodes()?(r=Math.min(r,t.childNodes.length-1),e?t.insertBefore(n,t.childNodes[r]):R.insertAfter(n,t.childNodes[r])):t.appendChild(n),t=n,r=0),i[e?"startContainer":"endContainer"]=t,i[e?"startOffset":"endOffset"]=r};return e(!0),o.collapsed||e(),i},_=function(o){function e(e){var n,t,r;n=r=o[e?"startContainer":"endContainer"],t=o[e?"startOffset":"endOffset"],n&&(1===n.nodeType&&(t=function(e){for(var n=e.parentNode.firstChild,t=0;n;){if(n===e)return t;1===n.nodeType&&"bookmark"===n.getAttribute("data-mce-type")||t++,n=n.nextSibling}return-1}(n),n=n.parentNode,R.remove(r),!n.hasChildNodes()&&R.isBlock(n)&&n.appendChild(R.create("br"))),o[e?"startContainer":"endContainer"]=n,o[e?"startOffset":"endOffset"]=t)}e(!0),e();var n=R.createRng();return n.setStart(o.startContainer,o.startOffset),o.endContainer&&n.setEnd(o.endContainer,o.endOffset),x(n)},B=function(){},P=function(e){return function(){return e}},M=function(t){return function(){for(var e=[],n=0;ne.length?Sn(t,e,n):Nn(t,e,n)},[]),oe(o).map(function(e){return e.list})).toArray();var t,r,o},Pn=function(e){var n,t,r=J(ve.getSelectedListItems(e),ye.fromDom);return Ne(te(r,M(On)),te((n=r,(t=Y.call(n,0)).reverse(),t),M(On)),function(e,n){return{start:e,end:n}})},Mn=function(s,e,a){var n,t,r,o=(n=e,t=Pn(s),r=kn(!1),J(n,function(e){return{sourceList:e,entries:xn(0,t,r,e)}}));Z(o,function(e){var n,t,r,o,i,u;n=e.entries,t=a,Z(ee(n,Tn),function(e){return function(e,n){switch(e){case"Indent":n.depth++;break;case"Outdent":n.depth--;break;case"Flatten":n.depth=0}}(t,e)}),r=e.sourceList,i=s,u=e.entries,o=re(function(e,n){if(0===e.length)return[];for(var t=n(e[0]),r=[],o=[],i=0,u=e.length;i"):"application/x-shockwave-flash"===n.source1mime?(d='',m.poster&&(d+=''),d+=""):-1!==n.source1mime.indexOf("audio")?(s=n,(l=p)?l(s):'"):"script"===n.type?' */ var dispatches = [ /** Dispatched when runtime is connected and file-picker is ready to be used. @event ready @param {Object} event */ 'ready', /** Dispatched right after [ready](#event_ready) event, and whenever [refresh()](#method_refresh) is invoked. Check [corresponding documentation entry](#method_refresh) for more info. @event refresh @param {Object} event */ /** Dispatched when selection of files in the dialog is complete. @event change @param {Object} event */ 'change', 'cancel', // TODO: might be useful /** Dispatched when mouse cursor enters file-picker area. Can be used to style element accordingly. @event mouseenter @param {Object} event */ 'mouseenter', /** Dispatched when mouse cursor leaves file-picker area. Can be used to style element accordingly. @event mouseleave @param {Object} event */ 'mouseleave', /** Dispatched when functional mouse button is pressed on top of file-picker area. @event mousedown @param {Object} event */ 'mousedown', /** Dispatched when functional mouse button is released on top of file-picker area. @event mouseup @param {Object} event */ 'mouseup' ]; function FileInput(options) { if (MXI_DEBUG) { Env.log("Instantiating FileInput..."); } var self = this, container, browseButton, defaults; // if flat argument passed it should be browse_button id if (Basic.inArray(Basic.typeOf(options), ['string', 'node']) !== -1) { options = { browse_button : options }; } // this will help us to find proper default container browseButton = Dom.get(options.browse_button); if (!browseButton) { // browse button is required throw new x.DOMException(x.DOMException.NOT_FOUND_ERR); } // figure out the options defaults = { accept: [{ title: I18n.translate('All Files'), extensions: '*' }], name: 'file', multiple: false, required_caps: false, container: browseButton.parentNode || document.body }; options = Basic.extend({}, defaults, options); // convert to object representation if (typeof(options.required_caps) === 'string') { options.required_caps = Runtime.parseCaps(options.required_caps); } // normalize accept option (could be list of mime types or array of title/extensions pairs) if (typeof(options.accept) === 'string') { options.accept = Mime.mimes2extList(options.accept); } container = Dom.get(options.container); // make sure we have container if (!container) { container = document.body; } // make container relative, if it's not if (Dom.getStyle(container, 'position') === 'static') { container.style.position = 'relative'; } container = browseButton = null; // IE RuntimeClient.call(self); Basic.extend(self, { /** Unique id of the component @property uid @protected @readOnly @type {String} @default UID */ uid: Basic.guid('uid_'), /** Unique id of the connected runtime, if any. @property ruid @protected @type {String} */ ruid: null, /** Unique id of the runtime container. Useful to get hold of it for various manipulations. @property shimid @protected @type {String} */ shimid: null, /** Array of selected mOxie.File objects @property files @type {Array} @default null */ files: null, /** Initializes the file-picker, connects it to runtime and dispatches event ready when done. @method init */ init: function() { self.bind('RuntimeInit', function(e, runtime) { self.ruid = runtime.uid; self.shimid = runtime.shimid; self.bind("Ready", function() { self.trigger("Refresh"); }, 999); // re-position and resize shim container self.bind('Refresh', function() { var pos, size, browseButton, shimContainer; browseButton = Dom.get(options.browse_button); shimContainer = Dom.get(runtime.shimid); // do not use runtime.getShimContainer(), since it will create container if it doesn't exist if (browseButton) { pos = Dom.getPos(browseButton, Dom.get(options.container)); size = Dom.getSize(browseButton); if (shimContainer) { Basic.extend(shimContainer.style, { top : pos.y + 'px', left : pos.x + 'px', width : size.w + 'px', height : size.h + 'px' }); } } shimContainer = browseButton = null; }); runtime.exec.call(self, 'FileInput', 'init', options); }); // runtime needs: options.required_features, options.runtime_order and options.container self.connectRuntime(Basic.extend({}, options, { required_caps: { select_file: true } })); }, /** Disables file-picker element, so that it doesn't react to mouse clicks. @method disable @param {Boolean} [state=true] Disable component if - true, enable if - false */ disable: function(state) { var runtime = this.getRuntime(); if (runtime) { runtime.exec.call(this, 'FileInput', 'disable', Basic.typeOf(state) === 'undefined' ? true : state); } }, /** Reposition and resize dialog trigger to match the position and size of browse_button element. @method refresh */ refresh: function() { self.trigger("Refresh"); }, /** Destroy component. @method destroy */ destroy: function() { var runtime = this.getRuntime(); if (runtime) { runtime.exec.call(this, 'FileInput', 'destroy'); this.disconnectRuntime(); } if (Basic.typeOf(this.files) === 'array') { // no sense in leaving associated files behind Basic.each(this.files, function(file) { file.destroy(); }); } this.files = null; this.unbindAll(); } }); this.handleEventProps(dispatches); } FileInput.prototype = EventTarget.instance; return FileInput; }); // Included from: src/javascript/core/utils/Encode.js /** * Encode.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ define('moxie/core/utils/Encode', [], function() { /** Encode string with UTF-8 @method utf8_encode @for Utils @static @param {String} str String to encode @return {String} UTF-8 encoded string */ var utf8_encode = function(str) { return unescape(encodeURIComponent(str)); }; /** Decode UTF-8 encoded string @method utf8_decode @static @param {String} str String to decode @return {String} Decoded string */ var utf8_decode = function(str_data) { return decodeURIComponent(escape(str_data)); }; /** Decode Base64 encoded string (uses browser's default method if available), from: https://raw.github.com/kvz/phpjs/master/functions/url/base64_decode.js @method atob @static @param {String} data String to decode @return {String} Decoded string */ var atob = function(data, utf8) { if (typeof(window.atob) === 'function') { return utf8 ? utf8_decode(window.atob(data)) : window.atob(data); } // http://kevin.vanzonneveld.net // + original by: Tyler Akins (http://rumkin.com) // + improved by: Thunder.m // + input by: Aman Gupta // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + bugfixed by: Onno Marsman // + bugfixed by: Pellentesque Malesuada // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + input by: Brett Zamir (http://brett-zamir.me) // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // * example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA=='); // * returns 1: 'Kevin van Zonneveld' // mozilla has this native // - but breaks in 2.0.0.12! //if (typeof this.window.atob == 'function') { // return atob(data); //} var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, dec = "", tmp_arr = []; if (!data) { return data; } data += ''; do { // unpack four hexets into three octets using index points in b64 h1 = b64.indexOf(data.charAt(i++)); h2 = b64.indexOf(data.charAt(i++)); h3 = b64.indexOf(data.charAt(i++)); h4 = b64.indexOf(data.charAt(i++)); bits = h1 << 18 | h2 << 12 | h3 << 6 | h4; o1 = bits >> 16 & 0xff; o2 = bits >> 8 & 0xff; o3 = bits & 0xff; if (h3 == 64) { tmp_arr[ac++] = String.fromCharCode(o1); } else if (h4 == 64) { tmp_arr[ac++] = String.fromCharCode(o1, o2); } else { tmp_arr[ac++] = String.fromCharCode(o1, o2, o3); } } while (i < data.length); dec = tmp_arr.join(''); return utf8 ? utf8_decode(dec) : dec; }; /** Base64 encode string (uses browser's default method if available), from: https://raw.github.com/kvz/phpjs/master/functions/url/base64_encode.js @method btoa @static @param {String} data String to encode @return {String} Base64 encoded string */ var btoa = function(data, utf8) { if (utf8) { data = utf8_encode(data); } if (typeof(window.btoa) === 'function') { return window.btoa(data); } // http://kevin.vanzonneveld.net // + original by: Tyler Akins (http://rumkin.com) // + improved by: Bayron Guevara // + improved by: Thunder.m // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + bugfixed by: Pellentesque Malesuada // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) // + improved by: Rafał Kukawski (http://kukawski.pl) // * example 1: base64_encode('Kevin van Zonneveld'); // * returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA==' // mozilla has this native // - but breaks in 2.0.0.12! var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, enc = "", tmp_arr = []; if (!data) { return data; } do { // pack three octets into four hexets o1 = data.charCodeAt(i++); o2 = data.charCodeAt(i++); o3 = data.charCodeAt(i++); bits = o1 << 16 | o2 << 8 | o3; h1 = bits >> 18 & 0x3f; h2 = bits >> 12 & 0x3f; h3 = bits >> 6 & 0x3f; h4 = bits & 0x3f; // use hexets to index into b64, and append result to encoded string tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); } while (i < data.length); enc = tmp_arr.join(''); var r = data.length % 3; return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3); }; return { utf8_encode: utf8_encode, utf8_decode: utf8_decode, atob: atob, btoa: btoa }; }); // Included from: src/javascript/file/Blob.js /** * Blob.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ define('moxie/file/Blob', [ 'moxie/core/utils/Basic', 'moxie/core/utils/Encode', 'moxie/runtime/RuntimeClient' ], function(Basic, Encode, RuntimeClient) { var blobpool = {}; /** @class Blob @constructor @param {String} ruid Unique id of the runtime, to which this blob belongs to @param {Object} blob Object "Native" blob object, as it is represented in the runtime */ function Blob(ruid, blob) { function _sliceDetached(start, end, type) { var blob, data = blobpool[this.uid]; if (Basic.typeOf(data) !== 'string' || !data.length) { return null; // or throw exception } blob = new Blob(null, { type: type, size: end - start }); blob.detach(data.substr(start, blob.size)); return blob; } RuntimeClient.call(this); if (ruid) { this.connectRuntime(ruid); } if (!blob) { blob = {}; } else if (Basic.typeOf(blob) === 'string') { // dataUrl or binary string blob = { data: blob }; } Basic.extend(this, { /** Unique id of the component @property uid @type {String} */ uid: blob.uid || Basic.guid('uid_'), /** Unique id of the connected runtime, if falsy, then runtime will have to be initialized before this Blob can be used, modified or sent @property ruid @type {String} */ ruid: ruid, /** Size of blob @property size @type {Number} @default 0 */ size: blob.size || 0, /** Mime type of blob @property type @type {String} @default '' */ type: blob.type || '', /** @method slice @param {Number} [start=0] */ slice: function(start, end, type) { if (this.isDetached()) { return _sliceDetached.apply(this, arguments); } return this.getRuntime().exec.call(this, 'Blob', 'slice', this.getSource(), start, end, type); }, /** Returns "native" blob object (as it is represented in connected runtime) or null if not found @method getSource @return {Blob} Returns "native" blob object or null if not found */ getSource: function() { if (!blobpool[this.uid]) { return null; } return blobpool[this.uid]; }, /** Detaches blob from any runtime that it depends on and initialize with standalone value @method detach @protected @param {DOMString} [data=''] Standalone value */ detach: function(data) { if (this.ruid) { this.getRuntime().exec.call(this, 'Blob', 'destroy'); this.disconnectRuntime(); this.ruid = null; } data = data || ''; // if dataUrl, convert to binary string if (data.substr(0, 5) == 'data:') { var base64Offset = data.indexOf(';base64,'); this.type = data.substring(5, base64Offset); data = Encode.atob(data.substring(base64Offset + 8)); } this.size = data.length; blobpool[this.uid] = data; }, /** Checks if blob is standalone (detached of any runtime) @method isDetached @protected @return {Boolean} */ isDetached: function() { return !this.ruid && Basic.typeOf(blobpool[this.uid]) === 'string'; }, /** Destroy Blob and free any resources it was using @method destroy */ destroy: function() { this.detach(); delete blobpool[this.uid]; } }); if (blob.data) { this.detach(blob.data); // auto-detach if payload has been passed } else { blobpool[this.uid] = blob; } } return Blob; }); // Included from: src/javascript/file/File.js /** * File.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ define('moxie/file/File', [ 'moxie/core/utils/Basic', 'moxie/core/utils/Mime', 'moxie/file/Blob' ], function(Basic, Mime, Blob) { /** @class File @extends Blob @constructor @param {String} ruid Unique id of the runtime, to which this blob belongs to @param {Object} file Object "Native" file object, as it is represented in the runtime */ function File(ruid, file) { if (!file) { // avoid extra errors in case we overlooked something file = {}; } Blob.apply(this, arguments); if (!this.type) { this.type = Mime.getFileMime(file.name); } // sanitize file name or generate new one var name; if (file.name) { name = file.name.replace(/\\/g, '/'); name = name.substr(name.lastIndexOf('/') + 1); } else if (this.type) { var prefix = this.type.split('/')[0]; name = Basic.guid((prefix !== '' ? prefix : 'file') + '_'); if (Mime.extensions[this.type]) { name += '.' + Mime.extensions[this.type][0]; // append proper extension if possible } } Basic.extend(this, { /** File name @property name @type {String} @default UID */ name: name || Basic.guid('file_'), /** Relative path to the file inside a directory @property relativePath @type {String} @default '' */ relativePath: '', /** Date of last modification @property lastModifiedDate @type {String} @default now */ lastModifiedDate: file.lastModifiedDate || (new Date()).toLocaleString() // Thu Aug 23 2012 19:40:00 GMT+0400 (GET) }); } File.prototype = Blob.prototype; return File; }); // Included from: src/javascript/file/FileDrop.js /** * FileDrop.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ define('moxie/file/FileDrop', [ 'moxie/core/I18n', 'moxie/core/utils/Dom', 'moxie/core/Exceptions', 'moxie/core/utils/Basic', 'moxie/core/utils/Env', 'moxie/file/File', 'moxie/runtime/RuntimeClient', 'moxie/core/EventTarget', 'moxie/core/utils/Mime' ], function(I18n, Dom, x, Basic, Env, File, RuntimeClient, EventTarget, Mime) { /** Turn arbitrary DOM element to a drop zone accepting files. Converts selected files to _File_ objects, to be used in conjunction with _Image_, preloaded in memory with _FileReader_ or uploaded to a server through _XMLHttpRequest_. @example
    Drop files here

    @class FileDrop @constructor @extends EventTarget @uses RuntimeClient @param {Object|String} options If options has typeof string, argument is considered as options.drop_zone @param {String|DOMElement} options.drop_zone DOM Element to turn into a drop zone @param {Array} [options.accept] Array of mime types to accept. By default accepts all @param {Object|String} [options.required_caps] Set of required capabilities, that chosen runtime must support */ var dispatches = [ /** Dispatched when runtime is connected and drop zone is ready to accept files. @event ready @param {Object} event */ 'ready', /** Dispatched when dragging cursor enters the drop zone. @event dragenter @param {Object} event */ 'dragenter', /** Dispatched when dragging cursor leaves the drop zone. @event dragleave @param {Object} event */ 'dragleave', /** Dispatched when file is dropped onto the drop zone. @event drop @param {Object} event */ 'drop', /** Dispatched if error occurs. @event error @param {Object} event */ 'error' ]; function FileDrop(options) { if (MXI_DEBUG) { Env.log("Instantiating FileDrop..."); } var self = this, defaults; // if flat argument passed it should be drop_zone id if (typeof(options) === 'string') { options = { drop_zone : options }; } // figure out the options defaults = { accept: [{ title: I18n.translate('All Files'), extensions: '*' }], required_caps: { drag_and_drop: true } }; options = typeof(options) === 'object' ? Basic.extend({}, defaults, options) : defaults; // this will help us to find proper default container options.container = Dom.get(options.drop_zone) || document.body; // make container relative, if it is not if (Dom.getStyle(options.container, 'position') === 'static') { options.container.style.position = 'relative'; } // normalize accept option (could be list of mime types or array of title/extensions pairs) if (typeof(options.accept) === 'string') { options.accept = Mime.mimes2extList(options.accept); } RuntimeClient.call(self); Basic.extend(self, { uid: Basic.guid('uid_'), ruid: null, files: null, init: function() { self.bind('RuntimeInit', function(e, runtime) { self.ruid = runtime.uid; runtime.exec.call(self, 'FileDrop', 'init', options); self.dispatchEvent('ready'); }); // runtime needs: options.required_features, options.runtime_order and options.container self.connectRuntime(options); // throws RuntimeError }, destroy: function() { var runtime = this.getRuntime(); if (runtime) { runtime.exec.call(this, 'FileDrop', 'destroy'); this.disconnectRuntime(); } this.files = null; this.unbindAll(); } }); this.handleEventProps(dispatches); } FileDrop.prototype = EventTarget.instance; return FileDrop; }); // Included from: src/javascript/file/FileReader.js /** * FileReader.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ define('moxie/file/FileReader', [ 'moxie/core/utils/Basic', 'moxie/core/utils/Encode', 'moxie/core/Exceptions', 'moxie/core/EventTarget', 'moxie/file/Blob', 'moxie/runtime/RuntimeClient' ], function(Basic, Encode, x, EventTarget, Blob, RuntimeClient) { /** Utility for preloading o.Blob/o.File objects in memory. By design closely follows [W3C FileReader](http://www.w3.org/TR/FileAPI/#dfn-filereader) interface. Where possible uses native FileReader, where - not falls back to shims. @class FileReader @constructor FileReader @extends EventTarget @uses RuntimeClient */ var dispatches = [ /** Dispatched when the read starts. @event loadstart @param {Object} event */ 'loadstart', /** Dispatched while reading (and decoding) blob, and reporting partial Blob data (progess.loaded/progress.total). @event progress @param {Object} event */ 'progress', /** Dispatched when the read has successfully completed. @event load @param {Object} event */ 'load', /** Dispatched when the read has been aborted. For instance, by invoking the abort() method. @event abort @param {Object} event */ 'abort', /** Dispatched when the read has failed. @event error @param {Object} event */ 'error', /** Dispatched when the request has completed (either in success or failure). @event loadend @param {Object} event */ 'loadend' ]; function FileReader() { RuntimeClient.call(this); Basic.extend(this, { /** UID of the component instance. @property uid @type {String} */ uid: Basic.guid('uid_'), /** Contains current state of FileReader object. Can take values of FileReader.EMPTY, FileReader.LOADING and FileReader.DONE. @property readyState @type {Number} @default FileReader.EMPTY */ readyState: FileReader.EMPTY, /** Result of the successful read operation. @property result @type {String} */ result: null, /** Stores the error of failed asynchronous read operation. @property error @type {DOMError} */ error: null, /** Initiates reading of File/Blob object contents to binary string. @method readAsBinaryString @param {Blob|File} blob Object to preload */ readAsBinaryString: function(blob) { _read.call(this, 'readAsBinaryString', blob); }, /** Initiates reading of File/Blob object contents to dataURL string. @method readAsDataURL @param {Blob|File} blob Object to preload */ readAsDataURL: function(blob) { _read.call(this, 'readAsDataURL', blob); }, /** Initiates reading of File/Blob object contents to string. @method readAsText @param {Blob|File} blob Object to preload */ readAsText: function(blob) { _read.call(this, 'readAsText', blob); }, /** Aborts preloading process. @method abort */ abort: function() { this.result = null; if (Basic.inArray(this.readyState, [FileReader.EMPTY, FileReader.DONE]) !== -1) { return; } else if (this.readyState === FileReader.LOADING) { this.readyState = FileReader.DONE; } this.exec('FileReader', 'abort'); this.trigger('abort'); this.trigger('loadend'); }, /** Destroy component and release resources. @method destroy */ destroy: function() { this.abort(); this.exec('FileReader', 'destroy'); this.disconnectRuntime(); this.unbindAll(); } }); // uid must already be assigned this.handleEventProps(dispatches); this.bind('Error', function(e, err) { this.readyState = FileReader.DONE; this.error = err; }, 999); this.bind('Load', function(e) { this.readyState = FileReader.DONE; }, 999); function _read(op, blob) { var self = this; this.trigger('loadstart'); if (this.readyState === FileReader.LOADING) { this.trigger('error', new x.DOMException(x.DOMException.INVALID_STATE_ERR)); this.trigger('loadend'); return; } // if source is not o.Blob/o.File if (!(blob instanceof Blob)) { this.trigger('error', new x.DOMException(x.DOMException.NOT_FOUND_ERR)); this.trigger('loadend'); return; } this.result = null; this.readyState = FileReader.LOADING; if (blob.isDetached()) { var src = blob.getSource(); switch (op) { case 'readAsText': case 'readAsBinaryString': this.result = src; break; case 'readAsDataURL': this.result = 'data:' + blob.type + ';base64,' + Encode.btoa(src); break; } this.readyState = FileReader.DONE; this.trigger('load'); this.trigger('loadend'); } else { this.connectRuntime(blob.ruid); this.exec('FileReader', 'read', op, blob); } } } /** Initial FileReader state @property EMPTY @type {Number} @final @static @default 0 */ FileReader.EMPTY = 0; /** FileReader switches to this state when it is preloading the source @property LOADING @type {Number} @final @static @default 1 */ FileReader.LOADING = 1; /** Preloading is complete, this is a final state @property DONE @type {Number} @final @static @default 2 */ FileReader.DONE = 2; FileReader.prototype = EventTarget.instance; return FileReader; }); // Included from: src/javascript/core/utils/Url.js /** * Url.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ define('moxie/core/utils/Url', [], function() { /** Parse url into separate components and fill in absent parts with parts from current url, based on https://raw.github.com/kvz/phpjs/master/functions/url/parse_url.js @method parseUrl @for Utils @static @param {String} url Url to parse (defaults to empty string if undefined) @return {Object} Hash containing extracted uri components */ var parseUrl = function(url, currentUrl) { var key = ['source', 'scheme', 'authority', 'userInfo', 'user', 'pass', 'host', 'port', 'relative', 'path', 'directory', 'file', 'query', 'fragment'] , i = key.length , ports = { http: 80, https: 443 } , uri = {} , regex = /^(?:([^:\/?#]+):)?(?:\/\/()(?:(?:()(?:([^:@\/]*):?([^:@\/]*))?@)?([^:\/?#]*)(?::(\d*))?))?()(?:(()(?:(?:[^?#\/]*\/)*)()(?:[^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/ , m = regex.exec(url || '') ; while (i--) { if (m[i]) { uri[key[i]] = m[i]; } } // when url is relative, we set the origin and the path ourselves if (!uri.scheme) { // come up with defaults if (!currentUrl || typeof(currentUrl) === 'string') { currentUrl = parseUrl(currentUrl || document.location.href); } uri.scheme = currentUrl.scheme; uri.host = currentUrl.host; uri.port = currentUrl.port; var path = ''; // for urls without trailing slash we need to figure out the path if (/^[^\/]/.test(uri.path)) { path = currentUrl.path; // if path ends with a filename, strip it if (/\/[^\/]*\.[^\/]*$/.test(path)) { path = path.replace(/\/[^\/]+$/, '/'); } else { // avoid double slash at the end (see #127) path = path.replace(/\/?$/, '/'); } } uri.path = path + (uri.path || ''); // site may reside at domain.com or domain.com/subdir } if (!uri.port) { uri.port = ports[uri.scheme] || 80; } uri.port = parseInt(uri.port, 10); if (!uri.path) { uri.path = "/"; } delete uri.source; return uri; }; /** Resolve url - among other things will turn relative url to absolute @method resolveUrl @static @param {String|Object} url Either absolute or relative, or a result of parseUrl call @return {String} Resolved, absolute url */ var resolveUrl = function(url) { var ports = { // we ignore default ports http: 80, https: 443 } , urlp = typeof(url) === 'object' ? url : parseUrl(url); ; return urlp.scheme + '://' + urlp.host + (urlp.port !== ports[urlp.scheme] ? ':' + urlp.port : '') + urlp.path + (urlp.query ? urlp.query : ''); }; /** Check if specified url has the same origin as the current document @method hasSameOrigin @param {String|Object} url @return {Boolean} */ var hasSameOrigin = function(url) { function origin(url) { return [url.scheme, url.host, url.port].join('/'); } if (typeof url === 'string') { url = parseUrl(url); } return origin(parseUrl()) === origin(url); }; return { parseUrl: parseUrl, resolveUrl: resolveUrl, hasSameOrigin: hasSameOrigin }; }); // Included from: src/javascript/runtime/RuntimeTarget.js /** * RuntimeTarget.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ define('moxie/runtime/RuntimeTarget', [ 'moxie/core/utils/Basic', 'moxie/runtime/RuntimeClient', "moxie/core/EventTarget" ], function(Basic, RuntimeClient, EventTarget) { /** Instance of this class can be used as a target for the events dispatched by shims, when allowing them onto components is for either reason inappropriate @class RuntimeTarget @constructor @protected @extends EventTarget */ function RuntimeTarget() { this.uid = Basic.guid('uid_'); RuntimeClient.call(this); this.destroy = function() { this.disconnectRuntime(); this.unbindAll(); }; } RuntimeTarget.prototype = EventTarget.instance; return RuntimeTarget; }); // Included from: src/javascript/file/FileReaderSync.js /** * FileReaderSync.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ define('moxie/file/FileReaderSync', [ 'moxie/core/utils/Basic', 'moxie/runtime/RuntimeClient', 'moxie/core/utils/Encode' ], function(Basic, RuntimeClient, Encode) { /** Synchronous FileReader implementation. Something like this is available in WebWorkers environment, here it can be used to read only preloaded blobs/files and only below certain size (not yet sure what that'd be, but probably < 1mb). Not meant to be used directly by user. @class FileReaderSync @private @constructor */ return function() { RuntimeClient.call(this); Basic.extend(this, { uid: Basic.guid('uid_'), readAsBinaryString: function(blob) { return _read.call(this, 'readAsBinaryString', blob); }, readAsDataURL: function(blob) { return _read.call(this, 'readAsDataURL', blob); }, /*readAsArrayBuffer: function(blob) { return _read.call(this, 'readAsArrayBuffer', blob); },*/ readAsText: function(blob) { return _read.call(this, 'readAsText', blob); } }); function _read(op, blob) { if (blob.isDetached()) { var src = blob.getSource(); switch (op) { case 'readAsBinaryString': return src; case 'readAsDataURL': return 'data:' + blob.type + ';base64,' + Encode.btoa(src); case 'readAsText': var txt = ''; for (var i = 0, length = src.length; i < length; i++) { txt += String.fromCharCode(src[i]); } return txt; } } else { var result = this.connectRuntime(blob.ruid).exec.call(this, 'FileReaderSync', 'read', op, blob); this.disconnectRuntime(); return result; } } }; }); // Included from: src/javascript/xhr/FormData.js /** * FormData.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ define("moxie/xhr/FormData", [ "moxie/core/Exceptions", "moxie/core/utils/Basic", "moxie/file/Blob" ], function(x, Basic, Blob) { /** FormData @class FormData @constructor */ function FormData() { var _blob, _fields = []; Basic.extend(this, { /** Append another key-value pair to the FormData object @method append @param {String} name Name for the new field @param {String|Blob|Array|Object} value Value for the field */ append: function(name, value) { var self = this, valueType = Basic.typeOf(value); // according to specs value might be either Blob or String if (value instanceof Blob) { _blob = { name: name, value: value // unfortunately we can only send single Blob in one FormData }; } else if ('array' === valueType) { name += '[]'; Basic.each(value, function(value) { self.append(name, value); }); } else if ('object' === valueType) { Basic.each(value, function(value, key) { self.append(name + '[' + key + ']', value); }); } else if ('null' === valueType || 'undefined' === valueType || 'number' === valueType && isNaN(value)) { self.append(name, "false"); } else { _fields.push({ name: name, value: value.toString() }); } }, /** Checks if FormData contains Blob. @method hasBlob @return {Boolean} */ hasBlob: function() { return !!this.getBlob(); }, /** Retrieves blob. @method getBlob @return {Object} Either Blob if found or null */ getBlob: function() { return _blob && _blob.value || null; }, /** Retrieves blob field name. @method getBlobName @return {String} Either Blob field name or null */ getBlobName: function() { return _blob && _blob.name || null; }, /** Loop over the fields in FormData and invoke the callback for each of them. @method each @param {Function} cb Callback to call for each field */ each: function(cb) { Basic.each(_fields, function(field) { cb(field.value, field.name); }); if (_blob) { cb(_blob.value, _blob.name); } }, destroy: function() { _blob = null; _fields = []; } }); } return FormData; }); // Included from: src/javascript/xhr/XMLHttpRequest.js /** * XMLHttpRequest.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ define("moxie/xhr/XMLHttpRequest", [ "moxie/core/utils/Basic", "moxie/core/Exceptions", "moxie/core/EventTarget", "moxie/core/utils/Encode", "moxie/core/utils/Url", "moxie/runtime/Runtime", "moxie/runtime/RuntimeTarget", "moxie/file/Blob", "moxie/file/FileReaderSync", "moxie/xhr/FormData", "moxie/core/utils/Env", "moxie/core/utils/Mime" ], function(Basic, x, EventTarget, Encode, Url, Runtime, RuntimeTarget, Blob, FileReaderSync, FormData, Env, Mime) { var httpCode = { 100: 'Continue', 101: 'Switching Protocols', 102: 'Processing', 200: 'OK', 201: 'Created', 202: 'Accepted', 203: 'Non-Authoritative Information', 204: 'No Content', 205: 'Reset Content', 206: 'Partial Content', 207: 'Multi-Status', 226: 'IM Used', 300: 'Multiple Choices', 301: 'Moved Permanently', 302: 'Found', 303: 'See Other', 304: 'Not Modified', 305: 'Use Proxy', 306: 'Reserved', 307: 'Temporary Redirect', 400: 'Bad Request', 401: 'Unauthorized', 402: 'Payment Required', 403: 'Forbidden', 404: 'Not Found', 405: 'Method Not Allowed', 406: 'Not Acceptable', 407: 'Proxy Authentication Required', 408: 'Request Timeout', 409: 'Conflict', 410: 'Gone', 411: 'Length Required', 412: 'Precondition Failed', 413: 'Request Entity Too Large', 414: 'Request-URI Too Long', 415: 'Unsupported Media Type', 416: 'Requested Range Not Satisfiable', 417: 'Expectation Failed', 422: 'Unprocessable Entity', 423: 'Locked', 424: 'Failed Dependency', 426: 'Upgrade Required', 500: 'Internal Server Error', 501: 'Not Implemented', 502: 'Bad Gateway', 503: 'Service Unavailable', 504: 'Gateway Timeout', 505: 'HTTP Version Not Supported', 506: 'Variant Also Negotiates', 507: 'Insufficient Storage', 510: 'Not Extended' }; function XMLHttpRequestUpload() { this.uid = Basic.guid('uid_'); } XMLHttpRequestUpload.prototype = EventTarget.instance; /** Implementation of XMLHttpRequest @class XMLHttpRequest @constructor @uses RuntimeClient @extends EventTarget */ var dispatches = [ 'loadstart', 'progress', 'abort', 'error', 'load', 'timeout', 'loadend' // readystatechange (for historical reasons) ]; var NATIVE = 1, RUNTIME = 2; function XMLHttpRequest() { var self = this, // this (together with _p() @see below) is here to gracefully upgrade to setter/getter syntax where possible props = { /** The amount of milliseconds a request can take before being terminated. Initially zero. Zero means there is no timeout. @property timeout @type Number @default 0 */ timeout: 0, /** Current state, can take following values: UNSENT (numeric value 0) The object has been constructed. OPENED (numeric value 1) The open() method has been successfully invoked. During this state request headers can be set using setRequestHeader() and the request can be made using the send() method. HEADERS_RECEIVED (numeric value 2) All redirects (if any) have been followed and all HTTP headers of the final response have been received. Several response members of the object are now available. LOADING (numeric value 3) The response entity body is being received. DONE (numeric value 4) @property readyState @type Number @default 0 (UNSENT) */ readyState: XMLHttpRequest.UNSENT, /** True when user credentials are to be included in a cross-origin request. False when they are to be excluded in a cross-origin request and when cookies are to be ignored in its response. Initially false. @property withCredentials @type Boolean @default false */ withCredentials: false, /** Returns the HTTP status code. @property status @type Number @default 0 */ status: 0, /** Returns the HTTP status text. @property statusText @type String */ statusText: "", /** Returns the response type. Can be set to change the response type. Values are: the empty string (default), "arraybuffer", "blob", "document", "json", and "text". @property responseType @type String */ responseType: "", /** Returns the document response entity body. Throws an "InvalidStateError" exception if responseType is not the empty string or "document". @property responseXML @type Document */ responseXML: null, /** Returns the text response entity body. Throws an "InvalidStateError" exception if responseType is not the empty string or "text". @property responseText @type String */ responseText: null, /** Returns the response entity body (http://www.w3.org/TR/XMLHttpRequest/#response-entity-body). Can become: ArrayBuffer, Blob, Document, JSON, Text @property response @type Mixed */ response: null }, _async = true, _url, _method, _headers = {}, _user, _password, _encoding = null, _mimeType = null, // flags _sync_flag = false, _send_flag = false, _upload_events_flag = false, _upload_complete_flag = false, _error_flag = false, _same_origin_flag = false, // times _start_time, _timeoutset_time, _finalMime = null, _finalCharset = null, _options = {}, _xhr, _responseHeaders = '', _responseHeadersBag ; Basic.extend(this, props, { /** Unique id of the component @property uid @type String */ uid: Basic.guid('uid_'), /** Target for Upload events @property upload @type XMLHttpRequestUpload */ upload: new XMLHttpRequestUpload(), /** Sets the request method, request URL, synchronous flag, request username, and request password. Throws a "SyntaxError" exception if one of the following is true: method is not a valid HTTP method. url cannot be resolved. url contains the "user:password" format in the userinfo production. Throws a "SecurityError" exception if method is a case-insensitive match for CONNECT, TRACE or TRACK. Throws an "InvalidAccessError" exception if one of the following is true: Either user or password is passed as argument and the origin of url does not match the XMLHttpRequest origin. There is an associated XMLHttpRequest document and either the timeout attribute is not zero, the withCredentials attribute is true, or the responseType attribute is not the empty string. @method open @param {String} method HTTP method to use on request @param {String} url URL to request @param {Boolean} [async=true] If false request will be done in synchronous manner. Asynchronous by default. @param {String} [user] Username to use in HTTP authentication process on server-side @param {String} [password] Password to use in HTTP authentication process on server-side */ open: function(method, url, async, user, password) { var urlp; // first two arguments are required if (!method || !url) { throw new x.DOMException(x.DOMException.SYNTAX_ERR); } // 2 - check if any code point in method is higher than U+00FF or after deflating method it does not match the method if (/[\u0100-\uffff]/.test(method) || Encode.utf8_encode(method) !== method) { throw new x.DOMException(x.DOMException.SYNTAX_ERR); } // 3 if (!!~Basic.inArray(method.toUpperCase(), ['CONNECT', 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT', 'TRACE', 'TRACK'])) { _method = method.toUpperCase(); } // 4 - allowing these methods poses a security risk if (!!~Basic.inArray(_method, ['CONNECT', 'TRACE', 'TRACK'])) { throw new x.DOMException(x.DOMException.SECURITY_ERR); } // 5 url = Encode.utf8_encode(url); // 6 - Resolve url relative to the XMLHttpRequest base URL. If the algorithm returns an error, throw a "SyntaxError". urlp = Url.parseUrl(url); _same_origin_flag = Url.hasSameOrigin(urlp); // 7 - manually build up absolute url _url = Url.resolveUrl(url); // 9-10, 12-13 if ((user || password) && !_same_origin_flag) { throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR); } _user = user || urlp.user; _password = password || urlp.pass; // 11 _async = async || true; if (_async === false && (_p('timeout') || _p('withCredentials') || _p('responseType') !== "")) { throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR); } // 14 - terminate abort() // 15 - terminate send() // 18 _sync_flag = !_async; _send_flag = false; _headers = {}; _reset.call(this); // 19 _p('readyState', XMLHttpRequest.OPENED); // 20 this.dispatchEvent('readystatechange'); }, /** Appends an header to the list of author request headers, or if header is already in the list of author request headers, combines its value with value. Throws an "InvalidStateError" exception if the state is not OPENED or if the send() flag is set. Throws a "SyntaxError" exception if header is not a valid HTTP header field name or if value is not a valid HTTP header field value. @method setRequestHeader @param {String} header @param {String|Number} value */ setRequestHeader: function(header, value) { var uaHeaders = [ // these headers are controlled by the user agent "accept-charset", "accept-encoding", "access-control-request-headers", "access-control-request-method", "connection", "content-length", "cookie", "cookie2", "content-transfer-encoding", "date", "expect", "host", "keep-alive", "origin", "referer", "te", "trailer", "transfer-encoding", "upgrade", "user-agent", "via" ]; // 1-2 if (_p('readyState') !== XMLHttpRequest.OPENED || _send_flag) { throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); } // 3 if (/[\u0100-\uffff]/.test(header) || Encode.utf8_encode(header) !== header) { throw new x.DOMException(x.DOMException.SYNTAX_ERR); } // 4 /* this step is seemingly bypassed in browsers, probably to allow various unicode characters in header values if (/[\u0100-\uffff]/.test(value) || Encode.utf8_encode(value) !== value) { throw new x.DOMException(x.DOMException.SYNTAX_ERR); }*/ header = Basic.trim(header).toLowerCase(); // setting of proxy-* and sec-* headers is prohibited by spec if (!!~Basic.inArray(header, uaHeaders) || /^(proxy\-|sec\-)/.test(header)) { return false; } // camelize // browsers lowercase header names (at least for custom ones) // header = header.replace(/\b\w/g, function($1) { return $1.toUpperCase(); }); if (!_headers[header]) { _headers[header] = value; } else { // http://tools.ietf.org/html/rfc2616#section-4.2 (last paragraph) _headers[header] += ', ' + value; } return true; }, /** Returns all headers from the response, with the exception of those whose field name is Set-Cookie or Set-Cookie2. @method getAllResponseHeaders @return {String} reponse headers or empty string */ getAllResponseHeaders: function() { return _responseHeaders || ''; }, /** Returns the header field value from the response of which the field name matches header, unless the field name is Set-Cookie or Set-Cookie2. @method getResponseHeader @param {String} header @return {String} value(s) for the specified header or null */ getResponseHeader: function(header) { header = header.toLowerCase(); if (_error_flag || !!~Basic.inArray(header, ['set-cookie', 'set-cookie2'])) { return null; } if (_responseHeaders && _responseHeaders !== '') { // if we didn't parse response headers until now, do it and keep for later if (!_responseHeadersBag) { _responseHeadersBag = {}; Basic.each(_responseHeaders.split(/\r\n/), function(line) { var pair = line.split(/:\s+/); if (pair.length === 2) { // last line might be empty, omit pair[0] = Basic.trim(pair[0]); // just in case _responseHeadersBag[pair[0].toLowerCase()] = { // simply to retain header name in original form header: pair[0], value: Basic.trim(pair[1]) }; } }); } if (_responseHeadersBag.hasOwnProperty(header)) { return _responseHeadersBag[header].header + ': ' + _responseHeadersBag[header].value; } } return null; }, /** Sets the Content-Type header for the response to mime. Throws an "InvalidStateError" exception if the state is LOADING or DONE. Throws a "SyntaxError" exception if mime is not a valid media type. @method overrideMimeType @param String mime Mime type to set */ overrideMimeType: function(mime) { var matches, charset; // 1 if (!!~Basic.inArray(_p('readyState'), [XMLHttpRequest.LOADING, XMLHttpRequest.DONE])) { throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); } // 2 mime = Basic.trim(mime.toLowerCase()); if (/;/.test(mime) && (matches = mime.match(/^([^;]+)(?:;\scharset\=)?(.*)$/))) { mime = matches[1]; if (matches[2]) { charset = matches[2]; } } if (!Mime.mimes[mime]) { throw new x.DOMException(x.DOMException.SYNTAX_ERR); } // 3-4 _finalMime = mime; _finalCharset = charset; }, /** Initiates the request. The optional argument provides the request entity body. The argument is ignored if request method is GET or HEAD. Throws an "InvalidStateError" exception if the state is not OPENED or if the send() flag is set. @method send @param {Blob|Document|String|FormData} [data] Request entity body @param {Object} [options] Set of requirements and pre-requisities for runtime initialization */ send: function(data, options) { if (Basic.typeOf(options) === 'string') { _options = { ruid: options }; } else if (!options) { _options = {}; } else { _options = options; } // 1-2 if (this.readyState !== XMLHttpRequest.OPENED || _send_flag) { throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); } // 3 // sending Blob if (data instanceof Blob) { _options.ruid = data.ruid; _mimeType = data.type || 'application/octet-stream'; } // FormData else if (data instanceof FormData) { if (data.hasBlob()) { var blob = data.getBlob(); _options.ruid = blob.ruid; _mimeType = blob.type || 'application/octet-stream'; } } // DOMString else if (typeof data === 'string') { _encoding = 'UTF-8'; _mimeType = 'text/plain;charset=UTF-8'; // data should be converted to Unicode and encoded as UTF-8 data = Encode.utf8_encode(data); } // if withCredentials not set, but requested, set it automatically if (!this.withCredentials) { this.withCredentials = (_options.required_caps && _options.required_caps.send_browser_cookies) && !_same_origin_flag; } // 4 - storage mutex // 5 _upload_events_flag = (!_sync_flag && this.upload.hasEventListener()); // DSAP // 6 _error_flag = false; // 7 _upload_complete_flag = !data; // 8 - Asynchronous steps if (!_sync_flag) { // 8.1 _send_flag = true; // 8.2 // this.dispatchEvent('loadstart'); // will be dispatched either by native or runtime xhr // 8.3 //if (!_upload_complete_flag) { // this.upload.dispatchEvent('loadstart'); // will be dispatched either by native or runtime xhr //} } // 8.5 - Return the send() method call, but continue running the steps in this algorithm. _doXHR.call(this, data); }, /** Cancels any network activity. @method abort */ abort: function() { _error_flag = true; _sync_flag = false; if (!~Basic.inArray(_p('readyState'), [XMLHttpRequest.UNSENT, XMLHttpRequest.OPENED, XMLHttpRequest.DONE])) { _p('readyState', XMLHttpRequest.DONE); _send_flag = false; if (_xhr) { _xhr.getRuntime().exec.call(_xhr, 'XMLHttpRequest', 'abort', _upload_complete_flag); } else { throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); } _upload_complete_flag = true; } else { _p('readyState', XMLHttpRequest.UNSENT); } }, destroy: function() { if (_xhr) { if (Basic.typeOf(_xhr.destroy) === 'function') { _xhr.destroy(); } _xhr = null; } this.unbindAll(); if (this.upload) { this.upload.unbindAll(); this.upload = null; } } }); this.handleEventProps(dispatches.concat(['readystatechange'])); // for historical reasons this.upload.handleEventProps(dispatches); /* this is nice, but maybe too lengthy // if supported by JS version, set getters/setters for specific properties o.defineProperty(this, 'readyState', { configurable: false, get: function() { return _p('readyState'); } }); o.defineProperty(this, 'timeout', { configurable: false, get: function() { return _p('timeout'); }, set: function(value) { if (_sync_flag) { throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR); } // timeout still should be measured relative to the start time of request _timeoutset_time = (new Date).getTime(); _p('timeout', value); } }); // the withCredentials attribute has no effect when fetching same-origin resources o.defineProperty(this, 'withCredentials', { configurable: false, get: function() { return _p('withCredentials'); }, set: function(value) { // 1-2 if (!~o.inArray(_p('readyState'), [XMLHttpRequest.UNSENT, XMLHttpRequest.OPENED]) || _send_flag) { throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); } // 3-4 if (_anonymous_flag || _sync_flag) { throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR); } // 5 _p('withCredentials', value); } }); o.defineProperty(this, 'status', { configurable: false, get: function() { return _p('status'); } }); o.defineProperty(this, 'statusText', { configurable: false, get: function() { return _p('statusText'); } }); o.defineProperty(this, 'responseType', { configurable: false, get: function() { return _p('responseType'); }, set: function(value) { // 1 if (!!~o.inArray(_p('readyState'), [XMLHttpRequest.LOADING, XMLHttpRequest.DONE])) { throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); } // 2 if (_sync_flag) { throw new x.DOMException(x.DOMException.INVALID_ACCESS_ERR); } // 3 _p('responseType', value.toLowerCase()); } }); o.defineProperty(this, 'responseText', { configurable: false, get: function() { // 1 if (!~o.inArray(_p('responseType'), ['', 'text'])) { throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); } // 2-3 if (_p('readyState') !== XMLHttpRequest.DONE && _p('readyState') !== XMLHttpRequest.LOADING || _error_flag) { throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); } return _p('responseText'); } }); o.defineProperty(this, 'responseXML', { configurable: false, get: function() { // 1 if (!~o.inArray(_p('responseType'), ['', 'document'])) { throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); } // 2-3 if (_p('readyState') !== XMLHttpRequest.DONE || _error_flag) { throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); } return _p('responseXML'); } }); o.defineProperty(this, 'response', { configurable: false, get: function() { if (!!~o.inArray(_p('responseType'), ['', 'text'])) { if (_p('readyState') !== XMLHttpRequest.DONE && _p('readyState') !== XMLHttpRequest.LOADING || _error_flag) { return ''; } } if (_p('readyState') !== XMLHttpRequest.DONE || _error_flag) { return null; } return _p('response'); } }); */ function _p(prop, value) { if (!props.hasOwnProperty(prop)) { return; } if (arguments.length === 1) { // get return Env.can('define_property') ? props[prop] : self[prop]; } else { // set if (Env.can('define_property')) { props[prop] = value; } else { self[prop] = value; } } } /* function _toASCII(str, AllowUnassigned, UseSTD3ASCIIRules) { // TODO: http://tools.ietf.org/html/rfc3490#section-4.1 return str.toLowerCase(); } */ function _doXHR(data) { var self = this; _start_time = new Date().getTime(); _xhr = new RuntimeTarget(); function loadEnd() { if (_xhr) { // it could have been destroyed by now _xhr.destroy(); _xhr = null; } self.dispatchEvent('loadend'); self = null; } function exec(runtime) { _xhr.bind('LoadStart', function(e) { _p('readyState', XMLHttpRequest.LOADING); self.dispatchEvent('readystatechange'); self.dispatchEvent(e); if (_upload_events_flag) { self.upload.dispatchEvent(e); } }); _xhr.bind('Progress', function(e) { if (_p('readyState') !== XMLHttpRequest.LOADING) { _p('readyState', XMLHttpRequest.LOADING); // LoadStart unreliable (in Flash for example) self.dispatchEvent('readystatechange'); } self.dispatchEvent(e); }); _xhr.bind('UploadProgress', function(e) { if (_upload_events_flag) { self.upload.dispatchEvent({ type: 'progress', lengthComputable: false, total: e.total, loaded: e.loaded }); } }); _xhr.bind('Load', function(e) { _p('readyState', XMLHttpRequest.DONE); _p('status', Number(runtime.exec.call(_xhr, 'XMLHttpRequest', 'getStatus') || 0)); _p('statusText', httpCode[_p('status')] || ""); _p('response', runtime.exec.call(_xhr, 'XMLHttpRequest', 'getResponse', _p('responseType'))); if (!!~Basic.inArray(_p('responseType'), ['text', ''])) { _p('responseText', _p('response')); } else if (_p('responseType') === 'document') { _p('responseXML', _p('response')); } _responseHeaders = runtime.exec.call(_xhr, 'XMLHttpRequest', 'getAllResponseHeaders'); self.dispatchEvent('readystatechange'); if (_p('status') > 0) { // status 0 usually means that server is unreachable if (_upload_events_flag) { self.upload.dispatchEvent(e); } self.dispatchEvent(e); } else { _error_flag = true; self.dispatchEvent('error'); } loadEnd(); }); _xhr.bind('Abort', function(e) { self.dispatchEvent(e); loadEnd(); }); _xhr.bind('Error', function(e) { _error_flag = true; _p('readyState', XMLHttpRequest.DONE); self.dispatchEvent('readystatechange'); _upload_complete_flag = true; self.dispatchEvent(e); loadEnd(); }); runtime.exec.call(_xhr, 'XMLHttpRequest', 'send', { url: _url, method: _method, async: _async, user: _user, password: _password, headers: _headers, mimeType: _mimeType, encoding: _encoding, responseType: self.responseType, withCredentials: self.withCredentials, options: _options }, data); } // clarify our requirements if (typeof(_options.required_caps) === 'string') { _options.required_caps = Runtime.parseCaps(_options.required_caps); } _options.required_caps = Basic.extend({}, _options.required_caps, { return_response_type: self.responseType }); if (data instanceof FormData) { _options.required_caps.send_multipart = true; } if (!Basic.isEmptyObj(_headers)) { _options.required_caps.send_custom_headers = true; } if (!_same_origin_flag) { _options.required_caps.do_cors = true; } if (_options.ruid) { // we do not need to wait if we can connect directly exec(_xhr.connectRuntime(_options)); } else { _xhr.bind('RuntimeInit', function(e, runtime) { exec(runtime); }); _xhr.bind('RuntimeError', function(e, err) { self.dispatchEvent('RuntimeError', err); }); _xhr.connectRuntime(_options); } } function _reset() { _p('responseText', ""); _p('responseXML', null); _p('response', null); _p('status', 0); _p('statusText', ""); _start_time = _timeoutset_time = null; } } XMLHttpRequest.UNSENT = 0; XMLHttpRequest.OPENED = 1; XMLHttpRequest.HEADERS_RECEIVED = 2; XMLHttpRequest.LOADING = 3; XMLHttpRequest.DONE = 4; XMLHttpRequest.prototype = EventTarget.instance; return XMLHttpRequest; }); // Included from: src/javascript/runtime/Transporter.js /** * Transporter.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ define("moxie/runtime/Transporter", [ "moxie/core/utils/Basic", "moxie/core/utils/Encode", "moxie/runtime/RuntimeClient", "moxie/core/EventTarget" ], function(Basic, Encode, RuntimeClient, EventTarget) { function Transporter() { var mod, _runtime, _data, _size, _pos, _chunk_size; RuntimeClient.call(this); Basic.extend(this, { uid: Basic.guid('uid_'), state: Transporter.IDLE, result: null, transport: function(data, type, options) { var self = this; options = Basic.extend({ chunk_size: 204798 }, options); // should divide by three, base64 requires this if ((mod = options.chunk_size % 3)) { options.chunk_size += 3 - mod; } _chunk_size = options.chunk_size; _reset.call(this); _data = data; _size = data.length; if (Basic.typeOf(options) === 'string' || options.ruid) { _run.call(self, type, this.connectRuntime(options)); } else { // we require this to run only once var cb = function(e, runtime) { self.unbind("RuntimeInit", cb); _run.call(self, type, runtime); }; this.bind("RuntimeInit", cb); this.connectRuntime(options); } }, abort: function() { var self = this; self.state = Transporter.IDLE; if (_runtime) { _runtime.exec.call(self, 'Transporter', 'clear'); self.trigger("TransportingAborted"); } _reset.call(self); }, destroy: function() { this.unbindAll(); _runtime = null; this.disconnectRuntime(); _reset.call(this); } }); function _reset() { _size = _pos = 0; _data = this.result = null; } function _run(type, runtime) { var self = this; _runtime = runtime; //self.unbind("RuntimeInit"); self.bind("TransportingProgress", function(e) { _pos = e.loaded; if (_pos < _size && Basic.inArray(self.state, [Transporter.IDLE, Transporter.DONE]) === -1) { _transport.call(self); } }, 999); self.bind("TransportingComplete", function() { _pos = _size; self.state = Transporter.DONE; _data = null; // clean a bit self.result = _runtime.exec.call(self, 'Transporter', 'getAsBlob', type || ''); }, 999); self.state = Transporter.BUSY; self.trigger("TransportingStarted"); _transport.call(self); } function _transport() { var self = this, chunk, bytesLeft = _size - _pos; if (_chunk_size > bytesLeft) { _chunk_size = bytesLeft; } chunk = Encode.btoa(_data.substr(_pos, _chunk_size)); _runtime.exec.call(self, 'Transporter', 'receive', chunk, _size); } } Transporter.IDLE = 0; Transporter.BUSY = 1; Transporter.DONE = 2; Transporter.prototype = EventTarget.instance; return Transporter; }); // Included from: src/javascript/image/Image.js /** * Image.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ define("moxie/image/Image", [ "moxie/core/utils/Basic", "moxie/core/utils/Dom", "moxie/core/Exceptions", "moxie/file/FileReaderSync", "moxie/xhr/XMLHttpRequest", "moxie/runtime/Runtime", "moxie/runtime/RuntimeClient", "moxie/runtime/Transporter", "moxie/core/utils/Env", "moxie/core/EventTarget", "moxie/file/Blob", "moxie/file/File", "moxie/core/utils/Encode" ], function(Basic, Dom, x, FileReaderSync, XMLHttpRequest, Runtime, RuntimeClient, Transporter, Env, EventTarget, Blob, File, Encode) { /** Image preloading and manipulation utility. Additionally it provides access to image meta info (Exif, GPS) and raw binary data. @class Image @constructor @extends EventTarget */ var dispatches = [ 'progress', /** Dispatched when loading is complete. @event load @param {Object} event */ 'load', 'error', /** Dispatched when resize operation is complete. @event resize @param {Object} event */ 'resize', /** Dispatched when visual representation of the image is successfully embedded into the corresponsing container. @event embedded @param {Object} event */ 'embedded' ]; function Image() { RuntimeClient.call(this); Basic.extend(this, { /** Unique id of the component @property uid @type {String} */ uid: Basic.guid('uid_'), /** Unique id of the connected runtime, if any. @property ruid @type {String} */ ruid: null, /** Name of the file, that was used to create an image, if available. If not equals to empty string. @property name @type {String} @default "" */ name: "", /** Size of the image in bytes. Actual value is set only after image is preloaded. @property size @type {Number} @default 0 */ size: 0, /** Width of the image. Actual value is set only after image is preloaded. @property width @type {Number} @default 0 */ width: 0, /** Height of the image. Actual value is set only after image is preloaded. @property height @type {Number} @default 0 */ height: 0, /** Mime type of the image. Currently only image/jpeg and image/png are supported. Actual value is set only after image is preloaded. @property type @type {String} @default "" */ type: "", /** Holds meta info (Exif, GPS). Is populated only for image/jpeg. Actual value is set only after image is preloaded. @property meta @type {Object} @default {} */ meta: {}, /** Alias for load method, that takes another mOxie.Image object as a source (see load). @method clone @param {Image} src Source for the image @param {Boolean} [exact=false] Whether to activate in-depth clone mode */ clone: function() { this.load.apply(this, arguments); }, /** Loads image from various sources. Currently the source for new image can be: mOxie.Image, mOxie.Blob/mOxie.File, native Blob/File, dataUrl or URL. Depending on the type of the source, arguments - differ. When source is URL, Image will be downloaded from remote destination and loaded in memory. @example var img = new mOxie.Image(); img.onload = function() { var blob = img.getAsBlob(); var formData = new mOxie.FormData(); formData.append('file', blob); var xhr = new mOxie.XMLHttpRequest(); xhr.onload = function() { // upload complete }; xhr.open('post', 'upload.php'); xhr.send(formData); }; img.load("http://www.moxiecode.com/images/mox-logo.jpg"); // notice file extension (.jpg) @method load @param {Image|Blob|File|String} src Source for the image @param {Boolean|Object} [mixed] */ load: function() { _load.apply(this, arguments); }, /** Downsizes the image to fit the specified width/height. If crop is supplied, image will be cropped to exact dimensions. @method downsize @param {Object} opts @param {Number} opts.width Resulting width @param {Number} [opts.height=width] Resulting height (optional, if not supplied will default to width) @param {Boolean} [opts.crop=false] Whether to crop the image to exact dimensions @param {Boolean} [opts.preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize) @param {String} [opts.resample=false] Resampling algorithm to use for resizing */ downsize: function(opts) { var defaults = { width: this.width, height: this.height, type: this.type || 'image/jpeg', quality: 90, crop: false, preserveHeaders: true, resample: false }; if (typeof(opts) === 'object') { opts = Basic.extend(defaults, opts); } else { // for backward compatibility opts = Basic.extend(defaults, { width: arguments[0], height: arguments[1], crop: arguments[2], preserveHeaders: arguments[3] }); } try { if (!this.size) { // only preloaded image objects can be used as source throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); } // no way to reliably intercept the crash due to high resolution, so we simply avoid it if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) { throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR); } this.exec('Image', 'downsize', opts.width, opts.height, opts.crop, opts.preserveHeaders); } catch(ex) { // for now simply trigger error event this.trigger('error', ex.code); } }, /** Alias for downsize(width, height, true). (see downsize) @method crop @param {Number} width Resulting width @param {Number} [height=width] Resulting height (optional, if not supplied will default to width) @param {Boolean} [preserveHeaders=true] Whether to preserve meta headers (on JPEGs after resize) */ crop: function(width, height, preserveHeaders) { this.downsize(width, height, true, preserveHeaders); }, getAsCanvas: function() { if (!Env.can('create_canvas')) { throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR); } var runtime = this.connectRuntime(this.ruid); return runtime.exec.call(this, 'Image', 'getAsCanvas'); }, /** Retrieves image in it's current state as mOxie.Blob object. Cannot be run on empty or image in progress (throws DOMException.INVALID_STATE_ERR). @method getAsBlob @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png @param {Number} [quality=90] Applicable only together with mime type image/jpeg @return {Blob} Image as Blob */ getAsBlob: function(type, quality) { if (!this.size) { throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); } return this.exec('Image', 'getAsBlob', type || 'image/jpeg', quality || 90); }, /** Retrieves image in it's current state as dataURL string. Cannot be run on empty or image in progress (throws DOMException.INVALID_STATE_ERR). @method getAsDataURL @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png @param {Number} [quality=90] Applicable only together with mime type image/jpeg @return {String} Image as dataURL string */ getAsDataURL: function(type, quality) { if (!this.size) { throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); } return this.exec('Image', 'getAsDataURL', type || 'image/jpeg', quality || 90); }, /** Retrieves image in it's current state as binary string. Cannot be run on empty or image in progress (throws DOMException.INVALID_STATE_ERR). @method getAsBinaryString @param {String} [type="image/jpeg"] Mime type of resulting blob. Can either be image/jpeg or image/png @param {Number} [quality=90] Applicable only together with mime type image/jpeg @return {String} Image as binary string */ getAsBinaryString: function(type, quality) { var dataUrl = this.getAsDataURL(type, quality); return Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7)); }, /** Embeds a visual representation of the image into the specified node. Depending on the runtime, it might be a canvas, an img node or a thrid party shim object (Flash or SilverLight - very rare, can be used in legacy browsers that do not have canvas or proper dataURI support). @method embed @param {DOMElement} el DOM element to insert the image object into @param {Object} [opts] @param {Number} [opts.width] The width of an embed (defaults to the image width) @param {Number} [opts.height] The height of an embed (defaults to the image height) @param {String} [type="image/jpeg"] Mime type @param {Number} [quality=90] Quality of an embed, if mime type is image/jpeg @param {Boolean} [crop=false] Whether to crop an embed to the specified dimensions */ embed: function(el, opts) { var self = this , runtime // this has to be outside of all the closures to contain proper runtime ; opts = Basic.extend({ width: this.width, height: this.height, type: this.type || 'image/jpeg', quality: 90 }, opts || {}); function render(type, quality) { var img = this; // if possible, embed a canvas element directly if (Env.can('create_canvas')) { var canvas = img.getAsCanvas(); if (canvas) { el.appendChild(canvas); canvas = null; img.destroy(); self.trigger('embedded'); return; } } var dataUrl = img.getAsDataURL(type, quality); if (!dataUrl) { throw new x.ImageError(x.ImageError.WRONG_FORMAT); } if (Env.can('use_data_uri_of', dataUrl.length)) { el.innerHTML = ''; img.destroy(); self.trigger('embedded'); } else { var tr = new Transporter(); tr.bind("TransportingComplete", function() { runtime = self.connectRuntime(this.result.ruid); self.bind("Embedded", function() { // position and size properly Basic.extend(runtime.getShimContainer().style, { //position: 'relative', top: '0px', left: '0px', width: img.width + 'px', height: img.height + 'px' }); // some shims (Flash/SilverLight) reinitialize, if parent element is hidden, reordered or it's // position type changes (in Gecko), but since we basically need this only in IEs 6/7 and // sometimes 8 and they do not have this problem, we can comment this for now /*tr.bind("RuntimeInit", function(e, runtime) { tr.destroy(); runtime.destroy(); onResize.call(self); // re-feed our image data });*/ runtime = null; // release }, 999); runtime.exec.call(self, "ImageView", "display", this.result.uid, width, height); img.destroy(); }); tr.transport(Encode.atob(dataUrl.substring(dataUrl.indexOf('base64,') + 7)), type, { required_caps: { display_media: true }, runtime_order: 'flash,silverlight', container: el }); } } try { if (!(el = Dom.get(el))) { throw new x.DOMException(x.DOMException.INVALID_NODE_TYPE_ERR); } if (!this.size) { // only preloaded image objects can be used as source throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); } // high-resolution images cannot be consistently handled across the runtimes if (this.width > Image.MAX_RESIZE_WIDTH || this.height > Image.MAX_RESIZE_HEIGHT) { //throw new x.ImageError(x.ImageError.MAX_RESOLUTION_ERR); } var imgCopy = new Image(); imgCopy.bind("Resize", function() { render.call(this, opts.type, opts.quality); }); imgCopy.bind("Load", function() { imgCopy.downsize(opts); }); // if embedded thumb data is available and dimensions are big enough, use it if (this.meta.thumb && this.meta.thumb.width >= opts.width && this.meta.thumb.height >= opts.height) { imgCopy.load(this.meta.thumb.data); } else { imgCopy.clone(this, false); } return imgCopy; } catch(ex) { // for now simply trigger error event this.trigger('error', ex.code); } }, /** Properly destroys the image and frees resources in use. If any. Recommended way to dispose mOxie.Image object. @method destroy */ destroy: function() { if (this.ruid) { this.getRuntime().exec.call(this, 'Image', 'destroy'); this.disconnectRuntime(); } this.unbindAll(); } }); // this is here, because in order to bind properly, we need uid, which is created above this.handleEventProps(dispatches); this.bind('Load Resize', function() { _updateInfo.call(this); }, 999); function _updateInfo(info) { if (!info) { info = this.exec('Image', 'getInfo'); } this.size = info.size; this.width = info.width; this.height = info.height; this.type = info.type; this.meta = info.meta; // update file name, only if empty if (this.name === '') { this.name = info.name; } } function _load(src) { var srcType = Basic.typeOf(src); try { // if source is Image if (src instanceof Image) { if (!src.size) { // only preloaded image objects can be used as source throw new x.DOMException(x.DOMException.INVALID_STATE_ERR); } _loadFromImage.apply(this, arguments); } // if source is o.Blob/o.File else if (src instanceof Blob) { if (!~Basic.inArray(src.type, ['image/jpeg', 'image/png'])) { throw new x.ImageError(x.ImageError.WRONG_FORMAT); } _loadFromBlob.apply(this, arguments); } // if native blob/file else if (Basic.inArray(srcType, ['blob', 'file']) !== -1) { _load.call(this, new File(null, src), arguments[1]); } // if String else if (srcType === 'string') { // if dataUrl String if (src.substr(0, 5) === 'data:') { _load.call(this, new Blob(null, { data: src }), arguments[1]); } // else assume Url, either relative or absolute else { _loadFromUrl.apply(this, arguments); } } // if source seems to be an img node else if (srcType === 'node' && src.nodeName.toLowerCase() === 'img') { _load.call(this, src.src, arguments[1]); } else { throw new x.DOMException(x.DOMException.TYPE_MISMATCH_ERR); } } catch(ex) { // for now simply trigger error event this.trigger('error', ex.code); } } function _loadFromImage(img, exact) { var runtime = this.connectRuntime(img.ruid); this.ruid = runtime.uid; runtime.exec.call(this, 'Image', 'loadFromImage', img, (Basic.typeOf(exact) === 'undefined' ? true : exact)); } function _loadFromBlob(blob, options) { var self = this; self.name = blob.name || ''; function exec(runtime) { self.ruid = runtime.uid; runtime.exec.call(self, 'Image', 'loadFromBlob', blob); } if (blob.isDetached()) { this.bind('RuntimeInit', function(e, runtime) { exec(runtime); }); // convert to object representation if (options && typeof(options.required_caps) === 'string') { options.required_caps = Runtime.parseCaps(options.required_caps); } this.connectRuntime(Basic.extend({ required_caps: { access_image_binary: true, resize_image: true } }, options)); } else { exec(this.connectRuntime(blob.ruid)); } } function _loadFromUrl(url, options) { var self = this, xhr; xhr = new XMLHttpRequest(); xhr.open('get', url); xhr.responseType = 'blob'; xhr.onprogress = function(e) { self.trigger(e); }; xhr.onload = function() { _loadFromBlob.call(self, xhr.response, true); }; xhr.onerror = function(e) { self.trigger(e); }; xhr.onloadend = function() { xhr.destroy(); }; xhr.bind('RuntimeError', function(e, err) { self.trigger('RuntimeError', err); }); xhr.send(null, options); } } // virtual world will crash on you if image has a resolution higher than this: Image.MAX_RESIZE_WIDTH = 8192; Image.MAX_RESIZE_HEIGHT = 8192; Image.prototype = EventTarget.instance; return Image; }); // Included from: src/javascript/runtime/html5/Runtime.js /** * Runtime.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ /*global File:true */ /** Defines constructor for HTML5 runtime. @class moxie/runtime/html5/Runtime @private */ define("moxie/runtime/html5/Runtime", [ "moxie/core/utils/Basic", "moxie/core/Exceptions", "moxie/runtime/Runtime", "moxie/core/utils/Env" ], function(Basic, x, Runtime, Env) { var type = "html5", extensions = {}; function Html5Runtime(options) { var I = this , Test = Runtime.capTest , True = Runtime.capTrue ; var caps = Basic.extend({ access_binary: Test(window.FileReader || window.File && window.File.getAsDataURL), access_image_binary: function() { return I.can('access_binary') && !!extensions.Image; }, display_media: Test(Env.can('create_canvas') || Env.can('use_data_uri_over32kb')), do_cors: Test(window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()), drag_and_drop: Test(function() { // this comes directly from Modernizr: http://www.modernizr.com/ var div = document.createElement('div'); // IE has support for drag and drop since version 5, but doesn't support dropping files from desktop return (('draggable' in div) || ('ondragstart' in div && 'ondrop' in div)) && (Env.browser !== 'IE' || Env.verComp(Env.version, 9, '>')); }()), filter_by_extension: Test(function() { // if you know how to feature-detect this, please suggest return (Env.browser === 'Chrome' && Env.verComp(Env.version, 28, '>=')) || (Env.browser === 'IE' && Env.verComp(Env.version, 10, '>=')) || (Env.browser === 'Safari' && Env.verComp(Env.version, 7, '>=')); }()), return_response_headers: True, return_response_type: function(responseType) { if (responseType === 'json' && !!window.JSON) { // we can fake this one even if it's not supported return true; } return Env.can('return_response_type', responseType); }, return_status_code: True, report_upload_progress: Test(window.XMLHttpRequest && new XMLHttpRequest().upload), resize_image: function() { return I.can('access_binary') && Env.can('create_canvas'); }, select_file: function() { return Env.can('use_fileinput') && window.File; }, select_folder: function() { return I.can('select_file') && Env.browser === 'Chrome' && Env.verComp(Env.version, 21, '>='); }, select_multiple: function() { // it is buggy on Safari Windows and iOS return I.can('select_file') && !(Env.browser === 'Safari' && Env.os === 'Windows') && !(Env.os === 'iOS' && Env.verComp(Env.osVersion, "7.0.0", '>') && Env.verComp(Env.osVersion, "8.0.0", '<')); }, send_binary_string: Test(window.XMLHttpRequest && (new XMLHttpRequest().sendAsBinary || (window.Uint8Array && window.ArrayBuffer))), send_custom_headers: Test(window.XMLHttpRequest), send_multipart: function() { return !!(window.XMLHttpRequest && new XMLHttpRequest().upload && window.FormData) || I.can('send_binary_string'); }, slice_blob: Test(window.File && (File.prototype.mozSlice || File.prototype.webkitSlice || File.prototype.slice)), stream_upload: function(){ return I.can('slice_blob') && I.can('send_multipart'); }, summon_file_dialog: function() { // yeah... some dirty sniffing here... return I.can('select_file') && ( (Env.browser === 'Firefox' && Env.verComp(Env.version, 4, '>=')) || (Env.browser === 'Opera' && Env.verComp(Env.version, 12, '>=')) || (Env.browser === 'IE' && Env.verComp(Env.version, 10, '>=')) || !!~Basic.inArray(Env.browser, ['Chrome', 'Safari']) ); }, upload_filesize: True }, arguments[2] ); Runtime.call(this, options, (arguments[1] || type), caps); Basic.extend(this, { init : function() { this.trigger("Init"); }, destroy: (function(destroy) { // extend default destroy method return function() { destroy.call(I); destroy = I = null; }; }(this.destroy)) }); Basic.extend(this.getShim(), extensions); } Runtime.addConstructor(type, Html5Runtime); return extensions; }); // Included from: src/javascript/core/utils/Events.js /** * Events.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ define('moxie/core/utils/Events', [ 'moxie/core/utils/Basic' ], function(Basic) { var eventhash = {}, uid = 'moxie_' + Basic.guid(); // IE W3C like event funcs function preventDefault() { this.returnValue = false; } function stopPropagation() { this.cancelBubble = true; } /** Adds an event handler to the specified object and store reference to the handler in objects internal Plupload registry (@see removeEvent). @method addEvent @for Utils @static @param {Object} obj DOM element like object to add handler to. @param {String} name Name to add event listener to. @param {Function} callback Function to call when event occurs. @param {String} [key] that might be used to add specifity to the event record. */ var addEvent = function(obj, name, callback, key) { var func, events; name = name.toLowerCase(); // Add event listener if (obj.addEventListener) { func = callback; obj.addEventListener(name, func, false); } else if (obj.attachEvent) { func = function() { var evt = window.event; if (!evt.target) { evt.target = evt.srcElement; } evt.preventDefault = preventDefault; evt.stopPropagation = stopPropagation; callback(evt); }; obj.attachEvent('on' + name, func); } // Log event handler to objects internal mOxie registry if (!obj[uid]) { obj[uid] = Basic.guid(); } if (!eventhash.hasOwnProperty(obj[uid])) { eventhash[obj[uid]] = {}; } events = eventhash[obj[uid]]; if (!events.hasOwnProperty(name)) { events[name] = []; } events[name].push({ func: func, orig: callback, // store original callback for IE key: key }); }; /** Remove event handler from the specified object. If third argument (callback) is not specified remove all events with the specified name. @method removeEvent @static @param {Object} obj DOM element to remove event listener(s) from. @param {String} name Name of event listener to remove. @param {Function|String} [callback] might be a callback or unique key to match. */ var removeEvent = function(obj, name, callback) { var type, undef; name = name.toLowerCase(); if (obj[uid] && eventhash[obj[uid]] && eventhash[obj[uid]][name]) { type = eventhash[obj[uid]][name]; } else { return; } for (var i = type.length - 1; i >= 0; i--) { // undefined or not, key should match if (type[i].orig === callback || type[i].key === callback) { if (obj.removeEventListener) { obj.removeEventListener(name, type[i].func, false); } else if (obj.detachEvent) { obj.detachEvent('on'+name, type[i].func); } type[i].orig = null; type[i].func = null; type.splice(i, 1); // If callback was passed we are done here, otherwise proceed if (callback !== undef) { break; } } } // If event array got empty, remove it if (!type.length) { delete eventhash[obj[uid]][name]; } // If mOxie registry has become empty, remove it if (Basic.isEmptyObj(eventhash[obj[uid]])) { delete eventhash[obj[uid]]; // IE doesn't let you remove DOM object property with - delete try { delete obj[uid]; } catch(e) { obj[uid] = undef; } } }; /** Remove all kind of events from the specified object @method removeAllEvents @static @param {Object} obj DOM element to remove event listeners from. @param {String} [key] unique key to match, when removing events. */ var removeAllEvents = function(obj, key) { if (!obj || !obj[uid]) { return; } Basic.each(eventhash[obj[uid]], function(events, name) { removeEvent(obj, name, key); }); }; return { addEvent: addEvent, removeEvent: removeEvent, removeAllEvents: removeAllEvents }; }); // Included from: src/javascript/runtime/html5/file/FileInput.js /** * FileInput.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ /** @class moxie/runtime/html5/file/FileInput @private */ define("moxie/runtime/html5/file/FileInput", [ "moxie/runtime/html5/Runtime", "moxie/file/File", "moxie/core/utils/Basic", "moxie/core/utils/Dom", "moxie/core/utils/Events", "moxie/core/utils/Mime", "moxie/core/utils/Env" ], function(extensions, File, Basic, Dom, Events, Mime, Env) { function FileInput() { var _options; Basic.extend(this, { init: function(options) { var comp = this, I = comp.getRuntime(), input, shimContainer, mimes, browseButton, zIndex, top; _options = options; // figure out accept string mimes = _options.accept.mimes || Mime.extList2mimes(_options.accept, I.can('filter_by_extension')); shimContainer = I.getShimContainer(); shimContainer.innerHTML = ''; input = Dom.get(I.uid); // prepare file input to be placed underneath the browse_button element Basic.extend(input.style, { position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }); browseButton = Dom.get(_options.browse_button); // Route click event to the input[type=file] element for browsers that support such behavior if (I.can('summon_file_dialog')) { if (Dom.getStyle(browseButton, 'position') === 'static') { browseButton.style.position = 'relative'; } zIndex = parseInt(Dom.getStyle(browseButton, 'z-index'), 10) || 1; browseButton.style.zIndex = zIndex; shimContainer.style.zIndex = zIndex - 1; Events.addEvent(browseButton, 'click', function(e) { var input = Dom.get(I.uid); if (input && !input.disabled) { // for some reason FF (up to 8.0.1 so far) lets to click disabled input[type=file] input.click(); } e.preventDefault(); }, comp.uid); } /* Since we have to place input[type=file] on top of the browse_button for some browsers, browse_button loses interactivity, so we restore it here */ top = I.can('summon_file_dialog') ? browseButton : shimContainer; Events.addEvent(top, 'mouseover', function() { comp.trigger('mouseenter'); }, comp.uid); Events.addEvent(top, 'mouseout', function() { comp.trigger('mouseleave'); }, comp.uid); Events.addEvent(top, 'mousedown', function() { comp.trigger('mousedown'); }, comp.uid); Events.addEvent(Dom.get(_options.container), 'mouseup', function() { comp.trigger('mouseup'); }, comp.uid); input.onchange = function onChange(e) { // there should be only one handler for this comp.files = []; Basic.each(this.files, function(file) { var relativePath = ''; if (_options.directory) { // folders are represented by dots, filter them out (Chrome 11+) if (file.name == ".") { // if it looks like a folder... return true; } } if (file.webkitRelativePath) { relativePath = '/' + file.webkitRelativePath.replace(/^\//, ''); } file = new File(I.uid, file); file.relativePath = relativePath; comp.files.push(file); }); // clearing the value enables the user to select the same file again if they want to if (Env.browser !== 'IE' && Env.browser !== 'IEMobile') { this.value = ''; } else { // in IE input[type="file"] is read-only so the only way to reset it is to re-insert it var clone = this.cloneNode(true); this.parentNode.replaceChild(clone, this); clone.onchange = onChange; } if (comp.files.length) { comp.trigger('change'); } }; // ready event is perfectly asynchronous comp.trigger({ type: 'ready', async: true }); shimContainer = null; }, disable: function(state) { var I = this.getRuntime(), input; if ((input = Dom.get(I.uid))) { input.disabled = !!state; } }, destroy: function() { var I = this.getRuntime() , shim = I.getShim() , shimContainer = I.getShimContainer() ; Events.removeAllEvents(shimContainer, this.uid); Events.removeAllEvents(_options && Dom.get(_options.container), this.uid); Events.removeAllEvents(_options && Dom.get(_options.browse_button), this.uid); if (shimContainer) { shimContainer.innerHTML = ''; } shim.removeInstance(this.uid); _options = shimContainer = shim = null; } }); } return (extensions.FileInput = FileInput); }); // Included from: src/javascript/runtime/html5/file/Blob.js /** * Blob.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ /** @class moxie/runtime/html5/file/Blob @private */ define("moxie/runtime/html5/file/Blob", [ "moxie/runtime/html5/Runtime", "moxie/file/Blob" ], function(extensions, Blob) { function HTML5Blob() { function w3cBlobSlice(blob, start, end) { var blobSlice; if (window.File.prototype.slice) { try { blob.slice(); // depricated version will throw WRONG_ARGUMENTS_ERR exception return blob.slice(start, end); } catch (e) { // depricated slice method return blob.slice(start, end - start); } // slice method got prefixed: https://bugzilla.mozilla.org/show_bug.cgi?id=649672 } else if ((blobSlice = window.File.prototype.webkitSlice || window.File.prototype.mozSlice)) { return blobSlice.call(blob, start, end); } else { return null; // or throw some exception } } this.slice = function() { return new Blob(this.getRuntime().uid, w3cBlobSlice.apply(this, arguments)); }; } return (extensions.Blob = HTML5Blob); }); // Included from: src/javascript/runtime/html5/file/FileDrop.js /** * FileDrop.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ /** @class moxie/runtime/html5/file/FileDrop @private */ define("moxie/runtime/html5/file/FileDrop", [ "moxie/runtime/html5/Runtime", 'moxie/file/File', "moxie/core/utils/Basic", "moxie/core/utils/Dom", "moxie/core/utils/Events", "moxie/core/utils/Mime" ], function(extensions, File, Basic, Dom, Events, Mime) { function FileDrop() { var _files = [], _allowedExts = [], _options, _ruid; Basic.extend(this, { init: function(options) { var comp = this, dropZone; _options = options; _ruid = comp.ruid; // every dropped-in file should have a reference to the runtime _allowedExts = _extractExts(_options.accept); dropZone = _options.container; Events.addEvent(dropZone, 'dragover', function(e) { if (!_hasFiles(e)) { return; } e.preventDefault(); e.dataTransfer.dropEffect = 'copy'; }, comp.uid); Events.addEvent(dropZone, 'drop', function(e) { if (!_hasFiles(e)) { return; } e.preventDefault(); _files = []; // Chrome 21+ accepts folders via Drag'n'Drop if (e.dataTransfer.items && e.dataTransfer.items[0].webkitGetAsEntry) { _readItems(e.dataTransfer.items, function() { comp.files = _files; comp.trigger("drop"); }); } else { Basic.each(e.dataTransfer.files, function(file) { _addFile(file); }); comp.files = _files; comp.trigger("drop"); } }, comp.uid); Events.addEvent(dropZone, 'dragenter', function(e) { comp.trigger("dragenter"); }, comp.uid); Events.addEvent(dropZone, 'dragleave', function(e) { comp.trigger("dragleave"); }, comp.uid); }, destroy: function() { Events.removeAllEvents(_options && Dom.get(_options.container), this.uid); _ruid = _files = _allowedExts = _options = null; } }); function _hasFiles(e) { if (!e.dataTransfer || !e.dataTransfer.types) { // e.dataTransfer.files is not available in Gecko during dragover return false; } var types = Basic.toArray(e.dataTransfer.types || []); return Basic.inArray("Files", types) !== -1 || Basic.inArray("public.file-url", types) !== -1 || // Safari < 5 Basic.inArray("application/x-moz-file", types) !== -1 // Gecko < 1.9.2 (< Firefox 3.6) ; } function _addFile(file, relativePath) { if (_isAcceptable(file)) { var fileObj = new File(_ruid, file); fileObj.relativePath = relativePath || ''; _files.push(fileObj); } } function _extractExts(accept) { var exts = []; for (var i = 0; i < accept.length; i++) { [].push.apply(exts, accept[i].extensions.split(/\s*,\s*/)); } return Basic.inArray('*', exts) === -1 ? exts : []; } function _isAcceptable(file) { if (!_allowedExts.length) { return true; } var ext = Mime.getFileExtension(file.name); return !ext || Basic.inArray(ext, _allowedExts) !== -1; } function _readItems(items, cb) { var entries = []; Basic.each(items, function(item) { var entry = item.webkitGetAsEntry(); // Address #998 (https://code.google.com/p/chromium/issues/detail?id=332579) if (entry) { // file() fails on OSX when the filename contains a special character (e.g. umlaut): see #61 if (entry.isFile) { _addFile(item.getAsFile(), entry.fullPath); } else { entries.push(entry); } } }); if (entries.length) { _readEntries(entries, cb); } else { cb(); } } function _readEntries(entries, cb) { var queue = []; Basic.each(entries, function(entry) { queue.push(function(cbcb) { _readEntry(entry, cbcb); }); }); Basic.inSeries(queue, function() { cb(); }); } function _readEntry(entry, cb) { if (entry.isFile) { entry.file(function(file) { _addFile(file, entry.fullPath); cb(); }, function() { // fire an error event maybe cb(); }); } else if (entry.isDirectory) { _readDirEntry(entry, cb); } else { cb(); // not file, not directory? what then?.. } } function _readDirEntry(dirEntry, cb) { var entries = [], dirReader = dirEntry.createReader(); // keep quering recursively till no more entries function getEntries(cbcb) { dirReader.readEntries(function(moreEntries) { if (moreEntries.length) { [].push.apply(entries, moreEntries); getEntries(cbcb); } else { cbcb(); } }, cbcb); } // ...and you thought FileReader was crazy... getEntries(function() { _readEntries(entries, cb); }); } } return (extensions.FileDrop = FileDrop); }); // Included from: src/javascript/runtime/html5/file/FileReader.js /** * FileReader.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ /** @class moxie/runtime/html5/file/FileReader @private */ define("moxie/runtime/html5/file/FileReader", [ "moxie/runtime/html5/Runtime", "moxie/core/utils/Encode", "moxie/core/utils/Basic" ], function(extensions, Encode, Basic) { function FileReader() { var _fr, _convertToBinary = false; Basic.extend(this, { read: function(op, blob) { var comp = this; comp.result = ''; _fr = new window.FileReader(); _fr.addEventListener('progress', function(e) { comp.trigger(e); }); _fr.addEventListener('load', function(e) { comp.result = _convertToBinary ? _toBinary(_fr.result) : _fr.result; comp.trigger(e); }); _fr.addEventListener('error', function(e) { comp.trigger(e, _fr.error); }); _fr.addEventListener('loadend', function(e) { _fr = null; comp.trigger(e); }); if (Basic.typeOf(_fr[op]) === 'function') { _convertToBinary = false; _fr[op](blob.getSource()); } else if (op === 'readAsBinaryString') { // readAsBinaryString is depricated in general and never existed in IE10+ _convertToBinary = true; _fr.readAsDataURL(blob.getSource()); } }, abort: function() { if (_fr) { _fr.abort(); } }, destroy: function() { _fr = null; } }); function _toBinary(str) { return Encode.atob(str.substring(str.indexOf('base64,') + 7)); } } return (extensions.FileReader = FileReader); }); // Included from: src/javascript/runtime/html5/xhr/XMLHttpRequest.js /** * XMLHttpRequest.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ /*global ActiveXObject:true */ /** @class moxie/runtime/html5/xhr/XMLHttpRequest @private */ define("moxie/runtime/html5/xhr/XMLHttpRequest", [ "moxie/runtime/html5/Runtime", "moxie/core/utils/Basic", "moxie/core/utils/Mime", "moxie/core/utils/Url", "moxie/file/File", "moxie/file/Blob", "moxie/xhr/FormData", "moxie/core/Exceptions", "moxie/core/utils/Env" ], function(extensions, Basic, Mime, Url, File, Blob, FormData, x, Env) { function XMLHttpRequest() { var self = this , _xhr , _filename ; Basic.extend(this, { send: function(meta, data) { var target = this , isGecko2_5_6 = (Env.browser === 'Mozilla' && Env.verComp(Env.version, 4, '>=') && Env.verComp(Env.version, 7, '<')) , isAndroidBrowser = Env.browser === 'Android Browser' , mustSendAsBinary = false ; // extract file name _filename = meta.url.replace(/^.+?\/([\w\-\.]+)$/, '$1').toLowerCase(); _xhr = _getNativeXHR(); _xhr.open(meta.method, meta.url, meta.async, meta.user, meta.password); // prepare data to be sent if (data instanceof Blob) { if (data.isDetached()) { mustSendAsBinary = true; } data = data.getSource(); } else if (data instanceof FormData) { if (data.hasBlob()) { if (data.getBlob().isDetached()) { data = _prepareMultipart.call(target, data); // _xhr must be instantiated and be in OPENED state mustSendAsBinary = true; } else if ((isGecko2_5_6 || isAndroidBrowser) && Basic.typeOf(data.getBlob().getSource()) === 'blob' && window.FileReader) { // Gecko 2/5/6 can't send blob in FormData: https://bugzilla.mozilla.org/show_bug.cgi?id=649150 // Android browsers (default one and Dolphin) seem to have the same issue, see: #613 _preloadAndSend.call(target, meta, data); return; // _preloadAndSend will reinvoke send() with transmutated FormData =%D } } // transfer fields to real FormData if (data instanceof FormData) { // if still a FormData, e.g. not mangled by _prepareMultipart() var fd = new window.FormData(); data.each(function(value, name) { if (value instanceof Blob) { fd.append(name, value.getSource()); } else { fd.append(name, value); } }); data = fd; } } // if XHR L2 if (_xhr.upload) { if (meta.withCredentials) { _xhr.withCredentials = true; } _xhr.addEventListener('load', function(e) { target.trigger(e); }); _xhr.addEventListener('error', function(e) { target.trigger(e); }); // additionally listen to progress events _xhr.addEventListener('progress', function(e) { target.trigger(e); }); _xhr.upload.addEventListener('progress', function(e) { target.trigger({ type: 'UploadProgress', loaded: e.loaded, total: e.total }); }); // ... otherwise simulate XHR L2 } else { _xhr.onreadystatechange = function onReadyStateChange() { // fake Level 2 events switch (_xhr.readyState) { case 1: // XMLHttpRequest.OPENED // readystatechanged is fired twice for OPENED state (in IE and Mozilla) - neu break; // looks like HEADERS_RECEIVED (state 2) is not reported in Opera (or it's old versions) - neu case 2: // XMLHttpRequest.HEADERS_RECEIVED break; case 3: // XMLHttpRequest.LOADING // try to fire progress event for not XHR L2 var total, loaded; try { if (Url.hasSameOrigin(meta.url)) { // Content-Length not accessible for cross-domain on some browsers total = _xhr.getResponseHeader('Content-Length') || 0; // old Safari throws an exception here } if (_xhr.responseText) { // responseText was introduced in IE7 loaded = _xhr.responseText.length; } } catch(ex) { total = loaded = 0; } target.trigger({ type: 'progress', lengthComputable: !!total, total: parseInt(total, 10), loaded: loaded }); break; case 4: // XMLHttpRequest.DONE // release readystatechange handler (mostly for IE) _xhr.onreadystatechange = function() {}; // usually status 0 is returned when server is unreachable, but FF also fails to status 0 for 408 timeout if (_xhr.status === 0) { target.trigger('error'); } else { target.trigger('load'); } break; } }; } // set request headers if (!Basic.isEmptyObj(meta.headers)) { Basic.each(meta.headers, function(value, header) { _xhr.setRequestHeader(header, value); }); } // request response type if ("" !== meta.responseType && 'responseType' in _xhr) { if ('json' === meta.responseType && !Env.can('return_response_type', 'json')) { // we can fake this one _xhr.responseType = 'text'; } else { _xhr.responseType = meta.responseType; } } // send ... if (!mustSendAsBinary) { _xhr.send(data); } else { if (_xhr.sendAsBinary) { // Gecko _xhr.sendAsBinary(data); } else { // other browsers having support for typed arrays (function() { // mimic Gecko's sendAsBinary var ui8a = new Uint8Array(data.length); for (var i = 0; i < data.length; i++) { ui8a[i] = (data.charCodeAt(i) & 0xff); } _xhr.send(ui8a.buffer); }()); } } target.trigger('loadstart'); }, getStatus: function() { // according to W3C spec it should return 0 for readyState < 3, but instead it throws an exception try { if (_xhr) { return _xhr.status; } } catch(ex) {} return 0; }, getResponse: function(responseType) { var I = this.getRuntime(); try { switch (responseType) { case 'blob': var file = new File(I.uid, _xhr.response); // try to extract file name from content-disposition if possible (might be - not, if CORS for example) var disposition = _xhr.getResponseHeader('Content-Disposition'); if (disposition) { // extract filename from response header if available var match = disposition.match(/filename=([\'\"'])([^\1]+)\1/); if (match) { _filename = match[2]; } } file.name = _filename; // pre-webkit Opera doesn't set type property on the blob response if (!file.type) { file.type = Mime.getFileMime(_filename); } return file; case 'json': if (!Env.can('return_response_type', 'json')) { return _xhr.status === 200 && !!window.JSON ? JSON.parse(_xhr.responseText) : null; } return _xhr.response; case 'document': return _getDocument(_xhr); default: return _xhr.responseText !== '' ? _xhr.responseText : null; // against the specs, but for consistency across the runtimes } } catch(ex) { return null; } }, getAllResponseHeaders: function() { try { return _xhr.getAllResponseHeaders(); } catch(ex) {} return ''; }, abort: function() { if (_xhr) { _xhr.abort(); } }, destroy: function() { self = _filename = null; } }); // here we go... ugly fix for ugly bug function _preloadAndSend(meta, data) { var target = this, blob, fr; // get original blob blob = data.getBlob().getSource(); // preload blob in memory to be sent as binary string fr = new window.FileReader(); fr.onload = function() { // overwrite original blob data.append(data.getBlobName(), new Blob(null, { type: blob.type, data: fr.result })); // invoke send operation again self.send.call(target, meta, data); }; fr.readAsBinaryString(blob); } function _getNativeXHR() { if (window.XMLHttpRequest && !(Env.browser === 'IE' && Env.verComp(Env.version, 8, '<'))) { // IE7 has native XHR but it's buggy return new window.XMLHttpRequest(); } else { return (function() { var progIDs = ['Msxml2.XMLHTTP.6.0', 'Microsoft.XMLHTTP']; // if 6.0 available, use it, otherwise failback to default 3.0 for (var i = 0; i < progIDs.length; i++) { try { return new ActiveXObject(progIDs[i]); } catch (ex) {} } })(); } } // @credits Sergey Ilinsky (http://www.ilinsky.com/) function _getDocument(xhr) { var rXML = xhr.responseXML; var rText = xhr.responseText; // Try parsing responseText (@see: http://www.ilinsky.com/articles/XMLHttpRequest/#bugs-ie-responseXML-content-type) if (Env.browser === 'IE' && rText && rXML && !rXML.documentElement && /[^\/]+\/[^\+]+\+xml/.test(xhr.getResponseHeader("Content-Type"))) { rXML = new window.ActiveXObject("Microsoft.XMLDOM"); rXML.async = false; rXML.validateOnParse = false; rXML.loadXML(rText); } // Check if there is no error in document if (rXML) { if ((Env.browser === 'IE' && rXML.parseError !== 0) || !rXML.documentElement || rXML.documentElement.tagName === "parsererror") { return null; } } return rXML; } function _prepareMultipart(fd) { var boundary = '----moxieboundary' + new Date().getTime() , dashdash = '--' , crlf = '\r\n' , multipart = '' , I = this.getRuntime() ; if (!I.can('send_binary_string')) { throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR); } _xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary); // append multipart parameters fd.each(function(value, name) { // Firefox 3.6 failed to convert multibyte characters to UTF-8 in sendAsBinary(), // so we try it here ourselves with: unescape(encodeURIComponent(value)) if (value instanceof Blob) { // Build RFC2388 blob multipart += dashdash + boundary + crlf + 'Content-Disposition: form-data; name="' + name + '"; filename="' + unescape(encodeURIComponent(value.name || 'blob')) + '"' + crlf + 'Content-Type: ' + (value.type || 'application/octet-stream') + crlf + crlf + value.getSource() + crlf; } else { multipart += dashdash + boundary + crlf + 'Content-Disposition: form-data; name="' + name + '"' + crlf + crlf + unescape(encodeURIComponent(value)) + crlf; } }); multipart += dashdash + boundary + dashdash + crlf; return multipart; } } return (extensions.XMLHttpRequest = XMLHttpRequest); }); // Included from: src/javascript/runtime/html5/utils/BinaryReader.js /** * BinaryReader.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ /** @class moxie/runtime/html5/utils/BinaryReader @private */ define("moxie/runtime/html5/utils/BinaryReader", [ "moxie/core/utils/Basic" ], function(Basic) { function BinaryReader(data) { if (data instanceof ArrayBuffer) { ArrayBufferReader.apply(this, arguments); } else { UTF16StringReader.apply(this, arguments); } }   Basic.extend(BinaryReader.prototype, { littleEndian: false, read: function(idx, size) { var sum, mv, i; if (idx + size > this.length()) { throw new Error("You are trying to read outside the source boundaries."); } mv = this.littleEndian ? 0 : -8 * (size - 1) ; for (i = 0, sum = 0; i < size; i++) { sum |= (this.readByteAt(idx + i) << Math.abs(mv + i*8)); } return sum; }, write: function(idx, num, size) { var mv, i, str = ''; if (idx > this.length()) { throw new Error("You are trying to write outside the source boundaries."); } mv = this.littleEndian ? 0 : -8 * (size - 1) ; for (i = 0; i < size; i++) { this.writeByteAt(idx + i, (num >> Math.abs(mv + i*8)) & 255); } }, BYTE: function(idx) { return this.read(idx, 1); }, SHORT: function(idx) { return this.read(idx, 2); }, LONG: function(idx) { return this.read(idx, 4); }, SLONG: function(idx) { // 2's complement notation var num = this.read(idx, 4); return (num > 2147483647 ? num - 4294967296 : num); }, CHAR: function(idx) { return String.fromCharCode(this.read(idx, 1)); }, STRING: function(idx, count) { return this.asArray('CHAR', idx, count).join(''); }, asArray: function(type, idx, count) { var values = []; for (var i = 0; i < count; i++) { values[i] = this[type](idx + i); } return values; } }); function ArrayBufferReader(data) { var _dv = new DataView(data); Basic.extend(this, { readByteAt: function(idx) { return _dv.getUint8(idx); }, writeByteAt: function(idx, value) { _dv.setUint8(idx, value); }, SEGMENT: function(idx, size, value) { switch (arguments.length) { case 2: return data.slice(idx, idx + size); case 1: return data.slice(idx); case 3: if (value === null) { value = new ArrayBuffer(); } if (value instanceof ArrayBuffer) { var arr = new Uint8Array(this.length() - size + value.byteLength); if (idx > 0) { arr.set(new Uint8Array(data.slice(0, idx)), 0); } arr.set(new Uint8Array(value), idx); arr.set(new Uint8Array(data.slice(idx + size)), idx + value.byteLength); this.clear(); data = arr.buffer; _dv = new DataView(data); break; } default: return data; } }, length: function() { return data ? data.byteLength : 0; }, clear: function() { _dv = data = null; } }); } function UTF16StringReader(data) { Basic.extend(this, { readByteAt: function(idx) { return data.charCodeAt(idx); }, writeByteAt: function(idx, value) { putstr(String.fromCharCode(value), idx, 1); }, SEGMENT: function(idx, length, segment) { switch (arguments.length) { case 1: return data.substr(idx); case 2: return data.substr(idx, length); case 3: putstr(segment !== null ? segment : '', idx, length); break; default: return data; } }, length: function() { return data ? data.length : 0; }, clear: function() { data = null; } }); function putstr(segment, idx, length) { length = arguments.length === 3 ? length : data.length - idx - 1; data = data.substr(0, idx) + segment + data.substr(length + idx); } } return BinaryReader; }); // Included from: src/javascript/runtime/html5/image/JPEGHeaders.js /** * JPEGHeaders.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ /** @class moxie/runtime/html5/image/JPEGHeaders @private */ define("moxie/runtime/html5/image/JPEGHeaders", [ "moxie/runtime/html5/utils/BinaryReader", "moxie/core/Exceptions" ], function(BinaryReader, x) { return function JPEGHeaders(data) { var headers = [], _br, idx, marker, length = 0; _br = new BinaryReader(data); // Check if data is jpeg if (_br.SHORT(0) !== 0xFFD8) { _br.clear(); throw new x.ImageError(x.ImageError.WRONG_FORMAT); } idx = 2; while (idx <= _br.length()) { marker = _br.SHORT(idx); // omit RST (restart) markers if (marker >= 0xFFD0 && marker <= 0xFFD7) { idx += 2; continue; } // no headers allowed after SOS marker if (marker === 0xFFDA || marker === 0xFFD9) { break; } length = _br.SHORT(idx + 2) + 2; // APPn marker detected if (marker >= 0xFFE1 && marker <= 0xFFEF) { headers.push({ hex: marker, name: 'APP' + (marker & 0x000F), start: idx, length: length, segment: _br.SEGMENT(idx, length) }); } idx += length; } _br.clear(); return { headers: headers, restore: function(data) { var max, i, br; br = new BinaryReader(data); idx = br.SHORT(2) == 0xFFE0 ? 4 + br.SHORT(4) : 2; for (i = 0, max = headers.length; i < max; i++) { br.SEGMENT(idx, 0, headers[i].segment); idx += headers[i].length; } data = br.SEGMENT(); br.clear(); return data; }, strip: function(data) { var br, headers, jpegHeaders, i; jpegHeaders = new JPEGHeaders(data); headers = jpegHeaders.headers; jpegHeaders.purge(); br = new BinaryReader(data); i = headers.length; while (i--) { br.SEGMENT(headers[i].start, headers[i].length, ''); } data = br.SEGMENT(); br.clear(); return data; }, get: function(name) { var array = []; for (var i = 0, max = headers.length; i < max; i++) { if (headers[i].name === name.toUpperCase()) { array.push(headers[i].segment); } } return array; }, set: function(name, segment) { var array = [], i, ii, max; if (typeof(segment) === 'string') { array.push(segment); } else { array = segment; } for (i = ii = 0, max = headers.length; i < max; i++) { if (headers[i].name === name.toUpperCase()) { headers[i].segment = array[ii]; headers[i].length = array[ii].length; ii++; } if (ii >= array.length) { break; } } }, purge: function() { this.headers = headers = []; } }; }; }); // Included from: src/javascript/runtime/html5/image/ExifParser.js /** * ExifParser.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ /** @class moxie/runtime/html5/image/ExifParser @private */ define("moxie/runtime/html5/image/ExifParser", [ "moxie/core/utils/Basic", "moxie/runtime/html5/utils/BinaryReader", "moxie/core/Exceptions" ], function(Basic, BinaryReader, x) { function ExifParser(data) { var __super__, tags, tagDescs, offsets, idx, Tiff; BinaryReader.call(this, data); tags = { tiff: { /* The image orientation viewed in terms of rows and columns. 1 = The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side. 2 = The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side. 3 = The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side. 4 = The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side. 5 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual top. 6 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual top. 7 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom. 8 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom. */ 0x0112: 'Orientation', 0x010E: 'ImageDescription', 0x010F: 'Make', 0x0110: 'Model', 0x0131: 'Software', 0x8769: 'ExifIFDPointer', 0x8825: 'GPSInfoIFDPointer' }, exif: { 0x9000: 'ExifVersion', 0xA001: 'ColorSpace', 0xA002: 'PixelXDimension', 0xA003: 'PixelYDimension', 0x9003: 'DateTimeOriginal', 0x829A: 'ExposureTime', 0x829D: 'FNumber', 0x8827: 'ISOSpeedRatings', 0x9201: 'ShutterSpeedValue', 0x9202: 'ApertureValue' , 0x9207: 'MeteringMode', 0x9208: 'LightSource', 0x9209: 'Flash', 0x920A: 'FocalLength', 0xA402: 'ExposureMode', 0xA403: 'WhiteBalance', 0xA406: 'SceneCaptureType', 0xA404: 'DigitalZoomRatio', 0xA408: 'Contrast', 0xA409: 'Saturation', 0xA40A: 'Sharpness' }, gps: { 0x0000: 'GPSVersionID', 0x0001: 'GPSLatitudeRef', 0x0002: 'GPSLatitude', 0x0003: 'GPSLongitudeRef', 0x0004: 'GPSLongitude' }, thumb: { 0x0201: 'JPEGInterchangeFormat', 0x0202: 'JPEGInterchangeFormatLength' } }; tagDescs = { 'ColorSpace': { 1: 'sRGB', 0: 'Uncalibrated' }, 'MeteringMode': { 0: 'Unknown', 1: 'Average', 2: 'CenterWeightedAverage', 3: 'Spot', 4: 'MultiSpot', 5: 'Pattern', 6: 'Partial', 255: 'Other' }, 'LightSource': { 1: 'Daylight', 2: 'Fliorescent', 3: 'Tungsten', 4: 'Flash', 9: 'Fine weather', 10: 'Cloudy weather', 11: 'Shade', 12: 'Daylight fluorescent (D 5700 - 7100K)', 13: 'Day white fluorescent (N 4600 -5400K)', 14: 'Cool white fluorescent (W 3900 - 4500K)', 15: 'White fluorescent (WW 3200 - 3700K)', 17: 'Standard light A', 18: 'Standard light B', 19: 'Standard light C', 20: 'D55', 21: 'D65', 22: 'D75', 23: 'D50', 24: 'ISO studio tungsten', 255: 'Other' }, 'Flash': { 0x0000: 'Flash did not fire', 0x0001: 'Flash fired', 0x0005: 'Strobe return light not detected', 0x0007: 'Strobe return light detected', 0x0009: 'Flash fired, compulsory flash mode', 0x000D: 'Flash fired, compulsory flash mode, return light not detected', 0x000F: 'Flash fired, compulsory flash mode, return light detected', 0x0010: 'Flash did not fire, compulsory flash mode', 0x0018: 'Flash did not fire, auto mode', 0x0019: 'Flash fired, auto mode', 0x001D: 'Flash fired, auto mode, return light not detected', 0x001F: 'Flash fired, auto mode, return light detected', 0x0020: 'No flash function', 0x0041: 'Flash fired, red-eye reduction mode', 0x0045: 'Flash fired, red-eye reduction mode, return light not detected', 0x0047: 'Flash fired, red-eye reduction mode, return light detected', 0x0049: 'Flash fired, compulsory flash mode, red-eye reduction mode', 0x004D: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected', 0x004F: 'Flash fired, compulsory flash mode, red-eye reduction mode, return light detected', 0x0059: 'Flash fired, auto mode, red-eye reduction mode', 0x005D: 'Flash fired, auto mode, return light not detected, red-eye reduction mode', 0x005F: 'Flash fired, auto mode, return light detected, red-eye reduction mode' }, 'ExposureMode': { 0: 'Auto exposure', 1: 'Manual exposure', 2: 'Auto bracket' }, 'WhiteBalance': { 0: 'Auto white balance', 1: 'Manual white balance' }, 'SceneCaptureType': { 0: 'Standard', 1: 'Landscape', 2: 'Portrait', 3: 'Night scene' }, 'Contrast': { 0: 'Normal', 1: 'Soft', 2: 'Hard' }, 'Saturation': { 0: 'Normal', 1: 'Low saturation', 2: 'High saturation' }, 'Sharpness': { 0: 'Normal', 1: 'Soft', 2: 'Hard' }, // GPS related 'GPSLatitudeRef': { N: 'North latitude', S: 'South latitude' }, 'GPSLongitudeRef': { E: 'East longitude', W: 'West longitude' } }; offsets = { tiffHeader: 10 }; idx = offsets.tiffHeader; __super__ = { clear: this.clear }; // Public functions Basic.extend(this, { read: function() { try { return ExifParser.prototype.read.apply(this, arguments); } catch (ex) { throw new x.ImageError(x.ImageError.INVALID_META_ERR); } }, write: function() { try { return ExifParser.prototype.write.apply(this, arguments); } catch (ex) { throw new x.ImageError(x.ImageError.INVALID_META_ERR); } }, UNDEFINED: function() { return this.BYTE.apply(this, arguments); }, RATIONAL: function(idx) { return this.LONG(idx) / this.LONG(idx + 4) }, SRATIONAL: function(idx) { return this.SLONG(idx) / this.SLONG(idx + 4) }, ASCII: function(idx) { return this.CHAR(idx); }, TIFF: function() { return Tiff || null; }, EXIF: function() { var Exif = null; if (offsets.exifIFD) { try { Exif = extractTags.call(this, offsets.exifIFD, tags.exif); } catch(ex) { return null; } // Fix formatting of some tags if (Exif.ExifVersion && Basic.typeOf(Exif.ExifVersion) === 'array') { for (var i = 0, exifVersion = ''; i < Exif.ExifVersion.length; i++) { exifVersion += String.fromCharCode(Exif.ExifVersion[i]); } Exif.ExifVersion = exifVersion; } } return Exif; }, GPS: function() { var GPS = null; if (offsets.gpsIFD) { try { GPS = extractTags.call(this, offsets.gpsIFD, tags.gps); } catch (ex) { return null; } // iOS devices (and probably some others) do not put in GPSVersionID tag (why?..) if (GPS.GPSVersionID && Basic.typeOf(GPS.GPSVersionID) === 'array') { GPS.GPSVersionID = GPS.GPSVersionID.join('.'); } } return GPS; }, thumb: function() { if (offsets.IFD1) { try { var IFD1Tags = extractTags.call(this, offsets.IFD1, tags.thumb); if ('JPEGInterchangeFormat' in IFD1Tags) { return this.SEGMENT(offsets.tiffHeader + IFD1Tags.JPEGInterchangeFormat, IFD1Tags.JPEGInterchangeFormatLength); } } catch (ex) {} } return null; }, setExif: function(tag, value) { // Right now only setting of width/height is possible if (tag !== 'PixelXDimension' && tag !== 'PixelYDimension') { return false; } return setTag.call(this, 'exif', tag, value); }, clear: function() { __super__.clear(); data = tags = tagDescs = Tiff = offsets = __super__ = null; } }); // Check if that's APP1 and that it has EXIF if (this.SHORT(0) !== 0xFFE1 || this.STRING(4, 5).toUpperCase() !== "EXIF\0") { throw new x.ImageError(x.ImageError.INVALID_META_ERR); } // Set read order of multi-byte data this.littleEndian = (this.SHORT(idx) == 0x4949); // Check if always present bytes are indeed present if (this.SHORT(idx+=2) !== 0x002A) { throw new x.ImageError(x.ImageError.INVALID_META_ERR); } offsets.IFD0 = offsets.tiffHeader + this.LONG(idx += 2); Tiff = extractTags.call(this, offsets.IFD0, tags.tiff); if ('ExifIFDPointer' in Tiff) { offsets.exifIFD = offsets.tiffHeader + Tiff.ExifIFDPointer; delete Tiff.ExifIFDPointer; } if ('GPSInfoIFDPointer' in Tiff) { offsets.gpsIFD = offsets.tiffHeader + Tiff.GPSInfoIFDPointer; delete Tiff.GPSInfoIFDPointer; } if (Basic.isEmptyObj(Tiff)) { Tiff = null; } // check if we have a thumb as well var IFD1Offset = this.LONG(offsets.IFD0 + this.SHORT(offsets.IFD0) * 12 + 2); if (IFD1Offset) { offsets.IFD1 = offsets.tiffHeader + IFD1Offset; } function extractTags(IFD_offset, tags2extract) { var data = this; var length, i, tag, type, count, size, offset, value, values = [], hash = {}; var types = { 1 : 'BYTE', 7 : 'UNDEFINED', 2 : 'ASCII', 3 : 'SHORT', 4 : 'LONG', 5 : 'RATIONAL', 9 : 'SLONG', 10: 'SRATIONAL' }; var sizes = { 'BYTE' : 1, 'UNDEFINED' : 1, 'ASCII' : 1, 'SHORT' : 2, 'LONG' : 4, 'RATIONAL' : 8, 'SLONG' : 4, 'SRATIONAL' : 8 }; length = data.SHORT(IFD_offset); // The size of APP1 including all these elements shall not exceed the 64 Kbytes specified in the JPEG standard. for (i = 0; i < length; i++) { values = []; // Set binary reader pointer to beginning of the next tag offset = IFD_offset + 2 + i*12; tag = tags2extract[data.SHORT(offset)]; if (tag === undefined) { continue; // Not the tag we requested } type = types[data.SHORT(offset+=2)]; count = data.LONG(offset+=2); size = sizes[type]; if (!size) { throw new x.ImageError(x.ImageError.INVALID_META_ERR); } offset += 4; // tag can only fit 4 bytes of data, if data is larger we should look outside if (size * count > 4) { // instead of data tag contains an offset of the data offset = data.LONG(offset) + offsets.tiffHeader; } // in case we left the boundaries of data throw an early exception if (offset + size * count >= this.length()) { throw new x.ImageError(x.ImageError.INVALID_META_ERR); } // special care for the string if (type === 'ASCII') { hash[tag] = Basic.trim(data.STRING(offset, count).replace(/\0$/, '')); // strip trailing NULL continue; } else { values = data.asArray(type, offset, count); value = (count == 1 ? values[0] : values); if (tagDescs.hasOwnProperty(tag) && typeof value != 'object') { hash[tag] = tagDescs[tag][value]; } else { hash[tag] = value; } } } return hash; } // At the moment only setting of simple (LONG) values, that do not require offset recalculation, is supported function setTag(ifd, tag, value) { var offset, length, tagOffset, valueOffset = 0; // If tag name passed translate into hex key if (typeof(tag) === 'string') { var tmpTags = tags[ifd.toLowerCase()]; for (var hex in tmpTags) { if (tmpTags[hex] === tag) { tag = hex; break; } } } offset = offsets[ifd.toLowerCase() + 'IFD']; length = this.SHORT(offset); for (var i = 0; i < length; i++) { tagOffset = offset + 12 * i + 2; if (this.SHORT(tagOffset) == tag) { valueOffset = tagOffset + 8; break; } } if (!valueOffset) { return false; } try { this.write(valueOffset, value, 4); } catch(ex) { return false; } return true; } } ExifParser.prototype = BinaryReader.prototype; return ExifParser; }); // Included from: src/javascript/runtime/html5/image/JPEG.js /** * JPEG.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ /** @class moxie/runtime/html5/image/JPEG @private */ define("moxie/runtime/html5/image/JPEG", [ "moxie/core/utils/Basic", "moxie/core/Exceptions", "moxie/runtime/html5/image/JPEGHeaders", "moxie/runtime/html5/utils/BinaryReader", "moxie/runtime/html5/image/ExifParser" ], function(Basic, x, JPEGHeaders, BinaryReader, ExifParser) { function JPEG(data) { var _br, _hm, _ep, _info; _br = new BinaryReader(data); // check if it is jpeg if (_br.SHORT(0) !== 0xFFD8) { throw new x.ImageError(x.ImageError.WRONG_FORMAT); } // backup headers _hm = new JPEGHeaders(data); // extract exif info try { _ep = new ExifParser(_hm.get('app1')[0]); } catch(ex) {} // get dimensions _info = _getDimensions.call(this); Basic.extend(this, { type: 'image/jpeg', size: _br.length(), width: _info && _info.width || 0, height: _info && _info.height || 0, setExif: function(tag, value) { if (!_ep) { return false; // or throw an exception } if (Basic.typeOf(tag) === 'object') { Basic.each(tag, function(value, tag) { _ep.setExif(tag, value); }); } else { _ep.setExif(tag, value); } // update internal headers _hm.set('app1', _ep.SEGMENT()); }, writeHeaders: function() { if (!arguments.length) { // if no arguments passed, update headers internally return _hm.restore(data); } return _hm.restore(arguments[0]); }, stripHeaders: function(data) { return _hm.strip(data); }, purge: function() { _purge.call(this); } }); if (_ep) { this.meta = { tiff: _ep.TIFF(), exif: _ep.EXIF(), gps: _ep.GPS(), thumb: _getThumb() }; } function _getDimensions(br) { var idx = 0 , marker , length ; if (!br) { br = _br; } // examine all through the end, since some images might have very large APP segments while (idx <= br.length()) { marker = br.SHORT(idx += 2); if (marker >= 0xFFC0 && marker <= 0xFFC3) { // SOFn idx += 5; // marker (2 bytes) + length (2 bytes) + Sample precision (1 byte) return { height: br.SHORT(idx), width: br.SHORT(idx += 2) }; } length = br.SHORT(idx += 2); idx += length - 2; } return null; } function _getThumb() { var data = _ep.thumb() , br , info ; if (data) { br = new BinaryReader(data); info = _getDimensions(br); br.clear(); if (info) { info.data = data; return info; } } return null; } function _purge() { if (!_ep || !_hm || !_br) { return; // ignore any repeating purge requests } _ep.clear(); _hm.purge(); _br.clear(); _info = _hm = _ep = _br = null; } } return JPEG; }); // Included from: src/javascript/runtime/html5/image/PNG.js /** * PNG.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ /** @class moxie/runtime/html5/image/PNG @private */ define("moxie/runtime/html5/image/PNG", [ "moxie/core/Exceptions", "moxie/core/utils/Basic", "moxie/runtime/html5/utils/BinaryReader" ], function(x, Basic, BinaryReader) { function PNG(data) { var _br, _hm, _ep, _info; _br = new BinaryReader(data); // check if it's png (function() { var idx = 0, i = 0 , signature = [0x8950, 0x4E47, 0x0D0A, 0x1A0A] ; for (i = 0; i < signature.length; i++, idx += 2) { if (signature[i] != _br.SHORT(idx)) { throw new x.ImageError(x.ImageError.WRONG_FORMAT); } } }()); function _getDimensions() { var chunk, idx; chunk = _getChunkAt.call(this, 8); if (chunk.type == 'IHDR') { idx = chunk.start; return { width: _br.LONG(idx), height: _br.LONG(idx += 4) }; } return null; } function _purge() { if (!_br) { return; // ignore any repeating purge requests } _br.clear(); data = _info = _hm = _ep = _br = null; } _info = _getDimensions.call(this); Basic.extend(this, { type: 'image/png', size: _br.length(), width: _info.width, height: _info.height, purge: function() { _purge.call(this); } }); // for PNG we can safely trigger purge automatically, as we do not keep any data for later _purge.call(this); function _getChunkAt(idx) { var length, type, start, CRC; length = _br.LONG(idx); type = _br.STRING(idx += 4, 4); start = idx += 4; CRC = _br.LONG(idx + length); return { length: length, type: type, start: start, CRC: CRC }; } } return PNG; }); // Included from: src/javascript/runtime/html5/image/ImageInfo.js /** * ImageInfo.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ /** @class moxie/runtime/html5/image/ImageInfo @private */ define("moxie/runtime/html5/image/ImageInfo", [ "moxie/core/utils/Basic", "moxie/core/Exceptions", "moxie/runtime/html5/image/JPEG", "moxie/runtime/html5/image/PNG" ], function(Basic, x, JPEG, PNG) { /** Optional image investigation tool for HTML5 runtime. Provides the following features: - ability to distinguish image type (JPEG or PNG) by signature - ability to extract image width/height directly from it's internals, without preloading in memory (fast) - ability to extract APP headers from JPEGs (Exif, GPS, etc) - ability to replace width/height tags in extracted JPEG headers - ability to restore APP headers, that were for example stripped during image manipulation @class ImageInfo @constructor @param {String} data Image source as binary string */ return function(data) { var _cs = [JPEG, PNG], _img; // figure out the format, throw: ImageError.WRONG_FORMAT if not supported _img = (function() { for (var i = 0; i < _cs.length; i++) { try { return new _cs[i](data); } catch (ex) { // console.info(ex); } } throw new x.ImageError(x.ImageError.WRONG_FORMAT); }()); Basic.extend(this, { /** Image Mime Type extracted from it's depths @property type @type {String} @default '' */ type: '', /** Image size in bytes @property size @type {Number} @default 0 */ size: 0, /** Image width extracted from image source @property width @type {Number} @default 0 */ width: 0, /** Image height extracted from image source @property height @type {Number} @default 0 */ height: 0, /** Sets Exif tag. Currently applicable only for width and height tags. Obviously works only with JPEGs. @method setExif @param {String} tag Tag to set @param {Mixed} value Value to assign to the tag */ setExif: function() {}, /** Restores headers to the source. @method writeHeaders @param {String} data Image source as binary string @return {String} Updated binary string */ writeHeaders: function(data) { return data; }, /** Strip all headers from the source. @method stripHeaders @param {String} data Image source as binary string @return {String} Updated binary string */ stripHeaders: function(data) { return data; }, /** Dispose resources. @method purge */ purge: function() { data = null; } }); Basic.extend(this, _img); this.purge = function() { _img.purge(); _img = null; }; }; }); // Included from: src/javascript/runtime/html5/image/MegaPixel.js /** (The MIT License) Copyright (c) 2012 Shinichi Tomita ; Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /** * Mega pixel image rendering library for iOS6 Safari * * Fixes iOS6 Safari's image file rendering issue for large size image (over mega-pixel), * which causes unexpected subsampling when drawing it in canvas. * By using this library, you can safely render the image with proper stretching. * * Copyright (c) 2012 Shinichi Tomita * Released under the MIT license */ /** @class moxie/runtime/html5/image/MegaPixel @private */ define("moxie/runtime/html5/image/MegaPixel", [], function() { /** * Rendering image element (with resizing) into the canvas element */ function renderImageToCanvas(img, canvas, options) { var iw = img.naturalWidth, ih = img.naturalHeight; var width = options.width, height = options.height; var x = options.x || 0, y = options.y || 0; var ctx = canvas.getContext('2d'); if (detectSubsampling(img)) { iw /= 2; ih /= 2; } var d = 1024; // size of tiling canvas var tmpCanvas = document.createElement('canvas'); tmpCanvas.width = tmpCanvas.height = d; var tmpCtx = tmpCanvas.getContext('2d'); var vertSquashRatio = detectVerticalSquash(img, iw, ih); var sy = 0; while (sy < ih) { var sh = sy + d > ih ? ih - sy : d; var sx = 0; while (sx < iw) { var sw = sx + d > iw ? iw - sx : d; tmpCtx.clearRect(0, 0, d, d); tmpCtx.drawImage(img, -sx, -sy); var dx = (sx * width / iw + x) << 0; var dw = Math.ceil(sw * width / iw); var dy = (sy * height / ih / vertSquashRatio + y) << 0; var dh = Math.ceil(sh * height / ih / vertSquashRatio); ctx.drawImage(tmpCanvas, 0, 0, sw, sh, dx, dy, dw, dh); sx += d; } sy += d; } tmpCanvas = tmpCtx = null; } /** * Detect subsampling in loaded image. * In iOS, larger images than 2M pixels may be subsampled in rendering. */ function detectSubsampling(img) { var iw = img.naturalWidth, ih = img.naturalHeight; if (iw * ih > 1024 * 1024) { // subsampling may happen over megapixel image var canvas = document.createElement('canvas'); canvas.width = canvas.height = 1; var ctx = canvas.getContext('2d'); ctx.drawImage(img, -iw + 1, 0); // subsampled image becomes half smaller in rendering size. // check alpha channel value to confirm image is covering edge pixel or not. // if alpha value is 0 image is not covering, hence subsampled. return ctx.getImageData(0, 0, 1, 1).data[3] === 0; } else { return false; } } /** * Detecting vertical squash in loaded image. * Fixes a bug which squash image vertically while drawing into canvas for some images. */ function detectVerticalSquash(img, iw, ih) { var canvas = document.createElement('canvas'); canvas.width = 1; canvas.height = ih; var ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); var data = ctx.getImageData(0, 0, 1, ih).data; // search image edge pixel position in case it is squashed vertically. var sy = 0; var ey = ih; var py = ih; while (py > sy) { var alpha = data[(py - 1) * 4 + 3]; if (alpha === 0) { ey = py; } else { sy = py; } py = (ey + sy) >> 1; } canvas = null; var ratio = (py / ih); return (ratio === 0) ? 1 : ratio; } return { isSubsampled: detectSubsampling, renderTo: renderImageToCanvas }; }); // Included from: src/javascript/runtime/html5/image/Image.js /** * Image.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ /** @class moxie/runtime/html5/image/Image @private */ define("moxie/runtime/html5/image/Image", [ "moxie/runtime/html5/Runtime", "moxie/core/utils/Basic", "moxie/core/Exceptions", "moxie/core/utils/Encode", "moxie/file/Blob", "moxie/file/File", "moxie/runtime/html5/image/ImageInfo", "moxie/runtime/html5/image/MegaPixel", "moxie/core/utils/Mime", "moxie/core/utils/Env" ], function(extensions, Basic, x, Encode, Blob, File, ImageInfo, MegaPixel, Mime, Env) { function HTML5Image() { var me = this , _img, _imgInfo, _canvas, _binStr, _blob , _modified = false // is set true whenever image is modified , _preserveHeaders = true ; Basic.extend(this, { loadFromBlob: function(blob) { var comp = this, I = comp.getRuntime() , asBinary = arguments.length > 1 ? arguments[1] : true ; if (!I.can('access_binary')) { throw new x.RuntimeError(x.RuntimeError.NOT_SUPPORTED_ERR); } _blob = blob; if (blob.isDetached()) { _binStr = blob.getSource(); _preload.call(this, _binStr); return; } else { _readAsDataUrl.call(this, blob.getSource(), function(dataUrl) { if (asBinary) { _binStr = _toBinary(dataUrl); } _preload.call(comp, dataUrl); }); } }, loadFromImage: function(img, exact) { this.meta = img.meta; _blob = new File(null, { name: img.name, size: img.size, type: img.type }); _preload.call(this, exact ? (_binStr = img.getAsBinaryString()) : img.getAsDataURL()); }, getInfo: function() { var I = this.getRuntime(), info; if (!_imgInfo && _binStr && I.can('access_image_binary')) { _imgInfo = new ImageInfo(_binStr); } info = { width: _getImg().width || 0, height: _getImg().height || 0, type: _blob.type || Mime.getFileMime(_blob.name), size: _binStr && _binStr.length || _blob.size || 0, name: _blob.name || '', meta: _imgInfo && _imgInfo.meta || this.meta || {} }; // store thumbnail data as blob if (info.meta && info.meta.thumb && !(info.meta.thumb.data instanceof Blob)) { info.meta.thumb.data = new Blob(null, { type: 'image/jpeg', data: info.meta.thumb.data }); } return info; }, downsize: function() { _downsize.apply(this, arguments); }, getAsCanvas: function() { if (_canvas) { _canvas.id = this.uid + '_canvas'; } return _canvas; }, getAsBlob: function(type, quality) { if (type !== this.type) { // if different mime type requested prepare image for conversion _downsize.call(this, this.width, this.height, false); } return new File(null, { name: _blob.name || '', type: type, data: me.getAsBinaryString.call(this, type, quality) }); }, getAsDataURL: function(type) { var quality = arguments[1] || 90; // if image has not been modified, return the source right away if (!_modified) { return _img.src; } if ('image/jpeg' !== type) { return _canvas.toDataURL('image/png'); } else { try { // older Geckos used to result in an exception on quality argument return _canvas.toDataURL('image/jpeg', quality/100); } catch (ex) { return _canvas.toDataURL('image/jpeg'); } } }, getAsBinaryString: function(type, quality) { // if image has not been modified, return the source right away if (!_modified) { // if image was not loaded from binary string if (!_binStr) { _binStr = _toBinary(me.getAsDataURL(type, quality)); } return _binStr; } if ('image/jpeg' !== type) { _binStr = _toBinary(me.getAsDataURL(type, quality)); } else { var dataUrl; // if jpeg if (!quality) { quality = 90; } try { // older Geckos used to result in an exception on quality argument dataUrl = _canvas.toDataURL('image/jpeg', quality/100); } catch (ex) { dataUrl = _canvas.toDataURL('image/jpeg'); } _binStr = _toBinary(dataUrl); if (_imgInfo) { _binStr = _imgInfo.stripHeaders(_binStr); if (_preserveHeaders) { // update dimensions info in exif if (_imgInfo.meta && _imgInfo.meta.exif) { _imgInfo.setExif({ PixelXDimension: this.width, PixelYDimension: this.height }); } // re-inject the headers _binStr = _imgInfo.writeHeaders(_binStr); } // will be re-created from fresh on next getInfo call _imgInfo.purge(); _imgInfo = null; } } _modified = false; return _binStr; }, destroy: function() { me = null; _purge.call(this); this.getRuntime().getShim().removeInstance(this.uid); } }); function _getImg() { if (!_canvas && !_img) { throw new x.ImageError(x.DOMException.INVALID_STATE_ERR); } return _canvas || _img; } function _toBinary(str) { return Encode.atob(str.substring(str.indexOf('base64,') + 7)); } function _toDataUrl(str, type) { return 'data:' + (type || '') + ';base64,' + Encode.btoa(str); } function _preload(str) { var comp = this; _img = new Image(); _img.onerror = function() { _purge.call(this); comp.trigger('error', x.ImageError.WRONG_FORMAT); }; _img.onload = function() { comp.trigger('load'); }; _img.src = str.substr(0, 5) == 'data:' ? str : _toDataUrl(str, _blob.type); } function _readAsDataUrl(file, callback) { var comp = this, fr; // use FileReader if it's available if (window.FileReader) { fr = new FileReader(); fr.onload = function() { callback(this.result); }; fr.onerror = function() { comp.trigger('error', x.ImageError.WRONG_FORMAT); }; fr.readAsDataURL(file); } else { return callback(file.getAsDataURL()); } } function _downsize(width, height, crop, preserveHeaders) { var self = this , scale , mathFn , x = 0 , y = 0 , img , destWidth , destHeight , orientation ; _preserveHeaders = preserveHeaders; // we will need to check this on export (see getAsBinaryString()) // take into account orientation tag orientation = (this.meta && this.meta.tiff && this.meta.tiff.Orientation) || 1; if (Basic.inArray(orientation, [5,6,7,8]) !== -1) { // values that require 90 degree rotation // swap dimensions var tmp = width; width = height; height = tmp; } img = _getImg(); // unify dimensions if (!crop) { scale = Math.min(width/img.width, height/img.height); } else { // one of the dimensions may exceed the actual image dimensions - we need to take the smallest value width = Math.min(width, img.width); height = Math.min(height, img.height); scale = Math.max(width/img.width, height/img.height); } // we only downsize here if (scale > 1 && !crop && preserveHeaders) { this.trigger('Resize'); return; } // prepare canvas if necessary if (!_canvas) { _canvas = document.createElement("canvas"); } // calculate dimensions of proportionally resized image destWidth = Math.round(img.width * scale); destHeight = Math.round(img.height * scale); // scale image and canvas if (crop) { _canvas.width = width; _canvas.height = height; // if dimensions of the resulting image still larger than canvas, center it if (destWidth > width) { x = Math.round((destWidth - width) / 2); } if (destHeight > height) { y = Math.round((destHeight - height) / 2); } } else { _canvas.width = destWidth; _canvas.height = destHeight; } // rotate if required, according to orientation tag if (!_preserveHeaders) { _rotateToOrientaion(_canvas.width, _canvas.height, orientation); } _drawToCanvas.call(this, img, _canvas, -x, -y, destWidth, destHeight); this.width = _canvas.width; this.height = _canvas.height; _modified = true; self.trigger('Resize'); } function _drawToCanvas(img, canvas, x, y, w, h) { if (Env.OS === 'iOS') { // avoid squish bug in iOS6 MegaPixel.renderTo(img, canvas, { width: w, height: h, x: x, y: y }); } else { var ctx = canvas.getContext('2d'); ctx.drawImage(img, x, y, w, h); } } /** * Transform canvas coordination according to specified frame size and orientation * Orientation value is from EXIF tag * @author Shinichi Tomita */ function _rotateToOrientaion(width, height, orientation) { switch (orientation) { case 5: case 6: case 7: case 8: _canvas.width = height; _canvas.height = width; break; default: _canvas.width = width; _canvas.height = height; } /** 1 = The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side. 2 = The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side. 3 = The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side. 4 = The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side. 5 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual top. 6 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual top. 7 = The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom. 8 = The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom. */ var ctx = _canvas.getContext('2d'); switch (orientation) { case 2: // horizontal flip ctx.translate(width, 0); ctx.scale(-1, 1); break; case 3: // 180 rotate left ctx.translate(width, height); ctx.rotate(Math.PI); break; case 4: // vertical flip ctx.translate(0, height); ctx.scale(1, -1); break; case 5: // vertical flip + 90 rotate right ctx.rotate(0.5 * Math.PI); ctx.scale(1, -1); break; case 6: // 90 rotate right ctx.rotate(0.5 * Math.PI); ctx.translate(0, -height); break; case 7: // horizontal flip + 90 rotate right ctx.rotate(0.5 * Math.PI); ctx.translate(width, -height); ctx.scale(-1, 1); break; case 8: // 90 rotate left ctx.rotate(-0.5 * Math.PI); ctx.translate(-width, 0); break; } } function _purge() { if (_imgInfo) { _imgInfo.purge(); _imgInfo = null; } _binStr = _img = _canvas = _blob = null; _modified = false; } } return (extensions.Image = HTML5Image); }); /** * Stub for moxie/runtime/flash/Runtime * @private */ define("moxie/runtime/flash/Runtime", [ ], function() { return {}; }); /** * Stub for moxie/runtime/silverlight/Runtime * @private */ define("moxie/runtime/silverlight/Runtime", [ ], function() { return {}; }); // Included from: src/javascript/runtime/html4/Runtime.js /** * Runtime.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ /*global File:true */ /** Defines constructor for HTML4 runtime. @class moxie/runtime/html4/Runtime @private */ define("moxie/runtime/html4/Runtime", [ "moxie/core/utils/Basic", "moxie/core/Exceptions", "moxie/runtime/Runtime", "moxie/core/utils/Env" ], function(Basic, x, Runtime, Env) { var type = 'html4', extensions = {}; function Html4Runtime(options) { var I = this , Test = Runtime.capTest , True = Runtime.capTrue ; Runtime.call(this, options, type, { access_binary: Test(window.FileReader || window.File && File.getAsDataURL), access_image_binary: false, display_media: Test(extensions.Image && (Env.can('create_canvas') || Env.can('use_data_uri_over32kb'))), do_cors: false, drag_and_drop: false, filter_by_extension: Test(function() { // if you know how to feature-detect this, please suggest return (Env.browser === 'Chrome' && Env.verComp(Env.version, 28, '>=')) || (Env.browser === 'IE' && Env.verComp(Env.version, 10, '>=')) || (Env.browser === 'Safari' && Env.verComp(Env.version, 7, '>=')); }()), resize_image: function() { return extensions.Image && I.can('access_binary') && Env.can('create_canvas'); }, report_upload_progress: false, return_response_headers: false, return_response_type: function(responseType) { if (responseType === 'json' && !!window.JSON) { return true; } return !!~Basic.inArray(responseType, ['text', 'document', '']); }, return_status_code: function(code) { return !Basic.arrayDiff(code, [200, 404]); }, select_file: function() { return Env.can('use_fileinput'); }, select_multiple: false, send_binary_string: false, send_custom_headers: false, send_multipart: true, slice_blob: false, stream_upload: function() { return I.can('select_file'); }, summon_file_dialog: function() { // yeah... some dirty sniffing here... return I.can('select_file') && ( (Env.browser === 'Firefox' && Env.verComp(Env.version, 4, '>=')) || (Env.browser === 'Opera' && Env.verComp(Env.version, 12, '>=')) || (Env.browser === 'IE' && Env.verComp(Env.version, 10, '>=')) || !!~Basic.inArray(Env.browser, ['Chrome', 'Safari']) ); }, upload_filesize: True, use_http_method: function(methods) { return !Basic.arrayDiff(methods, ['GET', 'POST']); } }); Basic.extend(this, { init : function() { this.trigger("Init"); }, destroy: (function(destroy) { // extend default destroy method return function() { destroy.call(I); destroy = I = null; }; }(this.destroy)) }); Basic.extend(this.getShim(), extensions); } Runtime.addConstructor(type, Html4Runtime); return extensions; }); // Included from: src/javascript/runtime/html4/file/FileInput.js /** * FileInput.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ /** @class moxie/runtime/html4/file/FileInput @private */ define("moxie/runtime/html4/file/FileInput", [ "moxie/runtime/html4/Runtime", "moxie/file/File", "moxie/core/utils/Basic", "moxie/core/utils/Dom", "moxie/core/utils/Events", "moxie/core/utils/Mime", "moxie/core/utils/Env" ], function(extensions, File, Basic, Dom, Events, Mime, Env) { function FileInput() { var _uid, _mimes = [], _options; function addInput() { var comp = this, I = comp.getRuntime(), shimContainer, browseButton, currForm, form, input, uid; uid = Basic.guid('uid_'); shimContainer = I.getShimContainer(); // we get new ref everytime to avoid memory leaks in IE if (_uid) { // move previous form out of the view currForm = Dom.get(_uid + '_form'); if (currForm) { Basic.extend(currForm.style, { top: '100%' }); } } // build form in DOM, since innerHTML version not able to submit file for some reason form = document.createElement('form'); form.setAttribute('id', uid + '_form'); form.setAttribute('method', 'post'); form.setAttribute('enctype', 'multipart/form-data'); form.setAttribute('encoding', 'multipart/form-data'); Basic.extend(form.style, { overflow: 'hidden', position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }); input = document.createElement('input'); input.setAttribute('id', uid); input.setAttribute('type', 'file'); input.setAttribute('name', _options.name || 'Filedata'); input.setAttribute('accept', _mimes.join(',')); Basic.extend(input.style, { fontSize: '999px', opacity: 0 }); form.appendChild(input); shimContainer.appendChild(form); // prepare file input to be placed underneath the browse_button element Basic.extend(input.style, { position: 'absolute', top: 0, left: 0, width: '100%', height: '100%' }); if (Env.browser === 'IE' && Env.verComp(Env.version, 10, '<')) { Basic.extend(input.style, { filter : "progid:DXImageTransform.Microsoft.Alpha(opacity=0)" }); } input.onchange = function() { // there should be only one handler for this var file; if (!this.value) { return; } if (this.files) { // check if browser is fresh enough file = this.files[0]; // ignore empty files (IE10 for example hangs if you try to send them via XHR) if (file.size === 0) { form.parentNode.removeChild(form); return; } } else { file = { name: this.value }; } file = new File(I.uid, file); // clear event handler this.onchange = function() {}; addInput.call(comp); comp.files = [file]; // substitute all ids with file uids (consider file.uid read-only - we cannot do it the other way around) input.setAttribute('id', file.uid); form.setAttribute('id', file.uid + '_form'); comp.trigger('change'); input = form = null; }; // route click event to the input if (I.can('summon_file_dialog')) { browseButton = Dom.get(_options.browse_button); Events.removeEvent(browseButton, 'click', comp.uid); Events.addEvent(browseButton, 'click', function(e) { if (input && !input.disabled) { // for some reason FF (up to 8.0.1 so far) lets to click disabled input[type=file] input.click(); } e.preventDefault(); }, comp.uid); } _uid = uid; shimContainer = currForm = browseButton = null; } Basic.extend(this, { init: function(options) { var comp = this, I = comp.getRuntime(), shimContainer; // figure out accept string _options = options; _mimes = options.accept.mimes || Mime.extList2mimes(options.accept, I.can('filter_by_extension')); shimContainer = I.getShimContainer(); (function() { var browseButton, zIndex, top; browseButton = Dom.get(options.browse_button); // Route click event to the input[type=file] element for browsers that support such behavior if (I.can('summon_file_dialog')) { if (Dom.getStyle(browseButton, 'position') === 'static') { browseButton.style.position = 'relative'; } zIndex = parseInt(Dom.getStyle(browseButton, 'z-index'), 10) || 1; browseButton.style.zIndex = zIndex; shimContainer.style.zIndex = zIndex - 1; } /* Since we have to place input[type=file] on top of the browse_button for some browsers, browse_button loses interactivity, so we restore it here */ top = I.can('summon_file_dialog') ? browseButton : shimContainer; Events.addEvent(top, 'mouseover', function() { comp.trigger('mouseenter'); }, comp.uid); Events.addEvent(top, 'mouseout', function() { comp.trigger('mouseleave'); }, comp.uid); Events.addEvent(top, 'mousedown', function() { comp.trigger('mousedown'); }, comp.uid); Events.addEvent(Dom.get(options.container), 'mouseup', function() { comp.trigger('mouseup'); }, comp.uid); browseButton = null; }()); addInput.call(this); shimContainer = null; // trigger ready event asynchronously comp.trigger({ type: 'ready', async: true }); }, disable: function(state) { var input; if ((input = Dom.get(_uid))) { input.disabled = !!state; } }, destroy: function() { var I = this.getRuntime() , shim = I.getShim() , shimContainer = I.getShimContainer() ; Events.removeAllEvents(shimContainer, this.uid); Events.removeAllEvents(_options && Dom.get(_options.container), this.uid); Events.removeAllEvents(_options && Dom.get(_options.browse_button), this.uid); if (shimContainer) { shimContainer.innerHTML = ''; } shim.removeInstance(this.uid); _uid = _mimes = _options = shimContainer = shim = null; } }); } return (extensions.FileInput = FileInput); }); // Included from: src/javascript/runtime/html4/file/FileReader.js /** * FileReader.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ /** @class moxie/runtime/html4/file/FileReader @private */ define("moxie/runtime/html4/file/FileReader", [ "moxie/runtime/html4/Runtime", "moxie/runtime/html5/file/FileReader" ], function(extensions, FileReader) { return (extensions.FileReader = FileReader); }); // Included from: src/javascript/runtime/html4/xhr/XMLHttpRequest.js /** * XMLHttpRequest.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ /** @class moxie/runtime/html4/xhr/XMLHttpRequest @private */ define("moxie/runtime/html4/xhr/XMLHttpRequest", [ "moxie/runtime/html4/Runtime", "moxie/core/utils/Basic", "moxie/core/utils/Dom", "moxie/core/utils/Url", "moxie/core/Exceptions", "moxie/core/utils/Events", "moxie/file/Blob", "moxie/xhr/FormData" ], function(extensions, Basic, Dom, Url, x, Events, Blob, FormData) { function XMLHttpRequest() { var _status, _response, _iframe; function cleanup(cb) { var target = this, uid, form, inputs, i, hasFile = false; if (!_iframe) { return; } uid = _iframe.id.replace(/_iframe$/, ''); form = Dom.get(uid + '_form'); if (form) { inputs = form.getElementsByTagName('input'); i = inputs.length; while (i--) { switch (inputs[i].getAttribute('type')) { case 'hidden': inputs[i].parentNode.removeChild(inputs[i]); break; case 'file': hasFile = true; // flag the case for later break; } } inputs = []; if (!hasFile) { // we need to keep the form for sake of possible retries form.parentNode.removeChild(form); } form = null; } // without timeout, request is marked as canceled (in console) setTimeout(function() { Events.removeEvent(_iframe, 'load', target.uid); if (_iframe.parentNode) { // #382 _iframe.parentNode.removeChild(_iframe); } // check if shim container has any other children, if - not, remove it as well var shimContainer = target.getRuntime().getShimContainer(); if (!shimContainer.children.length) { shimContainer.parentNode.removeChild(shimContainer); } shimContainer = _iframe = null; cb(); }, 1); } Basic.extend(this, { send: function(meta, data) { var target = this, I = target.getRuntime(), uid, form, input, blob; _status = _response = null; function createIframe() { var container = I.getShimContainer() || document.body , temp = document.createElement('div') ; // IE 6 won't be able to set the name using setAttribute or iframe.name temp.innerHTML = ''; _iframe = temp.firstChild; container.appendChild(_iframe); /* _iframe.onreadystatechange = function() { console.info(_iframe.readyState); };*/ Events.addEvent(_iframe, 'load', function() { // _iframe.onload doesn't work in IE lte 8 var el; try { el = _iframe.contentWindow.document || _iframe.contentDocument || window.frames[_iframe.id].document; // try to detect some standard error pages if (/^4(0[0-9]|1[0-7]|2[2346])\s/.test(el.title)) { // test if title starts with 4xx HTTP error _status = el.title.replace(/^(\d+).*$/, '$1'); } else { _status = 200; // get result _response = Basic.trim(el.body.innerHTML); // we need to fire these at least once target.trigger({ type: 'progress', loaded: _response.length, total: _response.length }); if (blob) { // if we were uploading a file target.trigger({ type: 'uploadprogress', loaded: blob.size || 1025, total: blob.size || 1025 }); } } } catch (ex) { if (Url.hasSameOrigin(meta.url)) { // if response is sent with error code, iframe in IE gets redirected to res://ieframe.dll/http_x.htm // which obviously results to cross domain error (wtf?) _status = 404; } else { cleanup.call(target, function() { target.trigger('error'); }); return; } } cleanup.call(target, function() { target.trigger('load'); }); }, target.uid); } // end createIframe // prepare data to be sent and convert if required if (data instanceof FormData && data.hasBlob()) { blob = data.getBlob(); uid = blob.uid; input = Dom.get(uid); form = Dom.get(uid + '_form'); if (!form) { throw new x.DOMException(x.DOMException.NOT_FOUND_ERR); } } else { uid = Basic.guid('uid_'); form = document.createElement('form'); form.setAttribute('id', uid + '_form'); form.setAttribute('method', meta.method); form.setAttribute('enctype', 'multipart/form-data'); form.setAttribute('encoding', 'multipart/form-data'); I.getShimContainer().appendChild(form); } // set upload target form.setAttribute('target', uid + '_iframe'); if (data instanceof FormData) { data.each(function(value, name) { if (value instanceof Blob) { if (input) { input.setAttribute('name', name); } } else { var hidden = document.createElement('input'); Basic.extend(hidden, { type : 'hidden', name : name, value : value }); // make sure that input[type="file"], if it's there, comes last if (input) { form.insertBefore(hidden, input); } else { form.appendChild(hidden); } } }); } // set destination url form.setAttribute("action", meta.url); createIframe(); form.submit(); target.trigger('loadstart'); }, getStatus: function() { return _status; }, getResponse: function(responseType) { if ('json' === responseType) { // strip off
    ..
    tags that might be enclosing the response if (Basic.typeOf(_response) === 'string' && !!window.JSON) { try { return JSON.parse(_response.replace(/^\s*]*>/, '').replace(/<\/pre>\s*$/, '')); } catch (ex) { return null; } } } else if ('document' === responseType) { } return _response; }, abort: function() { var target = this; if (_iframe && _iframe.contentWindow) { if (_iframe.contentWindow.stop) { // FireFox/Safari/Chrome _iframe.contentWindow.stop(); } else if (_iframe.contentWindow.document.execCommand) { // IE _iframe.contentWindow.document.execCommand('Stop'); } else { _iframe.src = "about:blank"; } } cleanup.call(this, function() { // target.dispatchEvent('readystatechange'); target.dispatchEvent('abort'); }); } }); } return (extensions.XMLHttpRequest = XMLHttpRequest); }); // Included from: src/javascript/runtime/html4/image/Image.js /** * Image.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ /** @class moxie/runtime/html4/image/Image @private */ define("moxie/runtime/html4/image/Image", [ "moxie/runtime/html4/Runtime", "moxie/runtime/html5/image/Image" ], function(extensions, Image) { return (extensions.Image = Image); }); expose(["moxie/core/utils/Basic","moxie/core/utils/Env","moxie/core/I18n","moxie/core/utils/Mime","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/file/FileInput","moxie/core/utils/Encode","moxie/file/Blob","moxie/file/File","moxie/file/FileDrop","moxie/file/FileReader","moxie/core/utils/Url","moxie/runtime/RuntimeTarget","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/xhr/XMLHttpRequest","moxie/runtime/Transporter","moxie/image/Image","moxie/core/utils/Events"]); })(this); /** * o.js * * Copyright 2013, Moxiecode Systems AB * Released under GPL License. * * License: http://www.plupload.com/license * Contributing: http://www.plupload.com/contributing */ /*global moxie:true */ /** Globally exposed namespace with the most frequently used public classes and handy methods. @class o @static @private */ (function(exports) { "use strict"; var o = {}, inArray = exports.moxie.core.utils.Basic.inArray; // directly add some public classes // (we do it dynamically here, since for custom builds we cannot know beforehand what modules were included) (function addAlias(ns) { var name, itemType; for (name in ns) { itemType = typeof(ns[name]); if (itemType === 'object' && !~inArray(name, ['Exceptions', 'Env', 'Mime'])) { addAlias(ns[name]); } else if (itemType === 'function') { o[name] = ns[name]; } } })(exports.moxie); // add some manually o.Env = exports.moxie.core.utils.Env; o.Mime = exports.moxie.core.utils.Mime; o.Exceptions = exports.moxie.core.Exceptions; // expose globally exports.mOxie = o; if (!exports.o) { exports.o = o; } return o; })(this); plupload/plupload.min.js000064400000036365147573120640011352 0ustar00!function(e,I,S){var T=e.setTimeout,D={};function w(e){var t=e.required_features,r={};function i(e,t,i){var n={chunks:"slice_blob",jpgresize:"send_binary_string",pngresize:"send_binary_string",progress:"report_upload_progress",multi_selection:"select_multiple",dragdrop:"drag_and_drop",drop_element:"drag_and_drop",headers:"send_custom_headers",urlstream_upload:"send_binary_string",canSendBinary:"send_binary",triggerDialog:"summon_file_dialog"};n[e]?r[n[e]]=t:i||(r[e]=t)}return"string"==typeof t?F.each(t.split(/\s*,\s*/),function(e){i(e,!0)}):"object"==typeof t?F.each(t,function(e,t){i(t,e)}):!0===t&&(0":"gt","&":"amp",'"':"quot","'":"#39"};return e&&(""+e).replace(/[<>&\"\']/g,function(e){return t[e]?"&"+t[e]+";":e})},toArray:I.toArray,inArray:I.inArray,addI18n:I.addI18n,translate:I.translate,isEmptyObj:I.isEmptyObj,hasClass:I.hasClass,addClass:I.addClass,removeClass:I.removeClass,getStyle:I.getStyle,addEvent:I.addEvent,removeEvent:I.removeEvent,removeAllEvents:I.removeAllEvents,cleanName:function(e){for(var t=[/[\300-\306]/g,"A",/[\340-\346]/g,"a",/\307/g,"C",/\347/g,"c",/[\310-\313]/g,"E",/[\350-\353]/g,"e",/[\314-\317]/g,"I",/[\354-\357]/g,"i",/\321/g,"N",/\361/g,"n",/[\322-\330]/g,"O",/[\362-\370]/g,"o",/[\331-\334]/g,"U",/[\371-\374]/g,"u"],i=0;i(t/=1024)?i(e/t,1)+" "+F.translate("gb"):e>(t/=1024)?i(e/t,1)+" "+F.translate("mb"):1024e?(this.trigger("Error",{code:F.FILE_SIZE_ERROR,message:F.translate("File size error."),file:t}),i(!1)):i(!0)}),F.addFileFilter("prevent_duplicates",function(e,t,i){if(e)for(var n=this.files.length;n--;)if(t.name===this.files[n].name&&t.size===this.files[n].size)return this.trigger("Error",{code:F.FILE_DUPLICATE_ERROR,message:F.translate("Duplicate file error."),file:t}),void i(!1);i(!0)}),F.Uploader=function(e){var u,i,n,p,t=F.guid(),l=[],h={},o=[],d=[],c=!1;function r(){var e,t,i=0;if(this.state==F.STARTED){for(t=0;tu?(t=Math.min(u,a.size-c),a.slice(c,c+t)):(t=a.size,a),u&&d.chunks&&(r.settings.send_chunk_number?(n.chunk=Math.ceil(c/u),n.chunks=Math.ceil(a.size/u)):(n.offset=c,n.total=a.size)),(p=new I.XMLHttpRequest).upload&&(p.upload.onprogress=function(e){s.loaded=Math.min(s.size,c+e.loaded),r.trigger("UploadProgress",s)}),p.onload=function(){400<=p.status?f():(l=r.settings.max_retries,t=a.size?(s.size!=s.origSize&&(a.destroy(),a=null),r.trigger("UploadProgress",s),s.status=F.DONE,r.trigger("FileUploaded",s,{response:p.responseText,status:p.status,responseHeaders:p.getAllResponseHeaders()})):T(g,1))},p.onerror=function(){f()},p.onloadend=function(){this.destroy(),p=null},r.settings.multipart&&d.multipart?(p.open("post",o,!0),F.each(r.settings.headers,function(e,t){p.setRequestHeader(t,e)}),i=new I.FormData,F.each(F.extend(n,r.settings.multipart_params),function(e,t){i.append(t,e)}),i.append(r.settings.file_data_name,e),p.send(i,{runtime_order:r.settings.runtimes,required_caps:r.settings.required_features,preferred_caps:h})):(o=F.buildUrl(r.settings.url,F.extend(n,r.settings.multipart_params)),p.open("post",o,!0),p.setRequestHeader("Content-Type","application/octet-stream"),F.each(r.settings.headers,function(e,t){p.setRequestHeader(t,e)}),p.send(e,{runtime_order:r.settings.runtimes,required_caps:r.settings.required_features,preferred_caps:h})))}s.loaded&&(c=s.loaded=u?u*Math.floor(s.loaded/u):0),a=s.getSource(),r.settings.resize.enabled&&function(e,t){if(e.ruid){e=I.Runtime.getInfo(e.ruid);if(e)return e.can(t)}}(a,"send_binary_string")&&~I.inArray(a.type,["image/jpeg","image/png"])?function(t,e,i){var n=new I.Image;try{n.onload=function(){if(e.width>this.width&&e.height>this.height&&e.quality===S&&e.preserve_headers&&!e.crop)return this.destroy(),i(t);n.downsize(e.width,e.height,e.crop,e.preserve_headers)},n.onresize=function(){i(this.getAsBlob(t.type,e.quality)),this.destroy()},n.onerror=function(){i(t)},n.load(t)}catch(e){i(t)}}.call(this,a,r.settings.resize,function(e){a=e,s.size=e.size,g()}):g()}function R(e,t){s(t)}function E(e){if(e.state==F.STARTED)i=+new Date;else if(e.state==F.STOPPED)for(var t=e.files.length-1;0<=t;t--)e.files[t].status==F.UPLOADING&&(e.files[t].status=F.QUEUED,a())}function y(){p&&p.abort()}function v(e){a(),T(function(){r.call(e)},1)}function z(e,t){t.code===F.INIT_ERROR?e.destroy():t.code===F.HTTP_ERROR&&(t.file.status=F.FAILED,s(t.file),e.state==F.STARTED)&&(e.trigger("CancelUpload"),T(function(){r.call(e)},1))}function O(e){e.stop(),F.each(l,function(e){e.destroy()}),l=[],o.length&&(F.each(o,function(e){e.destroy()}),o=[]),d.length&&(F.each(d,function(e){e.destroy()}),d=[]),c=!(h={}),i=p=null,n.reset()}u={runtimes:I.Runtime.order,max_retries:0,chunk_size:0,multipart:!0,multi_selection:!0,file_data_name:"file",filters:{mime_types:[],prevent_duplicates:!1,max_file_size:0},resize:{enabled:!1,preserve_headers:!0,crop:!1},send_file_name:!0,send_chunk_number:!0},_.call(this,e,null,!0),n=new F.QueueProgress,F.extend(this,{id:t,uid:t,state:F.STOPPED,features:{},runtime:null,files:l,settings:u,total:n,init:function(){var t,i=this,e=i.getOption("preinit");return"function"==typeof e?e(i):F.each(e,function(e,t){i.bind(t,e)}),function(){this.bind("FilesAdded FilesRemoved",function(e){e.trigger("QueueChanged"),e.refresh()}),this.bind("CancelUpload",y),this.bind("BeforeUpload",m),this.bind("UploadFile",b),this.bind("UploadProgress",R),this.bind("StateChanged",E),this.bind("QueueChanged",a),this.bind("Error",z),this.bind("FileUploaded",v),this.bind("Destroy",O)}.call(i),F.each(["container","browse_button","drop_element"],function(e){if(null===i.getOption(e))return!(t={code:F.INIT_ERROR,message:F.translate("'%' specified, but cannot be found.")})}),t?i.trigger("Error",t):u.browse_button||u.drop_element?void g.call(i,u,function(e){var t=i.getOption("init");"function"==typeof t?t(i):F.each(t,function(e,t){i.bind(t,e)}),e?(i.runtime=I.Runtime.getInfo(f()).type,i.trigger("Init",{runtime:i.runtime}),i.trigger("PostInit")):i.trigger("Error",{code:F.INIT_ERROR,message:F.translate("Init error.")})}):i.trigger("Error",{code:F.INIT_ERROR,message:F.translate("You must specify either 'browse_button' or 'drop_element'.")})},setOption:function(e,t){_.call(this,e,t,!this.runtime)},getOption:function(e){return e?u[e]:u},refresh:function(){o.length&&F.each(o,function(e){e.trigger("Refresh")}),this.trigger("Refresh")},start:function(){this.state!=F.STARTED&&(this.state=F.STARTED,this.trigger("StateChanged"),r.call(this))},stop:function(){this.state!=F.STOPPED&&(this.state=F.STOPPED,this.trigger("StateChanged"),this.trigger("CancelUpload"))},disableBrowse:function(){c=arguments[0]===S||arguments[0],o.length&&F.each(o,function(e){e.disable(c)}),this.trigger("DisableBrowse",c)},getFile:function(e){for(var t=l.length-1;0<=t;t--)if(l[t].id===e)return l[t]},addFile:function(e,n){var r,s=this,a=[],o=[];r=f(),function e(i){var t=I.typeOf(i);if(i instanceof I.File){if(!i.ruid&&!i.isDetached()){if(!r)return!1;i.ruid=r,i.connectRuntime(r)}e(new F.File(i))}else i instanceof I.Blob?(e(i.getSource()),i.destroy()):i instanceof F.File?(n&&(i.name=n),a.push(function(t){var n,e,r;n=i,e=function(e){e||(l.push(i),o.push(i),s.trigger("FileFiltered",i)),T(t,1)},r=[],I.each(s.settings.filters,function(e,i){D[i]&&r.push(function(t){D[i].call(s,e,n,function(e){t(!e)})})}),I.inSeries(r,e)})):-1!==I.inArray(t,["file","blob"])?e(new I.File(null,i)):"node"===t&&"filelist"===I.typeOf(i.files)?I.each(i.files,e):"array"===t&&(n=null,I.each(i,e))}(e),a.length&&I.inSeries(a,function(){o.length&&s.trigger("FilesAdded",o)})},removeFile:function(e){for(var t="string"==typeof e?e:e.id,i=l.length-1;0<=i;i--)if(l[i].id===t)return this.splice(i,1)[0]},splice:function(e,t){var e=l.splice(e===S?0:e,t===S?l.length:t),i=!1;return this.state==F.STARTED&&(F.each(e,function(e){if(e.status===F.UPLOADING)return!(i=!0)}),i)&&this.stop(),this.trigger("FilesRemoved",e),F.each(e,function(e){e.destroy()}),i&&this.start(),e},dispatchEvent:function(e){var t,i;if(e=e.toLowerCase(),t=this.hasEventListener(e)){t.sort(function(e,t){return t.priority-e.priority}),(i=[].slice.call(arguments)).shift(),i.unshift(this);for(var n=0;n').css({position:"fixed",top:"-1000px",left:"-1000px",height:0,width:0}).attr("id","wp-uploader-browser-"+this.uploader.id).appendTo("body")).append(this.browser))}this.uploader.refresh()}}),u.queue=new wp.media.model.Attachments([],{query:!1}),u.errors=new Backbone.Collection,e.Uploader=u)}(wp,jQuery);plupload/handlers.min.js000064400000027236147573120640011327 0ustar00var uploader,uploader_init,topWin=window.dialogArguments||opener||parent||top;function fileQueued(e){jQuery(".media-blank").remove();var a=jQuery("#media-items").children(),r=post_id||0;1==a.length&&a.removeClass("open").find(".slidetoggle").slideUp(200),jQuery('
    ').attr("id","media-item-"+e.id).addClass("child-of-"+r).append(jQuery('
    ').text(" "+e.name),'
    0%
    ').appendTo(jQuery("#media-items")),jQuery("#insert-gallery").prop("disabled",!0)}function uploadStart(){try{void 0!==topWin.tb_remove&&topWin.jQuery("#TB_overlay").unbind("click",topWin.tb_remove)}catch(e){}return!0}function uploadProgress(e,a){var r=jQuery("#media-item-"+a.id);jQuery(".bar",r).width(200*a.loaded/a.size),jQuery(".percent",r).html(a.percent+"%")}function fileUploading(e,a){var r=104857600;rr&&setTimeout(function(){a.status<3&&0===a.loaded&&(wpFileError(a,pluploadL10n.big_upload_failed.replace("%1$s",'').replace("%2$s","")),e.stop(),e.removeFile(a),e.start())},1e4)}function updateMediaForm(){var e=jQuery("#media-items").children();1==e.length?(e.addClass("open").find(".slidetoggle").show(),jQuery(".insert-gallery").hide()):1(\d+)<\/pre>$/,"$1"),/media-upload-error|error-div/.test(a))?r.html(a):(r.find(".percent").html(pluploadL10n.crunching),prepareMediaItem(e,a),updateMediaForm(),post_id&&r.hasClass("child-of-"+post_id)&&jQuery("#attachments-count").text(+jQuery("#attachments-count").text()+1))}function setResize(e){e?window.resize_width&&window.resize_height?uploader.settings.resize={enabled:!0,width:window.resize_width,height:window.resize_height,quality:100}:uploader.settings.multipart_params.image_resize=!0:delete uploader.settings.multipart_params.image_resize}function prepareMediaItem(e,a){var r="undefined"==typeof shortform?1:2,i=jQuery("#media-item-"+e.id);2==r&&2

    '+e+"

    ")}function wpFileError(e,a){itemAjaxError(e.id,a)}function itemAjaxError(e,a){var r=jQuery("#media-item-"+e),i=r.find(".filename").text();r.data("last-err")!=e&&r.html('
    '+pluploadL10n.dismiss+""+pluploadL10n.error_uploading.replace("%s",jQuery.trim(i))+" "+a+"
    ").data("last-err",e)}function deleteSuccess(e){var a;return"-1"==e?itemAjaxError(this.id,"You do not have permission. Has your session expired?"):"0"==e?itemAjaxError(this.id,"Could not be deleted. Has it been deleted already?"):(e=this.id,a=jQuery("#media-item-"+e),(e=jQuery("#type-of-"+e).val())&&jQuery("#"+e+"-counter").text(jQuery("#"+e+"-counter").text()-1),post_id&&a.hasClass("child-of-"+post_id)&&jQuery("#attachments-count").text(jQuery("#attachments-count").text()-1),1==jQuery("form.type-form #media-items").children().length&&0 '+pluploadL10n.deleted+" ").siblings("a.toggle").hide(),jQuery(".filename",a).append(jQuery("a.undo",a).removeClass("hidden")),void jQuery(".menu_order_input",a).hide())}function deleteError(){}function uploadComplete(){jQuery("#insert-gallery").prop("disabled",!1)}function switchUploader(e){e?(deleteUserSetting("uploader"),jQuery(".media-upload-form").removeClass("html-uploader"),"object"==typeof uploader&&uploader.refresh()):(setUserSetting("uploader","1"),jQuery(".media-upload-form").addClass("html-uploader"))}function uploadError(e,a,r,i){var t=104857600;switch(a){case plupload.FAILED:wpFileError(e,pluploadL10n.upload_failed);break;case plupload.FILE_EXTENSION_ERROR:wpFileExtensionError(i,e,pluploadL10n.invalid_filetype);break;case plupload.FILE_SIZE_ERROR:uploadSizeError(i,e);break;case plupload.IMAGE_FORMAT_ERROR:wpFileError(e,pluploadL10n.not_an_image);break;case plupload.IMAGE_MEMORY_ERROR:wpFileError(e,pluploadL10n.image_memory_exceeded);break;case plupload.IMAGE_DIMENSIONS_ERROR:wpFileError(e,pluploadL10n.image_dimensions_exceeded);break;case plupload.GENERIC_ERROR:wpQueueError(pluploadL10n.upload_failed);break;case plupload.IO_ERROR:tt?wpFileError(e,pluploadL10n.big_upload_failed.replace("%1$s",'').replace("%2$s","")):wpQueueError(pluploadL10n.io_error);break;case plupload.HTTP_ERROR:wpQueueError(pluploadL10n.http_error);break;case plupload.INIT_ERROR:jQuery(".media-upload-form").addClass("html-uploader");break;case plupload.SECURITY_ERROR:wpQueueError(pluploadL10n.security_error);break;default:wpFileError(e,pluploadL10n.default_error)}}function uploadSizeError(e,a){var r=pluploadL10n.file_exceeds_size_limit.replace("%s",a.name),r=jQuery("
    ").attr({id:"media-item-"+a.id,class:"media-item error"}).append(jQuery("

    ").text(r));jQuery("#media-items").append(r),e.removeFile(a)}function wpFileExtensionError(e,a,r){jQuery("#media-items").append('

    '+r+"

    "),e.removeFile(a)}function copyAttachmentUploadURLClipboard(){var i;new ClipboardJS(".copy-attachment-url").on("success",function(e){var a=jQuery(e.trigger),r=jQuery(".success",a.closest(".copy-to-clipboard-container"));e.clearSelection(),clearTimeout(i),r.removeClass("hidden"),i=setTimeout(function(){r.addClass("hidden")},3e3),wp.a11y.speak(pluploadL10n.file_url_copied)})}jQuery(document).ready(function(o){copyAttachmentUploadURLClipboard();var d,l={};o(".media-upload-form").on("click.uploader",function(e){var a,r=o(e.target);r.is('input[type="radio"]')?(a=r.closest("tr")).hasClass("align")?setUserSetting("align",r.val()):a.hasClass("image-size")&&setUserSetting("imgsize",r.val()):r.is("button.button")?(a=(a=e.target.className||"").match(/url([^ '"]+)/))&&a[1]&&(setUserSetting("urlbutton",a[1]),r.siblings(".urlfield").val(r.data("link-url"))):r.is("a.dismiss")?r.parents(".media-item").fadeOut(200,function(){o(this).remove()}):r.is(".upload-flash-bypass a")||r.is("a.uploader-html")?(o("#media-items, p.submit, span.big-file-warning").css("display","none"),switchUploader(0),e.preventDefault()):r.is(".upload-html-bypass a")?(o("#media-items, p.submit, span.big-file-warning").css("display",""),switchUploader(1),e.preventDefault()):r.is("a.describe-toggle-on")?(r.parent().addClass("open"),r.siblings(".slidetoggle").fadeIn(250,function(){var e=o(window).scrollTop(),a=o(window).height(),r=o(this).offset().top,i=o(this).height();a&&r&&i&&(a=e+a)<(i=r+i)&&(i-at[s]){a=1;break}}if(!i)return a;switch(i){case">":case"gt":return 0=":case"ge":return 0<=a;case"<=":case"le":return a<=0;case"==":case"=":case"eq":return 0===a;case"<>":case"!=":case"ne":return 0!==a;case"":case"<":case"lt":return a<0;default:return null}},global_event_dispatcher:"moxie.core.EventTarget.instance.dispatchEvent"};return l.OS=l.os,MXI_DEBUG&&(l.debug={runtime:!0,events:!1},l.log=function(){var e,t,i=arguments[0];"string"===n.typeOf(i)&&(i=n.sprintf.apply(this,arguments)),window&&window.console&&window.console.log?window.console.log(i):document&&((e=document.getElementById("moxie-console"))||((e=document.createElement("pre")).id="moxie-console",document.body.appendChild(e)),-1!==n.inArray(n.typeOf(i),["object","array"])?(t=i,e.appendChild(document.createTextNode(t+"\n"))):e.appendChild(document.createTextNode(i+"\n")))}),l}),e("moxie/core/I18n",["moxie/core/utils/Basic"],function(i){var t={};return{addI18n:function(e){return i.extend(t,e)},translate:function(e){return t[e]||e},_:function(e){return this.translate(e)},sprintf:function(e){var t=[].slice.call(arguments,1);return e.replace(/%[a-z]/g,function(){var e=t.shift();return"undefined"!==i.typeOf(e)?e:""})}}}),e("moxie/core/utils/Mime",["moxie/core/utils/Basic","moxie/core/I18n"],function(a,n){var e={mimes:{},extensions:{},addMimeType:function(e){for(var t,i,n=e.split(/,/),r=0;r>16&255,n=s>>8&255,s=255&s,d[l++]=64==r?String.fromCharCode(i):64==o?String.fromCharCode(i,n):String.fromCharCode(i,n,s),c>12&63,n=o>>6&63,r=63&o,c[u++]=s.charAt(o>>18&63)+s.charAt(i)+s.charAt(n)+s.charAt(r),ap.MAX_RESIZE_WIDTH||this.height>p.MAX_RESIZE_HEIGHT)throw new u.ImageError(u.ImageError.MAX_RESOLUTION_ERR);this.exec("Image","downsize",e.width,e.height,e.crop,e.preserveHeaders)}catch(e){this.trigger("error",e.code)}},crop:function(e,t,i){this.downsize(e,t,!0,i)},getAsCanvas:function(){if(l.can("create_canvas"))return this.connectRuntime(this.ruid).exec.call(this,"Image","getAsCanvas");throw new u.RuntimeError(u.RuntimeError.NOT_SUPPORTED_ERR)},getAsBlob:function(e,t){if(this.size)return this.exec("Image","getAsBlob",e||"image/jpeg",t||90);throw new u.DOMException(u.DOMException.INVALID_STATE_ERR)},getAsDataURL:function(e,t){if(this.size)return this.exec("Image","getAsDataURL",e||"image/jpeg",t||90);throw new u.DOMException(u.DOMException.INVALID_STATE_ERR)},getAsBinaryString:function(e,t){e=this.getAsDataURL(e,t);return h.atob(e.substring(e.indexOf("base64,")+7))},embed:function(r,e){var o,s=this;e=a.extend({width:this.width,height:this.height,type:this.type||"image/jpeg",quality:90},e||{});try{if(!(r=n.get(r)))throw new u.DOMException(u.DOMException.INVALID_NODE_TYPE_ERR);if(!this.size)throw new u.DOMException(u.DOMException.INVALID_STATE_ERR);this.width>p.MAX_RESIZE_WIDTH||this.height;var t=new p;return t.bind("Resize",function(){!function(e,t){var i=this;if(l.can("create_canvas")){var n=i.getAsCanvas();if(n)return r.appendChild(n),i.destroy(),void s.trigger("embedded")}if(!(n=i.getAsDataURL(e,t)))throw new u.ImageError(u.ImageError.WRONG_FORMAT);l.can("use_data_uri_of",n.length)?(r.innerHTML='',i.destroy(),s.trigger("embedded")):((t=new c).bind("TransportingComplete",function(){o=s.connectRuntime(this.result.ruid),s.bind("Embedded",function(){a.extend(o.getShimContainer().style,{top:"0px",left:"0px",width:i.width+"px",height:i.height+"px"}),o=null},999),o.exec.call(s,"ImageView","display",this.result.uid,width,height),i.destroy()}),t.transport(h.atob(n.substring(n.indexOf("base64,")+7)),e,{required_caps:{display_media:!0},runtime_order:"flash,silverlight",container:r}))}.call(this,e.type,e.quality)}),t.bind("Load",function(){t.downsize(e)}),this.meta.thumb&&this.meta.thumb.width>=e.width&&this.meta.thumb.height>=e.height?t.load(this.meta.thumb.data):t.clone(this,!1),t}catch(e){this.trigger("error",e.code)}},destroy:function(){this.ruid&&(this.getRuntime().exec.call(this,"Image","destroy"),this.disconnectRuntime()),this.unbindAll()}}),this.handleEventProps(f),this.bind("Load Resize",function(){!function(e){e=e||this.exec("Image","getInfo");this.size=e.size,this.width=e.width,this.height=e.height,this.type=e.type,this.meta=e.meta,""===this.name&&(this.name=e.name)}.call(this)},999)}return p.MAX_RESIZE_WIDTH=8192,p.MAX_RESIZE_HEIGHT=8192,p.prototype=i.instance,p}),e("moxie/runtime/html5/Runtime",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/runtime/Runtime","moxie/core/utils/Env"],function(s,e,a,u){var c={};return a.addConstructor("html5",function(e){var t,i=this,n=a.capTest,r=a.capTrue,o=s.extend({access_binary:n(window.FileReader||window.File&&window.File.getAsDataURL),access_image_binary:function(){return i.can("access_binary")&&!!c.Image},display_media:n(u.can("create_canvas")||u.can("use_data_uri_over32kb")),do_cors:n(window.XMLHttpRequest&&"withCredentials"in new XMLHttpRequest),drag_and_drop:n(("draggable"in(o=document.createElement("div"))||"ondragstart"in o&&"ondrop"in o)&&("IE"!==u.browser||u.verComp(u.version,9,">"))),filter_by_extension:n("Chrome"===u.browser&&u.verComp(u.version,28,">=")||"IE"===u.browser&&u.verComp(u.version,10,">=")||"Safari"===u.browser&&u.verComp(u.version,7,">=")),return_response_headers:r,return_response_type:function(e){return!("json"!==e||!window.JSON)||u.can("return_response_type",e)},return_status_code:r,report_upload_progress:n(window.XMLHttpRequest&&(new XMLHttpRequest).upload),resize_image:function(){return i.can("access_binary")&&u.can("create_canvas")},select_file:function(){return u.can("use_fileinput")&&window.File},select_folder:function(){return i.can("select_file")&&"Chrome"===u.browser&&u.verComp(u.version,21,">=")},select_multiple:function(){return i.can("select_file")&&!("Safari"===u.browser&&"Windows"===u.os)&&!("iOS"===u.os&&u.verComp(u.osVersion,"7.0.0",">")&&u.verComp(u.osVersion,"8.0.0","<"))},send_binary_string:n(window.XMLHttpRequest&&((new XMLHttpRequest).sendAsBinary||window.Uint8Array&&window.ArrayBuffer)),send_custom_headers:n(window.XMLHttpRequest),send_multipart:function(){return!!(window.XMLHttpRequest&&(new XMLHttpRequest).upload&&window.FormData)||i.can("send_binary_string")},slice_blob:n(window.File&&(File.prototype.mozSlice||File.prototype.webkitSlice||File.prototype.slice)),stream_upload:function(){return i.can("slice_blob")&&i.can("send_multipart")},summon_file_dialog:function(){return i.can("select_file")&&("Firefox"===u.browser&&u.verComp(u.version,4,">=")||"Opera"===u.browser&&u.verComp(u.version,12,">=")||"IE"===u.browser&&u.verComp(u.version,10,">=")||!!~s.inArray(u.browser,["Chrome","Safari"]))},upload_filesize:r},arguments[2]);a.call(this,e,arguments[1]||"html5",o),s.extend(this,{init:function(){this.trigger("Init")},destroy:(t=this.destroy,function(){t.call(i),t=i=null})}),s.extend(this.getShim(),c)}),c}),e("moxie/core/utils/Events",["moxie/core/utils/Basic"],function(o){var s={},a="moxie_"+o.guid();function u(){this.returnValue=!1}function c(){this.cancelBubble=!0}function r(t,e,i){if(e=e.toLowerCase(),t[a]&&s[t[a]]&&s[t[a]][e]){for(var n,r=(n=s[t[a]][e]).length-1;0<=r&&(n[r].orig!==i&&n[r].key!==i||(t.removeEventListener?t.removeEventListener(e,n[r].func,!1):t.detachEvent&&t.detachEvent("on"+e,n[r].func),n[r].orig=null,n[r].func=null,n.splice(r,1),void 0===i));r--);if(n.length||delete s[t[a]][e],o.isEmptyObj(s[t[a]])){delete s[t[a]];try{delete t[a]}catch(e){t[a]=void 0}}}}return{addEvent:function(e,t,i,n){var r;t=t.toLowerCase(),e.addEventListener?e.addEventListener(t,r=i,!1):e.attachEvent&&e.attachEvent("on"+t,r=function(){var e=window.event;e.target||(e.target=e.srcElement),e.preventDefault=u,e.stopPropagation=c,i(e)}),e[a]||(e[a]=o.guid()),s.hasOwnProperty(e[a])||(s[e[a]]={}),(e=s[e[a]]).hasOwnProperty(t)||(e[t]=[]),e[t].push({func:r,orig:i,key:n})},removeEvent:r,removeAllEvents:function(i,n){i&&i[a]&&o.each(s[i[a]],function(e,t){r(i,t,n)})}}}),e("moxie/runtime/html5/file/FileInput",["moxie/runtime/html5/Runtime","moxie/file/File","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Events","moxie/core/utils/Mime","moxie/core/utils/Env"],function(e,a,u,c,l,d,m){return e.FileInput=function(){var s;u.extend(this,{init:function(e){var t,i,n,r=this,o=r.getRuntime(),e=(s=e).accept.mimes||d.extList2mimes(s.accept,o.can("filter_by_extension"));(t=o.getShimContainer()).innerHTML='",e=c.get(o.uid),u.extend(e.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),i=c.get(s.browse_button),o.can("summon_file_dialog")&&("static"===c.getStyle(i,"position")&&(i.style.position="relative"),n=parseInt(c.getStyle(i,"z-index"),10)||1,i.style.zIndex=n,t.style.zIndex=n-1,l.addEvent(i,"click",function(e){var t=c.get(o.uid);t&&!t.disabled&&t.click(),e.preventDefault()},r.uid)),n=o.can("summon_file_dialog")?i:t,l.addEvent(n,"mouseover",function(){r.trigger("mouseenter")},r.uid),l.addEvent(n,"mouseout",function(){r.trigger("mouseleave")},r.uid),l.addEvent(n,"mousedown",function(){r.trigger("mousedown")},r.uid),l.addEvent(c.get(s.container),"mouseup",function(){r.trigger("mouseup")},r.uid),e.onchange=function e(t){var i;r.files=[],u.each(this.files,function(e){var t="";if(s.directory&&"."==e.name)return!0;e.webkitRelativePath&&(t="/"+e.webkitRelativePath.replace(/^\//,"")),(e=new a(o.uid,e)).relativePath=t,r.files.push(e)}),"IE"!==m.browser&&"IEMobile"!==m.browser?this.value="":(i=this.cloneNode(!0),this.parentNode.replaceChild(i,this),i.onchange=e),r.files.length&&r.trigger("change")},r.trigger({type:"ready",async:!0})},disable:function(e){var t=this.getRuntime();(t=c.get(t.uid))&&(t.disabled=!!e)},destroy:function(){var e=this.getRuntime(),t=e.getShim(),e=e.getShimContainer();l.removeAllEvents(e,this.uid),l.removeAllEvents(s&&c.get(s.container),this.uid),l.removeAllEvents(s&&c.get(s.browse_button),this.uid),e&&(e.innerHTML=""),t.removeInstance(this.uid),s=null}})}}),e("moxie/runtime/html5/file/Blob",["moxie/runtime/html5/Runtime","moxie/file/Blob"],function(e,t){return e.Blob=function(){this.slice=function(){return new t(this.getRuntime().uid,function(t,i,n){var e;if(!window.File.prototype.slice)return(e=window.File.prototype.webkitSlice||window.File.prototype.mozSlice)?e.call(t,i,n):null;try{return t.slice(),t.slice(i,n)}catch(e){return t.slice(i,n-i)}}.apply(this,arguments))}}}),e("moxie/runtime/html5/file/FileDrop",["moxie/runtime/html5/Runtime","moxie/file/File","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Events","moxie/core/utils/Mime"],function(e,r,l,i,d,m){return e.FileDrop=function(){var t,n,o=[],s=[];function a(e){if(e.dataTransfer&&e.dataTransfer.types)return e=l.toArray(e.dataTransfer.types||[]),-1!==l.inArray("Files",e)||-1!==l.inArray("public.file-url",e)||-1!==l.inArray("application/x-moz-file",e)}function u(e,t){var i;i=e,s.length&&(i=m.getFileExtension(i.name))&&-1===l.inArray(i,s)||((i=new r(n,e)).relativePath=t||"",o.push(i))}function c(e,t){var i=[];l.each(e,function(s){i.push(function(e){{var t,n,r;(o=e,(i=s).isFile)?i.file(function(e){u(e,i.fullPath),o()},function(){o()}):i.isDirectory?(t=o,n=[],r=(e=i).createReader(),function t(i){r.readEntries(function(e){e.length?([].push.apply(n,e),t(i)):i()},i)}(function(){c(n,t)})):o()}var i,o})}),l.inSeries(i,function(){t()})}l.extend(this,{init:function(e){var r=this;t=e,n=r.ruid,s=function(e){for(var t=[],i=0;i=")&&E.verComp(E.version,7,"<"),o="Android Browser"===E.browser,s=!1;if(l=e.url.replace(/^.+?\/([\w\-\.]+)$/,"$1").toLowerCase(),(c=!window.XMLHttpRequest||"IE"===E.browser&&E.verComp(E.version,8,"<")?function(){for(var e=["Msxml2.XMLHTTP.6.0","Microsoft.XMLHTTP"],t=0;tthis.length())throw new Error("You are trying to read outside the source boundaries.");for(n=this.littleEndian?0:-8*(t-1),i=r=0;rthis.length())throw new Error("You are trying to write outside the source boundaries.");for(n=this.littleEndian?0:-8*(i-1),r=0;r>Math.abs(n+8*r)&255)},BYTE:function(e){return this.read(e,1)},SHORT:function(e){return this.read(e,2)},LONG:function(e){return this.read(e,4)},SLONG:function(e){e=this.read(e,4);return 2147483647=o.length));i++);},purge:function(){this.headers=s=[]}}}}),e("moxie/runtime/html5/image/ExifParser",["moxie/core/utils/Basic","moxie/runtime/html5/utils/BinaryReader","moxie/core/Exceptions"],function(p,o,g){function s(e){var t,l,h,f,i;if(o.call(this,e),l={tiff:{274:"Orientation",270:"ImageDescription",271:"Make",272:"Model",305:"Software",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer"},exif:{36864:"ExifVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",36867:"DateTimeOriginal",33434:"ExposureTime",33437:"FNumber",34855:"ISOSpeedRatings",37377:"ShutterSpeedValue",37378:"ApertureValue",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37386:"FocalLength",41986:"ExposureMode",41987:"WhiteBalance",41990:"SceneCaptureType",41988:"DigitalZoomRatio",41992:"Contrast",41993:"Saturation",41994:"Sharpness"},gps:{0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude"},thumb:{513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength"}},h={ColorSpace:{1:"sRGB",0:"Uncalibrated"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{1:"Daylight",2:"Fliorescent",3:"Tungsten",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 -5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},ExposureMode:{0:"Auto exposure",1:"Manual exposure",2:"Auto bracket"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},GPSLatitudeRef:{N:"North latitude",S:"South latitude"},GPSLongitudeRef:{E:"East longitude",W:"West longitude"}},n=(f={tiffHeader:10}).tiffHeader,t={clear:this.clear},p.extend(this,{read:function(){try{return s.prototype.read.apply(this,arguments)}catch(e){throw new g.ImageError(g.ImageError.INVALID_META_ERR)}},write:function(){try{return s.prototype.write.apply(this,arguments)}catch(e){throw new g.ImageError(g.ImageError.INVALID_META_ERR)}},UNDEFINED:function(){return this.BYTE.apply(this,arguments)},RATIONAL:function(e){return this.LONG(e)/this.LONG(e+4)},SRATIONAL:function(e){return this.SLONG(e)/this.SLONG(e+4)},ASCII:function(e){return this.CHAR(e)},TIFF:function(){return i||null},EXIF:function(){var e=null;if(f.exifIFD){try{e=r.call(this,f.exifIFD,l.exif)}catch(e){return null}if(e.ExifVersion&&"array"===p.typeOf(e.ExifVersion)){for(var t=0,i="";t=this.length())throw new g.ImageError(g.ImageError.INVALID_META_ERR);"ASCII"===o?u[i]=p.trim(a.STRING(r,n).replace(/\0$/,"")):(s=a.asArray(o,r,n),o=1==n?s[0]:s,h.hasOwnProperty(i)&&"object"!=typeof o?u[i]=h[i][o]:u[i]=o)}return u}n&&(f.IFD1=f.tiffHeader+n)}return s.prototype=o.prototype,s}),e("moxie/runtime/html5/image/JPEG",["moxie/core/utils/Basic","moxie/core/Exceptions","moxie/runtime/html5/image/JPEGHeaders","moxie/runtime/html5/utils/BinaryReader","moxie/runtime/html5/image/ExifParser"],function(s,a,u,c,l){return function(e){var i,n,t,r=new c(e);if(65496!==r.SHORT(0))throw new a.ImageError(a.ImageError.WRONG_FORMAT);i=new u(e);try{n=new l(i.get("app1")[0])}catch(e){}function o(e){var t,i=0;for(e=e||r;i<=e.length();){if(65472<=(t=e.SHORT(i+=2))&&t<=65475)return i+=5,{height:e.SHORT(i),width:e.SHORT(i+=2)};t=e.SHORT(i+=2),i+=t-2}return null}t=o.call(this),s.extend(this,{type:"image/jpeg",size:r.length(),width:t&&t.width||0,height:t&&t.height||0,setExif:function(e,t){if(!n)return!1;"object"===s.typeOf(e)?s.each(e,function(e,t){n.setExif(t,e)}):n.setExif(e,t),i.set("app1",n.SEGMENT())},writeHeaders:function(){return arguments.length?i.restore(arguments[0]):i.restore(e)},stripHeaders:function(e){return i.strip(e)},purge:function(){!function(){n&&i&&r&&(n.clear(),i.purge(),r.clear(),t=i=n=r=null)}.call(this)}}),n&&(this.meta={tiff:n.TIFF(),exif:n.EXIF(),gps:n.GPS(),thumb:function(){var e,t,i=n.thumb();if(i&&(e=new c(i),t=o(e),e.clear(),t))return t.data=i,t;return null}()})}}),e("moxie/runtime/html5/image/PNG",["moxie/core/Exceptions","moxie/core/utils/Basic","moxie/runtime/html5/utils/BinaryReader"],function(a,u,c){return function(e){for(var t,r=new c(e),i=0,n=0,o=[35152,20039,3338,6666],n=0;n>1;i=null;e=a/t;return 0==e?1:e}(e,r),f=0;f=")||"IE"===a.browser&&a.verComp(a.version,10,">=")||"Safari"===a.browser&&a.verComp(a.version,7,">=")),resize_image:function(){return u.Image&&i.can("access_binary")&&a.can("create_canvas")},report_upload_progress:!1,return_response_headers:!1,return_response_type:function(e){return!("json"!==e||!window.JSON)||!!~o.inArray(e,["text","document",""])},return_status_code:function(e){return!o.arrayDiff(e,[200,404])},select_file:function(){return a.can("use_fileinput")},select_multiple:!1,send_binary_string:!1,send_custom_headers:!1,send_multipart:!0,slice_blob:!1,stream_upload:function(){return i.can("select_file")},summon_file_dialog:function(){return i.can("select_file")&&("Firefox"===a.browser&&a.verComp(a.version,4,">=")||"Opera"===a.browser&&a.verComp(a.version,12,">=")||"IE"===a.browser&&a.verComp(a.version,10,">=")||!!~o.inArray(a.browser,["Chrome","Safari"]))},upload_filesize:r,use_http_method:function(e){return!o.arrayDiff(e,["GET","POST"])}}),o.extend(this,{init:function(){this.trigger("Init")},destroy:(t=this.destroy,function(){t.call(i),t=i=null})}),o.extend(this.getShim(),u)}),u}),e("moxie/runtime/html4/file/FileInput",["moxie/runtime/html4/Runtime","moxie/file/File","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Events","moxie/core/utils/Mime","moxie/core/utils/Env"],function(e,d,m,h,f,s,p){return e.FileInput=function(){var a,u,c=[];function l(){var e,t,i,n=this,r=n.getRuntime(),o=m.guid("uid_"),s=r.getShimContainer();a&&(e=h.get(a+"_form"))&&m.extend(e.style,{top:"100%"}),(t=document.createElement("form")).setAttribute("id",o+"_form"),t.setAttribute("method","post"),t.setAttribute("enctype","multipart/form-data"),t.setAttribute("encoding","multipart/form-data"),m.extend(t.style,{overflow:"hidden",position:"absolute",top:0,left:0,width:"100%",height:"100%"}),(i=document.createElement("input")).setAttribute("id",o),i.setAttribute("type","file"),i.setAttribute("name",u.name||"Filedata"),i.setAttribute("accept",c.join(",")),m.extend(i.style,{fontSize:"999px",opacity:0}),t.appendChild(i),s.appendChild(t),m.extend(i.style,{position:"absolute",top:0,left:0,width:"100%",height:"100%"}),"IE"===p.browser&&p.verComp(p.version,10,"<")&&m.extend(i.style,{filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=0)"}),i.onchange=function(){var e;if(this.value){if(this.files){if(0===(e=this.files[0]).size)return void t.parentNode.removeChild(t)}else e={name:this.value};e=new d(r.uid,e),this.onchange=function(){},l.call(n),n.files=[e],i.setAttribute("id",e.uid),t.setAttribute("id",e.uid+"_form"),n.trigger("change"),i=t=null}},r.can("summon_file_dialog")&&(e=h.get(u.browse_button),f.removeEvent(e,"click",n.uid),f.addEvent(e,"click",function(e){i&&!i.disabled&&i.click(),e.preventDefault()},n.uid)),a=o}m.extend(this,{init:function(e){var t,i,n,r=this,o=r.getRuntime();c=(u=e).accept.mimes||s.extList2mimes(e.accept,o.can("filter_by_extension")),t=o.getShimContainer(),n=h.get(e.browse_button),o.can("summon_file_dialog")&&("static"===h.getStyle(n,"position")&&(n.style.position="relative"),i=parseInt(h.getStyle(n,"z-index"),10)||1,n.style.zIndex=i,t.style.zIndex=i-1),i=o.can("summon_file_dialog")?n:t,f.addEvent(i,"mouseover",function(){r.trigger("mouseenter")},r.uid),f.addEvent(i,"mouseout",function(){r.trigger("mouseleave")},r.uid),f.addEvent(i,"mousedown",function(){r.trigger("mousedown")},r.uid),f.addEvent(h.get(e.container),"mouseup",function(){r.trigger("mouseup")},r.uid),l.call(this),t=null,r.trigger({type:"ready",async:!0})},disable:function(e){var t;(t=h.get(a))&&(t.disabled=!!e)},destroy:function(){var e=this.getRuntime(),t=e.getShim(),e=e.getShimContainer();f.removeAllEvents(e,this.uid),f.removeAllEvents(u&&h.get(u.container),this.uid),f.removeAllEvents(u&&h.get(u.browse_button),this.uid),e&&(e.innerHTML=""),t.removeInstance(this.uid),a=c=u=null}})}}),e("moxie/runtime/html4/file/FileReader",["moxie/runtime/html4/Runtime","moxie/runtime/html5/file/FileReader"],function(e,t){return e.FileReader=t}),e("moxie/runtime/html4/xhr/XMLHttpRequest",["moxie/runtime/html4/Runtime","moxie/core/utils/Basic","moxie/core/utils/Dom","moxie/core/utils/Url","moxie/core/Exceptions","moxie/core/utils/Events","moxie/file/Blob","moxie/xhr/FormData"],function(e,m,h,f,p,g,x,E){return e.XMLHttpRequest=function(){var u,c,l;function d(t){var e,i,n,r=this,o=!1;if(l){if(e=l.id.replace(/_iframe$/,""),e=h.get(e+"_form")){for(n=(i=e.getElementsByTagName("input")).length;n--;)switch(i[n].getAttribute("type")){case"hidden":i[n].parentNode.removeChild(i[n]);break;case"file":o=!0}i=[],o||e.parentNode.removeChild(e),e=null}setTimeout(function(){g.removeEvent(l,"load",r.uid),l.parentNode&&l.parentNode.removeChild(l);var e=r.getRuntime().getShimContainer();e.children.length||e.parentNode.removeChild(e),e=l=null,t()},1)}}m.extend(this,{send:function(t,e){var i,n,r,o,s=this,a=s.getRuntime();if(u=c=null,e instanceof E&&e.hasBlob()){if(o=e.getBlob(),i=o.uid,r=h.get(i),!(n=h.get(i+"_form")))throw new p.DOMException(p.DOMException.NOT_FOUND_ERR)}else i=m.guid("uid_"),(n=document.createElement("form")).setAttribute("id",i+"_form"),n.setAttribute("method",t.method),n.setAttribute("enctype","multipart/form-data"),n.setAttribute("encoding","multipart/form-data"),a.getShimContainer().appendChild(n);n.setAttribute("target",i+"_iframe"),e instanceof E&&e.each(function(e,t){var i;e instanceof x?r&&r.setAttribute("name",t):(i=document.createElement("input"),m.extend(i,{type:"hidden",name:t,value:e}),r?n.insertBefore(i,r):n.appendChild(i))}),n.setAttribute("action",t.url),e=a.getShimContainer()||document.body,(a=document.createElement("div")).innerHTML='',l=a.firstChild,e.appendChild(l),g.addEvent(l,"load",function(){var e;try{e=l.contentWindow.document||l.contentDocument||window.frames[l.id].document,/^4(0[0-9]|1[0-7]|2[2346])\s/.test(e.title)?u=e.title.replace(/^(\d+).*$/,"$1"):(u=200,c=m.trim(e.body.innerHTML),s.trigger({type:"progress",loaded:c.length,total:c.length}),o&&s.trigger({type:"uploadprogress",loaded:o.size||1025,total:o.size||1025}))}catch(e){if(!f.hasSameOrigin(t.url))return void d.call(s,function(){s.trigger("error")});u=404}d.call(s,function(){s.trigger("load")})},s.uid),n.submit(),s.trigger("loadstart")},getStatus:function(){return u},getResponse:function(e){if("json"===e&&"string"===m.typeOf(c)&&window.JSON)try{return JSON.parse(c.replace(/^\s*]*>/,"").replace(/<\/pre>\s*$/,""))}catch(e){return null}return c},abort:function(){var e=this;l&&l.contentWindow&&(l.contentWindow.stop?l.contentWindow.stop():l.contentWindow.document.execCommand?l.contentWindow.document.execCommand("Stop"):l.src="about:blank"),d.call(this,function(){e.dispatchEvent("abort")})}})}}),e("moxie/runtime/html4/image/Image",["moxie/runtime/html4/Runtime","moxie/runtime/html5/image/Image"],function(e,t){return e.Image=t});for(var t=["moxie/core/utils/Basic","moxie/core/utils/Env","moxie/core/I18n","moxie/core/utils/Mime","moxie/core/utils/Dom","moxie/core/Exceptions","moxie/core/EventTarget","moxie/runtime/Runtime","moxie/runtime/RuntimeClient","moxie/file/FileInput","moxie/core/utils/Encode","moxie/file/Blob","moxie/file/File","moxie/file/FileDrop","moxie/file/FileReader","moxie/core/utils/Url","moxie/runtime/RuntimeTarget","moxie/file/FileReaderSync","moxie/xhr/FormData","moxie/xhr/XMLHttpRequest","moxie/runtime/Transporter","moxie/image/Image","moxie/core/utils/Events"],i=0;i 0) { caps.slice_blob = true; } if (settings.resize.enabled || !settings.multipart) { caps.send_binary_string = true; } plupload.each(settings, function(value, feature) { resolve(feature, !!value, true); // strict check }); } // WP: only html runtimes. settings.runtimes = 'html5,html4'; return caps; } /** * @module plupload * @static */ var plupload = { /** * Plupload version will be replaced on build. * * @property VERSION * @for Plupload * @static * @final */ VERSION : '2.1.9', /** * The state of the queue before it has started and after it has finished * * @property STOPPED * @static * @final */ STOPPED : 1, /** * Upload process is running * * @property STARTED * @static * @final */ STARTED : 2, /** * File is queued for upload * * @property QUEUED * @static * @final */ QUEUED : 1, /** * File is being uploaded * * @property UPLOADING * @static * @final */ UPLOADING : 2, /** * File has failed to be uploaded * * @property FAILED * @static * @final */ FAILED : 4, /** * File has been uploaded successfully * * @property DONE * @static * @final */ DONE : 5, // Error constants used by the Error event /** * Generic error for example if an exception is thrown inside Silverlight. * * @property GENERIC_ERROR * @static * @final */ GENERIC_ERROR : -100, /** * HTTP transport error. For example if the server produces a HTTP status other than 200. * * @property HTTP_ERROR * @static * @final */ HTTP_ERROR : -200, /** * Generic I/O error. For example if it wasn't possible to open the file stream on local machine. * * @property IO_ERROR * @static * @final */ IO_ERROR : -300, /** * @property SECURITY_ERROR * @static * @final */ SECURITY_ERROR : -400, /** * Initialization error. Will be triggered if no runtime was initialized. * * @property INIT_ERROR * @static * @final */ INIT_ERROR : -500, /** * File size error. If the user selects a file that is too large it will be blocked and an error of this type will be triggered. * * @property FILE_SIZE_ERROR * @static * @final */ FILE_SIZE_ERROR : -600, /** * File extension error. If the user selects a file that isn't valid according to the filters setting. * * @property FILE_EXTENSION_ERROR * @static * @final */ FILE_EXTENSION_ERROR : -601, /** * Duplicate file error. If prevent_duplicates is set to true and user selects the same file again. * * @property FILE_DUPLICATE_ERROR * @static * @final */ FILE_DUPLICATE_ERROR : -602, /** * Runtime will try to detect if image is proper one. Otherwise will throw this error. * * @property IMAGE_FORMAT_ERROR * @static * @final */ IMAGE_FORMAT_ERROR : -700, /** * While working on files runtime may run out of memory and will throw this error. * * @since 2.1.2 * @property MEMORY_ERROR * @static * @final */ MEMORY_ERROR : -701, /** * Each runtime has an upper limit on a dimension of the image it can handle. If bigger, will throw this error. * * @property IMAGE_DIMENSIONS_ERROR * @static * @final */ IMAGE_DIMENSIONS_ERROR : -702, /** * Mime type lookup table. * * @property mimeTypes * @type Object * @final */ mimeTypes : o.mimes, /** * In some cases sniffing is the only way around :( */ ua: o.ua, /** * Gets the true type of the built-in object (better version of typeof). * @credits Angus Croll (http://javascriptweblog.wordpress.com/) * * @method typeOf * @static * @param {Object} o Object to check. * @return {String} Object [[Class]] */ typeOf: o.typeOf, /** * Extends the specified object with another object. * * @method extend * @static * @param {Object} target Object to extend. * @param {Object..} obj Multiple objects to extend with. * @return {Object} Same as target, the extended object. */ extend : o.extend, /** * Generates an unique ID. This is 99.99% unique since it takes the current time and 5 random numbers. * The only way a user would be able to get the same ID is if the two persons at the same exact millisecond manages * to get 5 the same random numbers between 0-65535 it also uses a counter so each call will be guaranteed to be page unique. * It's more probable for the earth to be hit with an asteriod. You can also if you want to be 100% sure set the plupload.guidPrefix property * to an user unique key. * * @method guid * @static * @return {String} Virtually unique id. */ guid : o.guid, /** * Get array of DOM Elements by their ids. * * @method get * @param {String} id Identifier of the DOM Element * @return {Array} */ getAll : function get(ids) { var els = [], el; if (plupload.typeOf(ids) !== 'array') { ids = [ids]; } var i = ids.length; while (i--) { el = plupload.get(ids[i]); if (el) { els.push(el); } } return els.length ? els : null; }, /** Get DOM element by id @method get @param {String} id Identifier of the DOM Element @return {Node} */ get: o.get, /** * Executes the callback function for each item in array/object. If you return false in the * callback it will break the loop. * * @method each * @static * @param {Object} obj Object to iterate. * @param {function} callback Callback function to execute for each item. */ each : o.each, /** * Returns the absolute x, y position of an Element. The position will be returned in a object with x, y fields. * * @method getPos * @static * @param {Element} node HTML element or element id to get x, y position from. * @param {Element} root Optional root element to stop calculations at. * @return {object} Absolute position of the specified element object with x, y fields. */ getPos : o.getPos, /** * Returns the size of the specified node in pixels. * * @method getSize * @static * @param {Node} node Node to get the size of. * @return {Object} Object with a w and h property. */ getSize : o.getSize, /** * Encodes the specified string. * * @method xmlEncode * @static * @param {String} s String to encode. * @return {String} Encoded string. */ xmlEncode : function(str) { var xmlEncodeChars = {'<' : 'lt', '>' : 'gt', '&' : 'amp', '"' : 'quot', '\'' : '#39'}, xmlEncodeRegExp = /[<>&\"\']/g; return str ? ('' + str).replace(xmlEncodeRegExp, function(chr) { return xmlEncodeChars[chr] ? '&' + xmlEncodeChars[chr] + ';' : chr; }) : str; }, /** * Forces anything into an array. * * @method toArray * @static * @param {Object} obj Object with length field. * @return {Array} Array object containing all items. */ toArray : o.toArray, /** * Find an element in array and return its index if present, otherwise return -1. * * @method inArray * @static * @param {mixed} needle Element to find * @param {Array} array * @return {Int} Index of the element, or -1 if not found */ inArray : o.inArray, /** * Extends the language pack object with new items. * * @method addI18n * @static * @param {Object} pack Language pack items to add. * @return {Object} Extended language pack object. */ addI18n : o.addI18n, /** * Translates the specified string by checking for the english string in the language pack lookup. * * @method translate * @static * @param {String} str String to look for. * @return {String} Translated string or the input string if it wasn't found. */ translate : o.translate, /** * Checks if object is empty. * * @method isEmptyObj * @static * @param {Object} obj Object to check. * @return {Boolean} */ isEmptyObj : o.isEmptyObj, /** * Checks if specified DOM element has specified class. * * @method hasClass * @static * @param {Object} obj DOM element like object to add handler to. * @param {String} name Class name */ hasClass : o.hasClass, /** * Adds specified className to specified DOM element. * * @method addClass * @static * @param {Object} obj DOM element like object to add handler to. * @param {String} name Class name */ addClass : o.addClass, /** * Removes specified className from specified DOM element. * * @method removeClass * @static * @param {Object} obj DOM element like object to add handler to. * @param {String} name Class name */ removeClass : o.removeClass, /** * Returns a given computed style of a DOM element. * * @method getStyle * @static * @param {Object} obj DOM element like object. * @param {String} name Style you want to get from the DOM element */ getStyle : o.getStyle, /** * Adds an event handler to the specified object and store reference to the handler * in objects internal Plupload registry (@see removeEvent). * * @method addEvent * @static * @param {Object} obj DOM element like object to add handler to. * @param {String} name Name to add event listener to. * @param {Function} callback Function to call when event occurs. * @param {String} (optional) key that might be used to add specifity to the event record. */ addEvent : o.addEvent, /** * Remove event handler from the specified object. If third argument (callback) * is not specified remove all events with the specified name. * * @method removeEvent * @static * @param {Object} obj DOM element to remove event listener(s) from. * @param {String} name Name of event listener to remove. * @param {Function|String} (optional) might be a callback or unique key to match. */ removeEvent: o.removeEvent, /** * Remove all kind of events from the specified object * * @method removeAllEvents * @static * @param {Object} obj DOM element to remove event listeners from. * @param {String} (optional) unique key to match, when removing events. */ removeAllEvents: o.removeAllEvents, /** * Cleans the specified name from national characters (diacritics). The result will be a name with only a-z, 0-9 and _. * * @method cleanName * @static * @param {String} s String to clean up. * @return {String} Cleaned string. */ cleanName : function(name) { var i, lookup; // Replace diacritics lookup = [ /[\300-\306]/g, 'A', /[\340-\346]/g, 'a', /\307/g, 'C', /\347/g, 'c', /[\310-\313]/g, 'E', /[\350-\353]/g, 'e', /[\314-\317]/g, 'I', /[\354-\357]/g, 'i', /\321/g, 'N', /\361/g, 'n', /[\322-\330]/g, 'O', /[\362-\370]/g, 'o', /[\331-\334]/g, 'U', /[\371-\374]/g, 'u' ]; for (i = 0; i < lookup.length; i += 2) { name = name.replace(lookup[i], lookup[i + 1]); } // Replace whitespace name = name.replace(/\s+/g, '_'); // Remove anything else name = name.replace(/[^a-z0-9_\-\.]+/gi, ''); return name; }, /** * Builds a full url out of a base URL and an object with items to append as query string items. * * @method buildUrl * @static * @param {String} url Base URL to append query string items to. * @param {Object} items Name/value object to serialize as a querystring. * @return {String} String with url + serialized query string items. */ buildUrl : function(url, items) { var query = ''; plupload.each(items, function(value, name) { query += (query ? '&' : '') + encodeURIComponent(name) + '=' + encodeURIComponent(value); }); if (query) { url += (url.indexOf('?') > 0 ? '&' : '?') + query; } return url; }, /** * Formats the specified number as a size string for example 1024 becomes 1 KB. * * @method formatSize * @static * @param {Number} size Size to format as string. * @return {String} Formatted size string. */ formatSize : function(size) { if (size === undef || /\D/.test(size)) { return plupload.translate('N/A'); } function round(num, precision) { return Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision); } var boundary = Math.pow(1024, 4); // TB if (size > boundary) { return round(size / boundary, 1) + " " + plupload.translate('tb'); } // GB if (size > (boundary/=1024)) { return round(size / boundary, 1) + " " + plupload.translate('gb'); } // MB if (size > (boundary/=1024)) { return round(size / boundary, 1) + " " + plupload.translate('mb'); } // KB if (size > 1024) { return Math.round(size / 1024) + " " + plupload.translate('kb'); } return size + " " + plupload.translate('b'); }, /** * Parses the specified size string into a byte value. For example 10kb becomes 10240. * * @method parseSize * @static * @param {String|Number} size String to parse or number to just pass through. * @return {Number} Size in bytes. */ parseSize : o.parseSizeStr, /** * A way to predict what runtime will be choosen in the current environment with the * specified settings. * * @method predictRuntime * @static * @param {Object|String} config Plupload settings to check * @param {String} [runtimes] Comma-separated list of runtimes to check against * @return {String} Type of compatible runtime */ predictRuntime : function(config, runtimes) { var up, runtime; up = new plupload.Uploader(config); runtime = o.Runtime.thatCan(up.getOption().required_features, runtimes || config.runtimes); up.destroy(); return runtime; }, /** * Registers a filter that will be executed for each file added to the queue. * If callback returns false, file will not be added. * * Callback receives two arguments: a value for the filter as it was specified in settings.filters * and a file to be filtered. Callback is executed in the context of uploader instance. * * @method addFileFilter * @static * @param {String} name Name of the filter by which it can be referenced in settings.filters * @param {String} cb Callback - the actual routine that every added file must pass */ addFileFilter: function(name, cb) { fileFilters[name] = cb; } }; plupload.addFileFilter('mime_types', function(filters, file, cb) { if (filters.length && !filters.regexp.test(file.name)) { this.trigger('Error', { code : plupload.FILE_EXTENSION_ERROR, message : plupload.translate('File extension error.'), file : file }); cb(false); } else { cb(true); } }); plupload.addFileFilter('max_file_size', function(maxSize, file, cb) { var undef; maxSize = plupload.parseSize(maxSize); // Invalid file size if (file.size !== undef && maxSize && file.size > maxSize) { this.trigger('Error', { code : plupload.FILE_SIZE_ERROR, message : plupload.translate('File size error.'), file : file }); cb(false); } else { cb(true); } }); plupload.addFileFilter('prevent_duplicates', function(value, file, cb) { if (value) { var ii = this.files.length; while (ii--) { // Compare by name and size (size might be 0 or undefined, but still equivalent for both) if (file.name === this.files[ii].name && file.size === this.files[ii].size) { this.trigger('Error', { code : plupload.FILE_DUPLICATE_ERROR, message : plupload.translate('Duplicate file error.'), file : file }); cb(false); return; } } } cb(true); }); /** @class Uploader @constructor @param {Object} settings For detailed information about each option check documentation. @param {String|DOMElement} settings.browse_button id of the DOM element or DOM element itself to use as file dialog trigger. @param {String} settings.url URL of the server-side upload handler. @param {Number|String} [settings.chunk_size=0] Chunk size in bytes to slice the file into. Shorcuts with b, kb, mb, gb, tb suffixes also supported. `e.g. 204800 or "204800b" or "200kb"`. By default - disabled. @param {Boolean} [settings.send_chunk_number=true] Whether to send chunks and chunk numbers, or total and offset bytes. @param {String|DOMElement} [settings.container] id of the DOM element or DOM element itself that will be used to wrap uploader structures. Defaults to immediate parent of the `browse_button` element. @param {String|DOMElement} [settings.drop_element] id of the DOM element or DOM element itself to use as a drop zone for Drag-n-Drop. @param {String} [settings.file_data_name="file"] Name for the file field in Multipart formated message. @param {Object} [settings.filters={}] Set of file type filters. @param {Array} [settings.filters.mime_types=[]] List of file types to accept, each one defined by title and list of extensions. `e.g. {title : "Image files", extensions : "jpg,jpeg,gif,png"}`. Dispatches `plupload.FILE_EXTENSION_ERROR` @param {String|Number} [settings.filters.max_file_size=0] Maximum file size that the user can pick, in bytes. Optionally supports b, kb, mb, gb, tb suffixes. `e.g. "10mb" or "1gb"`. By default - not set. Dispatches `plupload.FILE_SIZE_ERROR`. @param {Boolean} [settings.filters.prevent_duplicates=false] Do not let duplicates into the queue. Dispatches `plupload.FILE_DUPLICATE_ERROR`. @param {String} [settings.flash_swf_url] URL of the Flash swf. (Not used in WordPress) @param {Object} [settings.headers] Custom headers to send with the upload. Hash of name/value pairs. @param {Number} [settings.max_retries=0] How many times to retry the chunk or file, before triggering Error event. @param {Boolean} [settings.multipart=true] Whether to send file and additional parameters as Multipart formated message. @param {Object} [settings.multipart_params] Hash of key/value pairs to send with every file upload. @param {Boolean} [settings.multi_selection=true] Enable ability to select multiple files at once in file dialog. @param {String|Object} [settings.required_features] Either comma-separated list or hash of required features that chosen runtime should absolutely possess. @param {Object} [settings.resize] Enable resizng of images on client-side. Applies to `image/jpeg` and `image/png` only. `e.g. {width : 200, height : 200, quality : 90, crop: true}` @param {Number} [settings.resize.width] If image is bigger, it will be resized. @param {Number} [settings.resize.height] If image is bigger, it will be resized. @param {Number} [settings.resize.quality=90] Compression quality for jpegs (1-100). @param {Boolean} [settings.resize.crop=false] Whether to crop images to exact dimensions. By default they will be resized proportionally. @param {String} [settings.runtimes="html5,html4"] Comma separated list of runtimes, that Plupload will try in turn, moving to the next if previous fails. @param {String} [settings.silverlight_xap_url] URL of the Silverlight xap. (Not used in WordPress) @param {Boolean} [settings.unique_names=false] If true will generate unique filenames for uploaded files. @param {Boolean} [settings.send_file_name=true] Whether to send file name as additional argument - 'name' (required for chunked uploads and some other cases where file name cannot be sent via normal ways). */ plupload.Uploader = function(options) { /** Fires when the current RunTime has been initialized. @event Init @param {plupload.Uploader} uploader Uploader instance sending the event. */ /** Fires after the init event incase you need to perform actions there. @event PostInit @param {plupload.Uploader} uploader Uploader instance sending the event. */ /** Fires when the option is changed in via uploader.setOption(). @event OptionChanged @since 2.1 @param {plupload.Uploader} uploader Uploader instance sending the event. @param {String} name Name of the option that was changed @param {Mixed} value New value for the specified option @param {Mixed} oldValue Previous value of the option */ /** Fires when the silverlight/flash or other shim needs to move. @event Refresh @param {plupload.Uploader} uploader Uploader instance sending the event. */ /** Fires when the overall state is being changed for the upload queue. @event StateChanged @param {plupload.Uploader} uploader Uploader instance sending the event. */ /** Fires when browse_button is clicked and browse dialog shows. @event Browse @since 2.1.2 @param {plupload.Uploader} uploader Uploader instance sending the event. */ /** Fires for every filtered file before it is added to the queue. @event FileFiltered @since 2.1 @param {plupload.Uploader} uploader Uploader instance sending the event. @param {plupload.File} file Another file that has to be added to the queue. */ /** Fires when the file queue is changed. In other words when files are added/removed to the files array of the uploader instance. @event QueueChanged @param {plupload.Uploader} uploader Uploader instance sending the event. */ /** Fires after files were filtered and added to the queue. @event FilesAdded @param {plupload.Uploader} uploader Uploader instance sending the event. @param {Array} files Array of file objects that were added to queue by the user. */ /** Fires when file is removed from the queue. @event FilesRemoved @param {plupload.Uploader} uploader Uploader instance sending the event. @param {Array} files Array of files that got removed. */ /** Fires just before a file is uploaded. Can be used to cancel the upload for the specified file by returning false from the handler. @event BeforeUpload @param {plupload.Uploader} uploader Uploader instance sending the event. @param {plupload.File} file File to be uploaded. */ /** Fires when a file is to be uploaded by the runtime. @event UploadFile @param {plupload.Uploader} uploader Uploader instance sending the event. @param {plupload.File} file File to be uploaded. */ /** Fires while a file is being uploaded. Use this event to update the current file upload progress. @event UploadProgress @param {plupload.Uploader} uploader Uploader instance sending the event. @param {plupload.File} file File that is currently being uploaded. */ /** Fires when file chunk is uploaded. @event ChunkUploaded @param {plupload.Uploader} uploader Uploader instance sending the event. @param {plupload.File} file File that the chunk was uploaded for. @param {Object} result Object with response properties. @param {Number} result.offset The amount of bytes the server has received so far, including this chunk. @param {Number} result.total The size of the file. @param {String} result.response The response body sent by the server. @param {Number} result.status The HTTP status code sent by the server. @param {String} result.responseHeaders All the response headers as a single string. */ /** Fires when a file is successfully uploaded. @event FileUploaded @param {plupload.Uploader} uploader Uploader instance sending the event. @param {plupload.File} file File that was uploaded. @param {Object} result Object with response properties. @param {String} result.response The response body sent by the server. @param {Number} result.status The HTTP status code sent by the server. @param {String} result.responseHeaders All the response headers as a single string. */ /** Fires when all files in a queue are uploaded. @event UploadComplete @param {plupload.Uploader} uploader Uploader instance sending the event. @param {Array} files Array of file objects that was added to queue/selected by the user. */ /** Fires when a error occurs. @event Error @param {plupload.Uploader} uploader Uploader instance sending the event. @param {Object} error Contains code, message and sometimes file and other details. @param {Number} error.code The plupload error code. @param {String} error.message Description of the error (uses i18n). */ /** Fires when destroy method is called. @event Destroy @param {plupload.Uploader} uploader Uploader instance sending the event. */ var uid = plupload.guid() , settings , files = [] , preferred_caps = {} , fileInputs = [] , fileDrops = [] , startTime , total , disabled = false , xhr ; // Private methods function uploadNext() { var file, count = 0, i; if (this.state == plupload.STARTED) { // Find first QUEUED file for (i = 0; i < files.length; i++) { if (!file && files[i].status == plupload.QUEUED) { file = files[i]; if (this.trigger("BeforeUpload", file)) { file.status = plupload.UPLOADING; this.trigger("UploadFile", file); } } else { count++; } } // All files are DONE or FAILED if (count == files.length) { if (this.state !== plupload.STOPPED) { this.state = plupload.STOPPED; this.trigger("StateChanged"); } this.trigger("UploadComplete", files); } } } function calcFile(file) { file.percent = file.size > 0 ? Math.ceil(file.loaded / file.size * 100) : 100; calc(); } function calc() { var i, file; // Reset stats total.reset(); // Check status, size, loaded etc on all files for (i = 0; i < files.length; i++) { file = files[i]; if (file.size !== undef) { // We calculate totals based on original file size total.size += file.origSize; // Since we cannot predict file size after resize, we do opposite and // interpolate loaded amount to match magnitude of total total.loaded += file.loaded * file.origSize / file.size; } else { total.size = undef; } if (file.status == plupload.DONE) { total.uploaded++; } else if (file.status == plupload.FAILED) { total.failed++; } else { total.queued++; } } // If we couldn't calculate a total file size then use the number of files to calc percent if (total.size === undef) { total.percent = files.length > 0 ? Math.ceil(total.uploaded / files.length * 100) : 0; } else { total.bytesPerSec = Math.ceil(total.loaded / ((+new Date() - startTime || 1) / 1000.0)); total.percent = total.size > 0 ? Math.ceil(total.loaded / total.size * 100) : 0; } } function getRUID() { var ctrl = fileInputs[0] || fileDrops[0]; if (ctrl) { return ctrl.getRuntime().uid; } return false; } function runtimeCan(file, cap) { if (file.ruid) { var info = o.Runtime.getInfo(file.ruid); if (info) { return info.can(cap); } } return false; } function bindEventListeners() { this.bind('FilesAdded FilesRemoved', function(up) { up.trigger('QueueChanged'); up.refresh(); }); this.bind('CancelUpload', onCancelUpload); this.bind('BeforeUpload', onBeforeUpload); this.bind('UploadFile', onUploadFile); this.bind('UploadProgress', onUploadProgress); this.bind('StateChanged', onStateChanged); this.bind('QueueChanged', calc); this.bind('Error', onError); this.bind('FileUploaded', onFileUploaded); this.bind('Destroy', onDestroy); } function initControls(settings, cb) { var self = this, inited = 0, queue = []; // common settings var options = { runtime_order: settings.runtimes, required_caps: settings.required_features, preferred_caps: preferred_caps }; // add runtime specific options if any plupload.each(settings.runtimes.split(/\s*,\s*/), function(runtime) { if (settings[runtime]) { options[runtime] = settings[runtime]; } }); // initialize file pickers - there can be many if (settings.browse_button) { plupload.each(settings.browse_button, function(el) { queue.push(function(cb) { var fileInput = new o.FileInput(plupload.extend({}, options, { accept: settings.filters.mime_types, name: settings.file_data_name, multiple: settings.multi_selection, container: settings.container, browse_button: el })); fileInput.onready = function() { var info = o.Runtime.getInfo(this.ruid); // for backward compatibility o.extend(self.features, { chunks: info.can('slice_blob'), multipart: info.can('send_multipart'), multi_selection: info.can('select_multiple') }); inited++; fileInputs.push(this); cb(); }; fileInput.onchange = function() { self.addFile(this.files); }; fileInput.bind('mouseenter mouseleave mousedown mouseup', function(e) { if (!disabled) { if (settings.browse_button_hover) { if ('mouseenter' === e.type) { o.addClass(el, settings.browse_button_hover); } else if ('mouseleave' === e.type) { o.removeClass(el, settings.browse_button_hover); } } if (settings.browse_button_active) { if ('mousedown' === e.type) { o.addClass(el, settings.browse_button_active); } else if ('mouseup' === e.type) { o.removeClass(el, settings.browse_button_active); } } } }); fileInput.bind('mousedown', function() { self.trigger('Browse'); }); fileInput.bind('error runtimeerror', function() { fileInput = null; cb(); }); fileInput.init(); }); }); } // initialize drop zones if (settings.drop_element) { plupload.each(settings.drop_element, function(el) { queue.push(function(cb) { var fileDrop = new o.FileDrop(plupload.extend({}, options, { drop_zone: el })); fileDrop.onready = function() { var info = o.Runtime.getInfo(this.ruid); // for backward compatibility o.extend(self.features, { chunks: info.can('slice_blob'), multipart: info.can('send_multipart'), dragdrop: info.can('drag_and_drop') }); inited++; fileDrops.push(this); cb(); }; fileDrop.ondrop = function() { self.addFile(this.files); }; fileDrop.bind('error runtimeerror', function() { fileDrop = null; cb(); }); fileDrop.init(); }); }); } o.inSeries(queue, function() { if (typeof(cb) === 'function') { cb(inited); } }); } function resizeImage(blob, params, cb) { var img = new o.Image(); try { img.onload = function() { // no manipulation required if... if (params.width > this.width && params.height > this.height && params.quality === undef && params.preserve_headers && !params.crop ) { this.destroy(); return cb(blob); } // otherwise downsize img.downsize(params.width, params.height, params.crop, params.preserve_headers); }; img.onresize = function() { cb(this.getAsBlob(blob.type, params.quality)); this.destroy(); }; img.onerror = function() { cb(blob); }; img.load(blob); } catch(ex) { cb(blob); } } function setOption(option, value, init) { var self = this, reinitRequired = false; function _setOption(option, value, init) { var oldValue = settings[option]; switch (option) { case 'max_file_size': if (option === 'max_file_size') { settings.max_file_size = settings.filters.max_file_size = value; } break; case 'chunk_size': if (value = plupload.parseSize(value)) { settings[option] = value; settings.send_file_name = true; } break; case 'multipart': settings[option] = value; if (!value) { settings.send_file_name = true; } break; case 'unique_names': settings[option] = value; if (value) { settings.send_file_name = true; } break; case 'filters': // for sake of backward compatibility if (plupload.typeOf(value) === 'array') { value = { mime_types: value }; } if (init) { plupload.extend(settings.filters, value); } else { settings.filters = value; } // if file format filters are being updated, regenerate the matching expressions if (value.mime_types) { settings.filters.mime_types.regexp = (function(filters) { var extensionsRegExp = []; plupload.each(filters, function(filter) { plupload.each(filter.extensions.split(/,/), function(ext) { if (/^\s*\*\s*$/.test(ext)) { extensionsRegExp.push('\\.*'); } else { extensionsRegExp.push('\\.' + ext.replace(new RegExp('[' + ('/^$.*+?|()[]{}\\'.replace(/./g, '\\$&')) + ']', 'g'), '\\$&')); } }); }); return new RegExp('(' + extensionsRegExp.join('|') + ')$', 'i'); }(settings.filters.mime_types)); } break; case 'resize': if (init) { plupload.extend(settings.resize, value, { enabled: true }); } else { settings.resize = value; } break; case 'prevent_duplicates': settings.prevent_duplicates = settings.filters.prevent_duplicates = !!value; break; // options that require reinitialisation case 'container': case 'browse_button': case 'drop_element': value = 'container' === option ? plupload.get(value) : plupload.getAll(value) ; case 'runtimes': case 'multi_selection': settings[option] = value; if (!init) { reinitRequired = true; } break; default: settings[option] = value; } if (!init) { self.trigger('OptionChanged', option, value, oldValue); } } if (typeof(option) === 'object') { plupload.each(option, function(value, option) { _setOption(option, value, init); }); } else { _setOption(option, value, init); } if (init) { // Normalize the list of required capabilities settings.required_features = normalizeCaps(plupload.extend({}, settings)); // Come up with the list of capabilities that can affect default mode in a multi-mode runtimes preferred_caps = normalizeCaps(plupload.extend({}, settings, { required_features: true })); } else if (reinitRequired) { self.trigger('Destroy'); initControls.call(self, settings, function(inited) { if (inited) { self.runtime = o.Runtime.getInfo(getRUID()).type; self.trigger('Init', { runtime: self.runtime }); self.trigger('PostInit'); } else { self.trigger('Error', { code : plupload.INIT_ERROR, message : plupload.translate('Init error.') }); } }); } } // Internal event handlers function onBeforeUpload(up, file) { // Generate unique target filenames if (up.settings.unique_names) { var matches = file.name.match(/\.([^.]+)$/), ext = "part"; if (matches) { ext = matches[1]; } file.target_name = file.id + '.' + ext; } } function onUploadFile(up, file) { var url = up.settings.url , chunkSize = up.settings.chunk_size , retries = up.settings.max_retries , features = up.features , offset = 0 , blob ; // make sure we start at a predictable offset if (file.loaded) { offset = file.loaded = chunkSize ? chunkSize * Math.floor(file.loaded / chunkSize) : 0; } function handleError() { if (retries-- > 0) { delay(uploadNextChunk, 1000); } else { file.loaded = offset; // reset all progress up.trigger('Error', { code : plupload.HTTP_ERROR, message : plupload.translate('HTTP Error.'), file : file, response : xhr.responseText, status : xhr.status, responseHeaders: xhr.getAllResponseHeaders() }); } } function uploadNextChunk() { var chunkBlob, formData, args = {}, curChunkSize; // make sure that file wasn't cancelled and upload is not stopped in general if (file.status !== plupload.UPLOADING || up.state === plupload.STOPPED) { return; } // send additional 'name' parameter only if required if (up.settings.send_file_name) { args.name = file.target_name || file.name; } if (chunkSize && features.chunks && blob.size > chunkSize) { // blob will be of type string if it was loaded in memory curChunkSize = Math.min(chunkSize, blob.size - offset); chunkBlob = blob.slice(offset, offset + curChunkSize); } else { curChunkSize = blob.size; chunkBlob = blob; } // If chunking is enabled add corresponding args, no matter if file is bigger than chunk or smaller if (chunkSize && features.chunks) { // Setup query string arguments if (up.settings.send_chunk_number) { args.chunk = Math.ceil(offset / chunkSize); args.chunks = Math.ceil(blob.size / chunkSize); } else { // keep support for experimental chunk format, just in case args.offset = offset; args.total = blob.size; } } xhr = new o.XMLHttpRequest(); // Do we have upload progress support if (xhr.upload) { xhr.upload.onprogress = function(e) { file.loaded = Math.min(file.size, offset + e.loaded); up.trigger('UploadProgress', file); }; } xhr.onload = function() { // check if upload made itself through if (xhr.status >= 400) { handleError(); return; } retries = up.settings.max_retries; // reset the counter // Handle chunk response if (curChunkSize < blob.size) { chunkBlob.destroy(); offset += curChunkSize; file.loaded = Math.min(offset, blob.size); up.trigger('ChunkUploaded', file, { offset : file.loaded, total : blob.size, response : xhr.responseText, status : xhr.status, responseHeaders: xhr.getAllResponseHeaders() }); // stock Android browser doesn't fire upload progress events, but in chunking mode we can fake them if (o.Env.browser === 'Android Browser') { // doesn't harm in general, but is not required anywhere else up.trigger('UploadProgress', file); } } else { file.loaded = file.size; } chunkBlob = formData = null; // Free memory // Check if file is uploaded if (!offset || offset >= blob.size) { // If file was modified, destory the copy if (file.size != file.origSize) { blob.destroy(); blob = null; } up.trigger('UploadProgress', file); file.status = plupload.DONE; up.trigger('FileUploaded', file, { response : xhr.responseText, status : xhr.status, responseHeaders: xhr.getAllResponseHeaders() }); } else { // Still chunks left delay(uploadNextChunk, 1); // run detached, otherwise event handlers interfere } }; xhr.onerror = function() { handleError(); }; xhr.onloadend = function() { this.destroy(); xhr = null; }; // Build multipart request if (up.settings.multipart && features.multipart) { xhr.open("post", url, true); // Set custom headers plupload.each(up.settings.headers, function(value, name) { xhr.setRequestHeader(name, value); }); formData = new o.FormData(); // Add multipart params plupload.each(plupload.extend(args, up.settings.multipart_params), function(value, name) { formData.append(name, value); }); // Add file and send it formData.append(up.settings.file_data_name, chunkBlob); xhr.send(formData, { runtime_order: up.settings.runtimes, required_caps: up.settings.required_features, preferred_caps: preferred_caps }); } else { // if no multipart, send as binary stream url = plupload.buildUrl(up.settings.url, plupload.extend(args, up.settings.multipart_params)); xhr.open("post", url, true); xhr.setRequestHeader('Content-Type', 'application/octet-stream'); // Binary stream header // Set custom headers plupload.each(up.settings.headers, function(value, name) { xhr.setRequestHeader(name, value); }); xhr.send(chunkBlob, { runtime_order: up.settings.runtimes, required_caps: up.settings.required_features, preferred_caps: preferred_caps }); } } blob = file.getSource(); // Start uploading chunks if (up.settings.resize.enabled && runtimeCan(blob, 'send_binary_string') && !!~o.inArray(blob.type, ['image/jpeg', 'image/png'])) { // Resize if required resizeImage.call(this, blob, up.settings.resize, function(resizedBlob) { blob = resizedBlob; file.size = resizedBlob.size; uploadNextChunk(); }); } else { uploadNextChunk(); } } function onUploadProgress(up, file) { calcFile(file); } function onStateChanged(up) { if (up.state == plupload.STARTED) { // Get start time to calculate bps startTime = (+new Date()); } else if (up.state == plupload.STOPPED) { // Reset currently uploading files for (var i = up.files.length - 1; i >= 0; i--) { if (up.files[i].status == plupload.UPLOADING) { up.files[i].status = plupload.QUEUED; calc(); } } } } function onCancelUpload() { if (xhr) { xhr.abort(); } } function onFileUploaded(up) { calc(); // Upload next file but detach it from the error event // since other custom listeners might want to stop the queue delay(function() { uploadNext.call(up); }, 1); } function onError(up, err) { if (err.code === plupload.INIT_ERROR) { up.destroy(); } // Set failed status if an error occured on a file else if (err.code === plupload.HTTP_ERROR) { err.file.status = plupload.FAILED; calcFile(err.file); // Upload next file but detach it from the error event // since other custom listeners might want to stop the queue if (up.state == plupload.STARTED) { // upload in progress up.trigger('CancelUpload'); delay(function() { uploadNext.call(up); }, 1); } } } function onDestroy(up) { up.stop(); // Purge the queue plupload.each(files, function(file) { file.destroy(); }); files = []; if (fileInputs.length) { plupload.each(fileInputs, function(fileInput) { fileInput.destroy(); }); fileInputs = []; } if (fileDrops.length) { plupload.each(fileDrops, function(fileDrop) { fileDrop.destroy(); }); fileDrops = []; } preferred_caps = {}; disabled = false; startTime = xhr = null; total.reset(); } // Default settings settings = { runtimes: o.Runtime.order, max_retries: 0, chunk_size: 0, multipart: true, multi_selection: true, file_data_name: 'file', filters: { mime_types: [], prevent_duplicates: false, max_file_size: 0 }, resize: { enabled: false, preserve_headers: true, crop: false }, send_file_name: true, send_chunk_number: true }; setOption.call(this, options, null, true); // Inital total state total = new plupload.QueueProgress(); // Add public methods plupload.extend(this, { /** * Unique id for the Uploader instance. * * @property id * @type String */ id : uid, uid : uid, // mOxie uses this to differentiate between event targets /** * Current state of the total uploading progress. This one can either be plupload.STARTED or plupload.STOPPED. * These states are controlled by the stop/start methods. The default value is STOPPED. * * @property state * @type Number */ state : plupload.STOPPED, /** * Map of features that are available for the uploader runtime. Features will be filled * before the init event is called, these features can then be used to alter the UI for the end user. * Some of the current features that might be in this map is: dragdrop, chunks, jpgresize, pngresize. * * @property features * @type Object */ features : {}, /** * Current runtime name. * * @property runtime * @type String */ runtime : null, /** * Current upload queue, an array of File instances. * * @property files * @type Array * @see plupload.File */ files : files, /** * Object with name/value settings. * * @property settings * @type Object */ settings : settings, /** * Total progess information. How many files has been uploaded, total percent etc. * * @property total * @type plupload.QueueProgress */ total : total, /** * Initializes the Uploader instance and adds internal event listeners. * * @method init */ init : function() { var self = this, opt, preinitOpt, err; preinitOpt = self.getOption('preinit'); if (typeof(preinitOpt) == "function") { preinitOpt(self); } else { plupload.each(preinitOpt, function(func, name) { self.bind(name, func); }); } bindEventListeners.call(self); // Check for required options plupload.each(['container', 'browse_button', 'drop_element'], function(el) { if (self.getOption(el) === null) { err = { code : plupload.INIT_ERROR, message : plupload.translate("'%' specified, but cannot be found.") } return false; } }); if (err) { return self.trigger('Error', err); } if (!settings.browse_button && !settings.drop_element) { return self.trigger('Error', { code : plupload.INIT_ERROR, message : plupload.translate("You must specify either 'browse_button' or 'drop_element'.") }); } initControls.call(self, settings, function(inited) { var initOpt = self.getOption('init'); if (typeof(initOpt) == "function") { initOpt(self); } else { plupload.each(initOpt, function(func, name) { self.bind(name, func); }); } if (inited) { self.runtime = o.Runtime.getInfo(getRUID()).type; self.trigger('Init', { runtime: self.runtime }); self.trigger('PostInit'); } else { self.trigger('Error', { code : plupload.INIT_ERROR, message : plupload.translate('Init error.') }); } }); }, /** * Set the value for the specified option(s). * * @method setOption * @since 2.1 * @param {String|Object} option Name of the option to change or the set of key/value pairs * @param {Mixed} [value] Value for the option (is ignored, if first argument is object) */ setOption: function(option, value) { setOption.call(this, option, value, !this.runtime); // until runtime not set we do not need to reinitialize }, /** * Get the value for the specified option or the whole configuration, if not specified. * * @method getOption * @since 2.1 * @param {String} [option] Name of the option to get * @return {Mixed} Value for the option or the whole set */ getOption: function(option) { if (!option) { return settings; } return settings[option]; }, /** * Refreshes the upload instance by dispatching out a refresh event to all runtimes. * This would for example reposition flash/silverlight shims on the page. * * @method refresh */ refresh : function() { if (fileInputs.length) { plupload.each(fileInputs, function(fileInput) { fileInput.trigger('Refresh'); }); } this.trigger('Refresh'); }, /** * Starts uploading the queued files. * * @method start */ start : function() { if (this.state != plupload.STARTED) { this.state = plupload.STARTED; this.trigger('StateChanged'); uploadNext.call(this); } }, /** * Stops the upload of the queued files. * * @method stop */ stop : function() { if (this.state != plupload.STOPPED) { this.state = plupload.STOPPED; this.trigger('StateChanged'); this.trigger('CancelUpload'); } }, /** * Disables/enables browse button on request. * * @method disableBrowse * @param {Boolean} disable Whether to disable or enable (default: true) */ disableBrowse : function() { disabled = arguments[0] !== undef ? arguments[0] : true; if (fileInputs.length) { plupload.each(fileInputs, function(fileInput) { fileInput.disable(disabled); }); } this.trigger('DisableBrowse', disabled); }, /** * Returns the specified file object by id. * * @method getFile * @param {String} id File id to look for. * @return {plupload.File} File object or undefined if it wasn't found; */ getFile : function(id) { var i; for (i = files.length - 1; i >= 0; i--) { if (files[i].id === id) { return files[i]; } } }, /** * Adds file to the queue programmatically. Can be native file, instance of Plupload.File, * instance of mOxie.File, input[type="file"] element, or array of these. Fires FilesAdded, * if any files were added to the queue. Otherwise nothing happens. * * @method addFile * @since 2.0 * @param {plupload.File|mOxie.File|File|Node|Array} file File or files to add to the queue. * @param {String} [fileName] If specified, will be used as a name for the file */ addFile : function(file, fileName) { var self = this , queue = [] , filesAdded = [] , ruid ; function filterFile(file, cb) { var queue = []; o.each(self.settings.filters, function(rule, name) { if (fileFilters[name]) { queue.push(function(cb) { fileFilters[name].call(self, rule, file, function(res) { cb(!res); }); }); } }); o.inSeries(queue, cb); } /** * @method resolveFile * @private * @param {o.File|o.Blob|plupload.File|File|Blob|input[type="file"]} file */ function resolveFile(file) { var type = o.typeOf(file); // o.File if (file instanceof o.File) { if (!file.ruid && !file.isDetached()) { if (!ruid) { // weird case return false; } file.ruid = ruid; file.connectRuntime(ruid); } resolveFile(new plupload.File(file)); } // o.Blob else if (file instanceof o.Blob) { resolveFile(file.getSource()); file.destroy(); } // plupload.File - final step for other branches else if (file instanceof plupload.File) { if (fileName) { file.name = fileName; } queue.push(function(cb) { // run through the internal and user-defined filters, if any filterFile(file, function(err) { if (!err) { // make files available for the filters by updating the main queue directly files.push(file); // collect the files that will be passed to FilesAdded event filesAdded.push(file); self.trigger("FileFiltered", file); } delay(cb, 1); // do not build up recursions or eventually we might hit the limits }); }); } // native File or blob else if (o.inArray(type, ['file', 'blob']) !== -1) { resolveFile(new o.File(null, file)); } // input[type="file"] else if (type === 'node' && o.typeOf(file.files) === 'filelist') { // if we are dealing with input[type="file"] o.each(file.files, resolveFile); } // mixed array of any supported types (see above) else if (type === 'array') { fileName = null; // should never happen, but unset anyway to avoid funny situations o.each(file, resolveFile); } } ruid = getRUID(); resolveFile(file); if (queue.length) { o.inSeries(queue, function() { // if any files left after filtration, trigger FilesAdded if (filesAdded.length) { self.trigger("FilesAdded", filesAdded); } }); } }, /** * Removes a specific file. * * @method removeFile * @param {plupload.File|String} file File to remove from queue. */ removeFile : function(file) { var id = typeof(file) === 'string' ? file : file.id; for (var i = files.length - 1; i >= 0; i--) { if (files[i].id === id) { return this.splice(i, 1)[0]; } } }, /** * Removes part of the queue and returns the files removed. This will also trigger the FilesRemoved and QueueChanged events. * * @method splice * @param {Number} start (Optional) Start index to remove from. * @param {Number} length (Optional) Lengh of items to remove. * @return {Array} Array of files that was removed. */ splice : function(start, length) { // Splice and trigger events var removed = files.splice(start === undef ? 0 : start, length === undef ? files.length : length); // if upload is in progress we need to stop it and restart after files are removed var restartRequired = false; if (this.state == plupload.STARTED) { // upload in progress plupload.each(removed, function(file) { if (file.status === plupload.UPLOADING) { restartRequired = true; // do not restart, unless file that is being removed is uploading return false; } }); if (restartRequired) { this.stop(); } } this.trigger("FilesRemoved", removed); // Dispose any resources allocated by those files plupload.each(removed, function(file) { file.destroy(); }); if (restartRequired) { this.start(); } return removed; }, /** Dispatches the specified event name and its arguments to all listeners. @method trigger @param {String} name Event name to fire. @param {Object..} Multiple arguments to pass along to the listener functions. */ // override the parent method to match Plupload-like event logic dispatchEvent: function(type) { var list, args, result; type = type.toLowerCase(); list = this.hasEventListener(type); if (list) { // sort event list by priority list.sort(function(a, b) { return b.priority - a.priority; }); // first argument should be current plupload.Uploader instance args = [].slice.call(arguments); args.shift(); args.unshift(this); for (var i = 0; i < list.length; i++) { // Fire event, break chain if false is returned if (list[i].fn.apply(list[i].scope, args) === false) { return false; } } } return true; }, /** Check whether uploader has any listeners to the specified event. @method hasEventListener @param {String} name Event name to check for. */ /** Adds an event listener by name. @method bind @param {String} name Event name to listen for. @param {function} fn Function to call ones the event gets fired. @param {Object} [scope] Optional scope to execute the specified function in. @param {Number} [priority=0] Priority of the event handler - handlers with higher priorities will be called first */ bind: function(name, fn, scope, priority) { // adapt moxie EventTarget style to Plupload-like plupload.Uploader.prototype.bind.call(this, name, fn, priority, scope); }, /** Removes the specified event listener. @method unbind @param {String} name Name of event to remove. @param {function} fn Function to remove from listener. */ /** Removes all event listeners. @method unbindAll */ /** * Destroys Plupload instance and cleans after itself. * * @method destroy */ destroy : function() { this.trigger('Destroy'); settings = total = null; // purge these exclusively this.unbindAll(); } }); }; plupload.Uploader.prototype = o.EventTarget.instance; /** * Constructs a new file instance. * * @class File * @constructor * * @param {Object} file Object containing file properties * @param {String} file.name Name of the file. * @param {Number} file.size File size. */ plupload.File = (function() { var filepool = {}; function PluploadFile(file) { plupload.extend(this, { /** * File id this is a globally unique id for the specific file. * * @property id * @type String */ id: plupload.guid(), /** * File name for example "myfile.gif". * * @property name * @type String */ name: file.name || file.fileName, /** * File type, `e.g image/jpeg` * * @property type * @type String */ type: file.type || '', /** * File size in bytes (may change after client-side manupilation). * * @property size * @type Number */ size: file.size || file.fileSize, /** * Original file size in bytes. * * @property origSize * @type Number */ origSize: file.size || file.fileSize, /** * Number of bytes uploaded of the files total size. * * @property loaded * @type Number */ loaded: 0, /** * Number of percentage uploaded of the file. * * @property percent * @type Number */ percent: 0, /** * Status constant matching the plupload states QUEUED, UPLOADING, FAILED, DONE. * * @property status * @type Number * @see plupload */ status: plupload.QUEUED, /** * Date of last modification. * * @property lastModifiedDate * @type {String} */ lastModifiedDate: file.lastModifiedDate || (new Date()).toLocaleString(), // Thu Aug 23 2012 19:40:00 GMT+0400 (GET) /** * Returns native window.File object, when it's available. * * @method getNative * @return {window.File} or null, if plupload.File is of different origin */ getNative: function() { var file = this.getSource().getSource(); return o.inArray(o.typeOf(file), ['blob', 'file']) !== -1 ? file : null; }, /** * Returns mOxie.File - unified wrapper object that can be used across runtimes. * * @method getSource * @return {mOxie.File} or null */ getSource: function() { if (!filepool[this.id]) { return null; } return filepool[this.id]; }, /** * Destroys plupload.File object. * * @method destroy */ destroy: function() { var src = this.getSource(); if (src) { src.destroy(); delete filepool[this.id]; } } }); filepool[this.id] = file; } return PluploadFile; }()); /** * Constructs a queue progress. * * @class QueueProgress * @constructor */ plupload.QueueProgress = function() { var self = this; // Setup alias for self to reduce code size when it's compressed /** * Total queue file size. * * @property size * @type Number */ self.size = 0; /** * Total bytes uploaded. * * @property loaded * @type Number */ self.loaded = 0; /** * Number of files uploaded. * * @property uploaded * @type Number */ self.uploaded = 0; /** * Number of files failed to upload. * * @property failed * @type Number */ self.failed = 0; /** * Number of files yet to be uploaded. * * @property queued * @type Number */ self.queued = 0; /** * Total percent of the uploaded bytes. * * @property percent * @type Number */ self.percent = 0; /** * Bytes uploaded per second. * * @property bytesPerSec * @type Number */ self.bytesPerSec = 0; /** * Resets the progress to its initial values. * * @method reset */ self.reset = function() { self.size = self.loaded = self.uploaded = self.failed = self.queued = self.percent = self.bytesPerSec = 0; }; }; window.plupload = plupload; }(window, mOxie)); plupload/license.txt000064400000043103147573120640010561 0ustar00 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. customize-selective-refresh.min.js000064400000024707147573120640013346 0ustar00/*! This file is auto-generated */ wp.customize.selectiveRefresh=function(o,r){"use strict";var t,s,c={ready:o.Deferred(),editShortcutVisibility:new r.Value,data:{partials:{},renderQueryVar:"",l10n:{shiftClickToEdit:""}},currentRequest:null};return _.extend(c,r.Events),t=c.Partial=r.Class.extend({id:null,defaults:{selector:null,primarySetting:null,containerInclusive:!1,fallbackRefresh:!0},initialize:function(e,t){var n=this;t=t||{},n.id=e,n.params=_.extend({settings:[]},n.defaults,t.params||t),n.deferred={},n.deferred.ready=o.Deferred(),n.deferred.ready.done(function(){n.ready()})},ready:function(){var n=this;_.each(n.placements(),function(e){o(e.container).attr("title",c.data.l10n.shiftClickToEdit),n.createEditShortcutForPlacement(e)}),o(document).on("click",n.params.selector,function(t){t.shiftKey&&(t.preventDefault(),_.each(n.placements(),function(e){o(e.container).is(t.currentTarget)&&n.showControl()}))})},createEditShortcutForPlacement:function(e){var t,n=this;!e.container||!(t=o(e.container)).length||t.is("area, audio, base, bdi, bdo, br, button, canvas, col, colgroup, command, datalist, embed, head, hr, html, iframe, img, input, keygen, label, link, map, math, menu, meta, noscript, object, optgroup, option, param, progress, rp, rt, ruby, script, select, source, style, svg, table, tbody, textarea, tfoot, thead, title, tr, track, video, wbr")||t.closest("head").length||((t=n.createEditShortcut()).on("click",function(e){e.preventDefault(),e.stopPropagation(),n.showControl()}),n.addEditShortcutToPlacement(e,t))},addEditShortcutToPlacement:function(e,t){e=o(e.container);e.prepend(t),e.is(":visible")&&"none"!==e.css("display")||t.addClass("customize-partial-edit-shortcut-hidden")},getEditShortcutClassName:function(){return"customize-partial-edit-shortcut-"+this.id.replace(/]/g,"").replace(/\[/g,"-")},getEditShortcutTitle:function(){var e=c.data.l10n;switch(this.getType()){case"widget":return e.clickEditWidget;case"blogname":case"blogdescription":return e.clickEditTitle;case"nav_menu":return e.clickEditMenu;default:return e.clickEditMisc}},getType:function(){var e=this,t=e.params.primarySetting||_.first(e.settings())||"unknown";return e.params.type||(t.match(/^nav_menu_instance\[/)?"nav_menu":t.match(/^widget_.+\[\d+]$/)?"widget":t)},createEditShortcut:function(){var e=this.getEditShortcutTitle(),t=o("",{class:"customize-partial-edit-shortcut "+this.getEditShortcutClassName()}),e=o("
    "); jQuery("#TB_closeWindowButton").on( 'click', tb_remove ); if (!(TB_PrevHTML === "")) { function goPrev(){ if(jQuery(document).off("click",goPrev)){jQuery(document).off("click",goPrev);} jQuery("#TB_window").remove(); jQuery("body").append("
    "); tb_show(TB_PrevCaption, TB_PrevURL, imageGroup); return false; } jQuery("#TB_prev").on( 'click', goPrev ); } if (!(TB_NextHTML === "")) { function goNext(){ jQuery("#TB_window").remove(); jQuery("body").append("
    "); tb_show(TB_NextCaption, TB_NextURL, imageGroup); return false; } jQuery("#TB_next").on( 'click', goNext ); } jQuery(document).on('keydown.thickbox', function(e){ if ( e.which == 27 ){ // close tb_remove(); } else if ( e.which == 190 ){ // display previous image if(!(TB_NextHTML == "")){ jQuery(document).off('thickbox'); goNext(); } } else if ( e.which == 188 ){ // display next image if(!(TB_PrevHTML == "")){ jQuery(document).off('thickbox'); goPrev(); } } return false; }); tb_position(); jQuery("#TB_load").remove(); jQuery("#TB_ImageOff").on( 'click', tb_remove ); jQuery("#TB_window").css({'visibility':'visible'}); //for safari using css instead of show }; imgPreloader.src = url; }else{//code to show html var queryString = url.replace(/^[^\?]+\??/,''); var params = tb_parseQuery( queryString ); TB_WIDTH = (params['width']*1) + 30 || 630; //defaults to 630 if no parameters were added to URL TB_HEIGHT = (params['height']*1) + 40 || 440; //defaults to 440 if no parameters were added to URL ajaxContentW = TB_WIDTH - 30; ajaxContentH = TB_HEIGHT - 45; if(url.indexOf('TB_iframe') != -1){// either iframe or ajax window urlNoQuery = url.split('TB_'); jQuery("#TB_iframeContent").remove(); if(params['modal'] != "true"){//iframe no modal jQuery("#TB_window").append("
    "+caption+"
    "); }else{//iframe modal jQuery("#TB_overlay").off(); jQuery("#TB_window").append(""); } }else{// not an iframe, ajax if(jQuery("#TB_window").css("visibility") != "visible"){ if(params['modal'] != "true"){//ajax no modal jQuery("#TB_window").append("
    "+caption+"
    "); }else{//ajax modal jQuery("#TB_overlay").off(); jQuery("#TB_window").append("
    "); } }else{//this means the window is already up, we are just loading new content via ajax jQuery("#TB_ajaxContent")[0].style.width = ajaxContentW +"px"; jQuery("#TB_ajaxContent")[0].style.height = ajaxContentH +"px"; jQuery("#TB_ajaxContent")[0].scrollTop = 0; jQuery("#TB_ajaxWindowTitle").html(caption); } } jQuery("#TB_closeWindowButton").on( 'click', tb_remove ); if(url.indexOf('TB_inline') != -1){ jQuery("#TB_ajaxContent").append(jQuery('#' + params['inlineId']).children()); jQuery("#TB_window").on('tb_unload', function () { jQuery('#' + params['inlineId']).append( jQuery("#TB_ajaxContent").children() ); // move elements back when you're finished }); tb_position(); jQuery("#TB_load").remove(); jQuery("#TB_window").css({'visibility':'visible'}); }else if(url.indexOf('TB_iframe') != -1){ tb_position(); jQuery("#TB_load").remove(); jQuery("#TB_window").css({'visibility':'visible'}); }else{ var load_url = url; load_url += -1 === url.indexOf('?') ? '?' : '&'; jQuery("#TB_ajaxContent").load(load_url += "random=" + (new Date().getTime()),function(){//to do a post change this load method tb_position(); jQuery("#TB_load").remove(); tb_init("#TB_ajaxContent a.thickbox"); jQuery("#TB_window").css({'visibility':'visible'}); }); } } if(!params['modal']){ jQuery(document).on('keydown.thickbox', function(e){ if ( e.which == 27 ){ // close tb_remove(); return false; } }); } $closeBtn = jQuery( '#TB_closeWindowButton' ); /* * If the native Close button icon is visible, move focus on the button * (e.g. in the Network Admin Themes screen). * In other admin screens is hidden and replaced by a different icon. */ if ( $closeBtn.find( '.tb-close-icon' ).is( ':visible' ) ) { $closeBtn.trigger( 'focus' ); } } catch(e) { //nothing here } } //helper functions below function tb_showIframe(){ jQuery("#TB_load").remove(); jQuery("#TB_window").css({'visibility':'visible'}).trigger( 'thickbox:iframe:loaded' ); } function tb_remove() { jQuery("#TB_imageOff").off("click"); jQuery("#TB_closeWindowButton").off("click"); jQuery( '#TB_window' ).fadeOut( 'fast', function() { jQuery( '#TB_window, #TB_overlay, #TB_HideSelect' ).trigger( 'tb_unload' ).off().remove(); jQuery( 'body' ).trigger( 'thickbox:removed' ); }); jQuery( 'body' ).removeClass( 'modal-open' ); jQuery("#TB_load").remove(); if (typeof document.body.style.maxHeight == "undefined") {//if IE 6 jQuery("body","html").css({height: "auto", width: "auto"}); jQuery("html").css("overflow",""); } jQuery(document).off('.thickbox'); return false; } function tb_position() { var isIE6 = typeof document.body.style.maxHeight === "undefined"; jQuery("#TB_window").css({marginLeft: '-' + parseInt((TB_WIDTH / 2),10) + 'px', width: TB_WIDTH + 'px'}); if ( ! isIE6 ) { // take away IE6 jQuery("#TB_window").css({marginTop: '-' + parseInt((TB_HEIGHT / 2),10) + 'px'}); } } function tb_parseQuery ( query ) { var Params = {}; if ( ! query ) {return Params;}// return empty object var Pairs = query.split(/[;&]/); for ( var i = 0; i < Pairs.length; i++ ) { var KeyVal = Pairs[i].split('='); if ( ! KeyVal || KeyVal.length != 2 ) {continue;} var key = unescape( KeyVal[0] ); var val = unescape( KeyVal[1] ); val = val.replace(/\+/g, ' '); Params[key] = val; } return Params; } function tb_getPageSize(){ var de = document.documentElement; var w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth; var h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight; arrayPageSize = [w,h]; return arrayPageSize; } function tb_detectMacXFF() { var userAgent = navigator.userAgent.toLowerCase(); if (userAgent.indexOf('mac') != -1 && userAgent.indexOf('firefox')!=-1) { return true; } } thickbox/macFFBgHack.png000064400000000136147573120640011112 0ustar00PNG  IHDRc%IDATH! _jM H$D"H_,!ZIENDB`admin-bar.min.js000064400000006637147573120640007543 0ustar00/*! This file is auto-generated */ !function(c,l,u){function d(e){27===e.which&&(e=E(e.target,".menupop"))&&(e.querySelector(".menupop > .ab-item").focus(),y(e,"hover"))}function p(e){var t;13!==e.which||e.ctrlKey||e.shiftKey||E(e.target,".ab-sub-wrapper")||(t=E(e.target,".menupop"))&&(e.preventDefault(),(a(t,"hover")?y:v)(t,"hover"))}function m(e,t){!E(t.target,".ab-sub-wrapper")&&(t.preventDefault(),t=E(t.target,".menupop"))&&(a(t,"hover")?y:(b(e),v))(t,"hover")}function f(e){var t,r=e.target.parentNode;if(t=r?r.querySelector(".shortlink-input"):t)return e.preventDefault&&e.preventDefault(),e.returnValue=!1,v(r,"selected"),t.focus(),t.select(),!(t.onblur=function(){y(r,"selected")})}function h(){if("sessionStorage"in l)try{for(var e in sessionStorage)-1
    '),findPosts.overlay()),i.show(),n&&e&&t("#affected").attr("name",n).val(e),t("#find-posts").show(),t("#find-posts-input").trigger("focus").on("keyup",function(n){27==n.which&&findPosts.close()}),findPosts.send(),!1},close:function(){t("#find-posts-response").empty(),t("#find-posts").hide(),t(".ui-find-overlay").hide()},overlay:function(){t(".ui-find-overlay").on("click",function(){findPosts.close()})},send:function(){var n={ps:t("#find-posts-input").val(),action:"find_posts",_ajax_nonce:t("#_ajax_nonce").val()},e=t(".find-box-search .spinner");e.addClass("is-active"),t.ajax(ajaxurl,{type:"POST",data:n,dataType:"json"}).always(function(){e.removeClass("is-active")}).done(function(n){n.success||t("#find-posts-response").text(wp.i18n.__("An error has occurred. Please reload the page and try again.")),t("#find-posts-response").html(n.data)}).fail(function(){t("#find-posts-response").text(wp.i18n.__("An error has occurred. Please reload the page and try again."))})}},t(function(){var o,n,e=t("#wp-media-grid"),i=new ClipboardJS(".copy-attachment-url.media-library"),s=null;e.length&&window.wp&&window.wp.media&&(n=_wpMediaGridSettings,n=window.wp.media({frame:"manage",container:e,library:n.queryVars}).open(),e.trigger("wp-media-grid-ready",n)),t("#find-posts-submit").on("click",function(n){t('#find-posts-response input[type="radio"]:checked').length||n.preventDefault()}),t("#find-posts .find-box-search :input").on("keypress",function(n){if(13==n.which)return findPosts.send(),!1}),t("#find-posts-search").on("click",findPosts.send),t("#find-posts-close").on("click",findPosts.close),t("#doaction").on("click",function(e){t('select[name="action"]').each(function(){var n=t(this).val();"attach"===n?(e.preventDefault(),findPosts.open()):"delete"!==n||showNotice.warn()||e.preventDefault()})}),t(".find-box-inside").on("click","tr",function(){t(this).find(".found-radio input").prop("checked",!0)}),i.on("success",function(n){var e=t(n.trigger),i=t(".success",e.closest(".copy-to-clipboard-container"));n.clearSelection(),s&&s.addClass("hidden"),clearTimeout(o),i.removeClass("hidden"),o=setTimeout(function(){i.addClass("hidden"),s=null},3e3),s=i,wp.a11y.speak(wp.i18n.__("The file URL has been copied to your clipboard"))})})}(jQuery);post.js000064400000115267147573140730006116 0ustar00/** * @file Contains all dynamic functionality needed on post and term pages. * * @output wp-admin/js/post.js */ /* global ajaxurl, wpAjax, postboxes, pagenow, tinymce, alert, deleteUserSetting, ClipboardJS */ /* global theList:true, theExtraList:true, getUserSetting, setUserSetting, commentReply, commentsBox */ /* global WPSetThumbnailHTML, wptitlehint */ // Backward compatibility: prevent fatal errors. window.makeSlugeditClickable = window.editPermalink = function(){}; // Make sure the wp object exists. window.wp = window.wp || {}; ( function( $ ) { var titleHasFocus = false, __ = wp.i18n.__; /** * Control loading of comments on the post and term edit pages. * * @type {{st: number, get: commentsBox.get, load: commentsBox.load}} * * @namespace commentsBox */ window.commentsBox = { // Comment offset to use when fetching new comments. st : 0, /** * Fetch comments using Ajax and display them in the box. * * @memberof commentsBox * * @param {number} total Total number of comments for this post. * @param {number} num Optional. Number of comments to fetch, defaults to 20. * @return {boolean} Always returns false. */ get : function(total, num) { var st = this.st, data; if ( ! num ) num = 20; this.st += num; this.total = total; $( '#commentsdiv .spinner' ).addClass( 'is-active' ); data = { 'action' : 'get-comments', 'mode' : 'single', '_ajax_nonce' : $('#add_comment_nonce').val(), 'p' : $('#post_ID').val(), 'start' : st, 'number' : num }; $.post( ajaxurl, data, function(r) { r = wpAjax.parseAjaxResponse(r); $('#commentsdiv .widefat').show(); $( '#commentsdiv .spinner' ).removeClass( 'is-active' ); if ( 'object' == typeof r && r.responses[0] ) { $('#the-comment-list').append( r.responses[0].data ); theList = theExtraList = null; $( 'a[className*=\':\']' ).off(); // If the offset is over the total number of comments we cannot fetch any more, so hide the button. if ( commentsBox.st > commentsBox.total ) $('#show-comments').hide(); else $('#show-comments').show().children('a').text( __( 'Show more comments' ) ); return; } else if ( 1 == r ) { $('#show-comments').text( __( 'No more comments found.' ) ); return; } $('#the-comment-list').append(''+wpAjax.broken+''); } ); return false; }, /** * Load the next batch of comments. * * @memberof commentsBox * * @param {number} total Total number of comments to load. */ load: function(total){ this.st = jQuery('#the-comment-list tr.comment:visible').length; this.get(total); } }; /** * Overwrite the content of the Featured Image postbox * * @param {string} html New HTML to be displayed in the content area of the postbox. * * @global */ window.WPSetThumbnailHTML = function(html){ $('.inside', '#postimagediv').html(html); }; /** * Set the Image ID of the Featured Image * * @param {number} id The post_id of the image to use as Featured Image. * * @global */ window.WPSetThumbnailID = function(id){ var field = $('input[value="_thumbnail_id"]', '#list-table'); if ( field.length > 0 ) { $('#meta\\[' + field.attr('id').match(/[0-9]+/) + '\\]\\[value\\]').text(id); } }; /** * Remove the Featured Image * * @param {string} nonce Nonce to use in the request. * * @global */ window.WPRemoveThumbnail = function(nonce){ $.post( ajaxurl, { action: 'set-post-thumbnail', post_id: $( '#post_ID' ).val(), thumbnail_id: -1, _ajax_nonce: nonce, cookie: encodeURIComponent( document.cookie ) }, /** * Handle server response * * @param {string} str Response, will be '0' when an error occurred otherwise contains link to add Featured Image. */ function(str){ if ( str == '0' ) { alert( __( 'Could not set that as the thumbnail image. Try a different attachment.' ) ); } else { WPSetThumbnailHTML(str); } } ); }; /** * Heartbeat locks. * * Used to lock editing of an object by only one user at a time. * * When the user does not send a heartbeat in a heartbeat-time * the user is no longer editing and another user can start editing. */ $(document).on( 'heartbeat-send.refresh-lock', function( e, data ) { var lock = $('#active_post_lock').val(), post_id = $('#post_ID').val(), send = {}; if ( ! post_id || ! $('#post-lock-dialog').length ) return; send.post_id = post_id; if ( lock ) send.lock = lock; data['wp-refresh-post-lock'] = send; }).on( 'heartbeat-tick.refresh-lock', function( e, data ) { // Post locks: update the lock string or show the dialog if somebody has taken over editing. var received, wrap, avatar; if ( data['wp-refresh-post-lock'] ) { received = data['wp-refresh-post-lock']; if ( received.lock_error ) { // Show "editing taken over" message. wrap = $('#post-lock-dialog'); if ( wrap.length && ! wrap.is(':visible') ) { if ( wp.autosave ) { // Save the latest changes and disable. $(document).one( 'heartbeat-tick', function() { wp.autosave.server.suspend(); wrap.removeClass('saving').addClass('saved'); $(window).off( 'beforeunload.edit-post' ); }); wrap.addClass('saving'); wp.autosave.server.triggerSave(); } if ( received.lock_error.avatar_src ) { avatar = $( '', { 'class': 'avatar avatar-64 photo', width: 64, height: 64, alt: '', src: received.lock_error.avatar_src, srcset: received.lock_error.avatar_src_2x ? received.lock_error.avatar_src_2x + ' 2x' : undefined } ); wrap.find('div.post-locked-avatar').empty().append( avatar ); } wrap.show().find('.currently-editing').text( received.lock_error.text ); wrap.find('.wp-tab-first').trigger( 'focus' ); } } else if ( received.new_lock ) { $('#active_post_lock').val( received.new_lock ); } } }).on( 'before-autosave.update-post-slug', function() { titleHasFocus = document.activeElement && document.activeElement.id === 'title'; }).on( 'after-autosave.update-post-slug', function() { /* * Create slug area only if not already there * and the title field was not focused (user was not typing a title) when autosave ran. */ if ( ! $('#edit-slug-box > *').length && ! titleHasFocus ) { $.post( ajaxurl, { action: 'sample-permalink', post_id: $('#post_ID').val(), new_title: $('#title').val(), samplepermalinknonce: $('#samplepermalinknonce').val() }, function( data ) { if ( data != '-1' ) { $('#edit-slug-box').html(data); } } ); } }); }(jQuery)); /** * Heartbeat refresh nonces. */ (function($) { var check, timeout; /** * Only allow to check for nonce refresh every 30 seconds. */ function schedule() { check = false; window.clearTimeout( timeout ); timeout = window.setTimeout( function(){ check = true; }, 300000 ); } $( function() { schedule(); }).on( 'heartbeat-send.wp-refresh-nonces', function( e, data ) { var post_id, $authCheck = $('#wp-auth-check-wrap'); if ( check || ( $authCheck.length && ! $authCheck.hasClass( 'hidden' ) ) ) { if ( ( post_id = $('#post_ID').val() ) && $('#_wpnonce').val() ) { data['wp-refresh-post-nonces'] = { post_id: post_id }; } } }).on( 'heartbeat-tick.wp-refresh-nonces', function( e, data ) { var nonces = data['wp-refresh-post-nonces']; if ( nonces ) { schedule(); if ( nonces.replace ) { $.each( nonces.replace, function( selector, value ) { $( '#' + selector ).val( value ); }); } if ( nonces.heartbeatNonce ) window.heartbeatSettings.nonce = nonces.heartbeatNonce; } }); }(jQuery)); /** * All post and postbox controls and functionality. */ jQuery( function($) { var stamp, visibility, $submitButtons, updateVisibility, updateText, $textarea = $('#content'), $document = $(document), postId = $('#post_ID').val() || 0, $submitpost = $('#submitpost'), releaseLock = true, $postVisibilitySelect = $('#post-visibility-select'), $timestampdiv = $('#timestampdiv'), $postStatusSelect = $('#post-status-select'), isMac = window.navigator.platform ? window.navigator.platform.indexOf( 'Mac' ) !== -1 : false, copyAttachmentURLClipboard = new ClipboardJS( '.copy-attachment-url.edit-media' ), copyAttachmentURLSuccessTimeout, __ = wp.i18n.__, _x = wp.i18n._x; postboxes.add_postbox_toggles(pagenow); /* * Clear the window name. Otherwise if this is a former preview window where the user navigated to edit another post, * and the first post is still being edited, clicking Preview there will use this window to show the preview. */ window.name = ''; // Post locks: contain focus inside the dialog. If the dialog is shown, focus the first item. $('#post-lock-dialog .notification-dialog').on( 'keydown', function(e) { // Don't do anything when [Tab] is pressed. if ( e.which != 9 ) return; var target = $(e.target); // [Shift] + [Tab] on first tab cycles back to last tab. if ( target.hasClass('wp-tab-first') && e.shiftKey ) { $(this).find('.wp-tab-last').trigger( 'focus' ); e.preventDefault(); // [Tab] on last tab cycles back to first tab. } else if ( target.hasClass('wp-tab-last') && ! e.shiftKey ) { $(this).find('.wp-tab-first').trigger( 'focus' ); e.preventDefault(); } }).filter(':visible').find('.wp-tab-first').trigger( 'focus' ); // Set the heartbeat interval to 10 seconds if post lock dialogs are enabled. if ( wp.heartbeat && $('#post-lock-dialog').length ) { wp.heartbeat.interval( 10 ); } // The form is being submitted by the user. $submitButtons = $submitpost.find( ':submit, a.submitdelete, #post-preview' ).on( 'click.edit-post', function( event ) { var $button = $(this); if ( $button.hasClass('disabled') ) { event.preventDefault(); return; } if ( $button.hasClass('submitdelete') || $button.is( '#post-preview' ) ) { return; } // The form submission can be blocked from JS or by using HTML 5.0 validation on some fields. // Run this only on an actual 'submit'. $('form#post').off( 'submit.edit-post' ).on( 'submit.edit-post', function( event ) { if ( event.isDefaultPrevented() ) { return; } // Stop auto save. if ( wp.autosave ) { wp.autosave.server.suspend(); } if ( typeof commentReply !== 'undefined' ) { /* * Warn the user they have an unsaved comment before submitting * the post data for update. */ if ( ! commentReply.discardCommentChanges() ) { return false; } /* * Close the comment edit/reply form if open to stop the form * action from interfering with the post's form action. */ commentReply.close(); } releaseLock = false; $(window).off( 'beforeunload.edit-post' ); $submitButtons.addClass( 'disabled' ); if ( $button.attr('id') === 'publish' ) { $submitpost.find( '#major-publishing-actions .spinner' ).addClass( 'is-active' ); } else { $submitpost.find( '#minor-publishing .spinner' ).addClass( 'is-active' ); } }); }); // Submit the form saving a draft or an autosave, and show a preview in a new tab. $('#post-preview').on( 'click.post-preview', function( event ) { var $this = $(this), $form = $('form#post'), $previewField = $('input#wp-preview'), target = $this.attr('target') || 'wp-preview', ua = navigator.userAgent.toLowerCase(); event.preventDefault(); if ( $this.hasClass('disabled') ) { return; } if ( wp.autosave ) { wp.autosave.server.tempBlockSave(); } $previewField.val('dopreview'); $form.attr( 'target', target ).trigger( 'submit' ).attr( 'target', '' ); // Workaround for WebKit bug preventing a form submitting twice to the same action. // https://bugs.webkit.org/show_bug.cgi?id=28633 if ( ua.indexOf('safari') !== -1 && ua.indexOf('chrome') === -1 ) { $form.attr( 'action', function( index, value ) { return value + '?t=' + ( new Date() ).getTime(); }); } $previewField.val(''); }); // Auto save new posts after a title is typed. if ( $( '#auto_draft' ).val() ) { $( '#title' ).on( 'blur', function() { var cancel; if ( ! this.value || $('#edit-slug-box > *').length ) { return; } // Cancel the auto save when the blur was triggered by the user submitting the form. $('form#post').one( 'submit', function() { cancel = true; }); window.setTimeout( function() { if ( ! cancel && wp.autosave ) { wp.autosave.server.triggerSave(); } }, 200 ); }); } $document.on( 'autosave-disable-buttons.edit-post', function() { $submitButtons.addClass( 'disabled' ); }).on( 'autosave-enable-buttons.edit-post', function() { if ( ! wp.heartbeat || ! wp.heartbeat.hasConnectionError() ) { $submitButtons.removeClass( 'disabled' ); } }).on( 'before-autosave.edit-post', function() { $( '.autosave-message' ).text( __( 'Saving Draft…' ) ); }).on( 'after-autosave.edit-post', function( event, data ) { $( '.autosave-message' ).text( data.message ); if ( $( document.body ).hasClass( 'post-new-php' ) ) { $( '.submitbox .submitdelete' ).show(); } }); /* * When the user is trying to load another page, or reloads current page * show a confirmation dialog when there are unsaved changes. */ $( window ).on( 'beforeunload.edit-post', function( event ) { var editor = window.tinymce && window.tinymce.get( 'content' ); var changed = false; if ( wp.autosave ) { changed = wp.autosave.server.postChanged(); } else if ( editor ) { changed = ( ! editor.isHidden() && editor.isDirty() ); } if ( changed ) { event.preventDefault(); // The return string is needed for browser compat. // See https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event. return __( 'The changes you made will be lost if you navigate away from this page.' ); } }).on( 'pagehide.edit-post', function( event ) { if ( ! releaseLock ) { return; } /* * Unload is triggered (by hand) on removing the Thickbox iframe. * Make sure we process only the main document unload. */ if ( event.target && event.target.nodeName != '#document' ) { return; } var postID = $('#post_ID').val(); var postLock = $('#active_post_lock').val(); if ( ! postID || ! postLock ) { return; } var data = { action: 'wp-remove-post-lock', _wpnonce: $('#_wpnonce').val(), post_ID: postID, active_post_lock: postLock }; if ( window.FormData && window.navigator.sendBeacon ) { var formData = new window.FormData(); $.each( data, function( key, value ) { formData.append( key, value ); }); if ( window.navigator.sendBeacon( ajaxurl, formData ) ) { return; } } // Fall back to a synchronous POST request. // See https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon $.post({ async: false, data: data, url: ajaxurl }); }); // Multiple taxonomies. if ( $('#tagsdiv-post_tag').length ) { window.tagBox && window.tagBox.init(); } else { $('.meta-box-sortables').children('div.postbox').each(function(){ if ( this.id.indexOf('tagsdiv-') === 0 ) { window.tagBox && window.tagBox.init(); return false; } }); } // Handle categories. $('.categorydiv').each( function(){ var this_id = $(this).attr('id'), catAddBefore, catAddAfter, taxonomyParts, taxonomy, settingName; taxonomyParts = this_id.split('-'); taxonomyParts.shift(); taxonomy = taxonomyParts.join('-'); settingName = taxonomy + '_tab'; if ( taxonomy == 'category' ) { settingName = 'cats'; } // @todo Move to jQuery 1.3+, support for multiple hierarchical taxonomies, see wp-lists.js. $('a', '#' + taxonomy + '-tabs').on( 'click', function( e ) { e.preventDefault(); var t = $(this).attr('href'); $(this).parent().addClass('tabs').siblings('li').removeClass('tabs'); $('#' + taxonomy + '-tabs').siblings('.tabs-panel').hide(); $(t).show(); if ( '#' + taxonomy + '-all' == t ) { deleteUserSetting( settingName ); } else { setUserSetting( settingName, 'pop' ); } }); if ( getUserSetting( settingName ) ) $('a[href="#' + taxonomy + '-pop"]', '#' + taxonomy + '-tabs').trigger( 'click' ); // Add category button controls. $('#new' + taxonomy).one( 'focus', function() { $( this ).val( '' ).removeClass( 'form-input-tip' ); }); // On [Enter] submit the taxonomy. $('#new' + taxonomy).on( 'keypress', function(event){ if( 13 === event.keyCode ) { event.preventDefault(); $('#' + taxonomy + '-add-submit').trigger( 'click' ); } }); // After submitting a new taxonomy, re-focus the input field. $('#' + taxonomy + '-add-submit').on( 'click', function() { $('#new' + taxonomy).trigger( 'focus' ); }); /** * Before adding a new taxonomy, disable submit button. * * @param {Object} s Taxonomy object which will be added. * * @return {Object} */ catAddBefore = function( s ) { if ( !$('#new'+taxonomy).val() ) { return false; } s.data += '&' + $( ':checked', '#'+taxonomy+'checklist' ).serialize(); $( '#' + taxonomy + '-add-submit' ).prop( 'disabled', true ); return s; }; /** * Re-enable submit button after a taxonomy has been added. * * Re-enable submit button. * If the taxonomy has a parent place the taxonomy underneath the parent. * * @param {Object} r Response. * @param {Object} s Taxonomy data. * * @return {void} */ catAddAfter = function( r, s ) { var sup, drop = $('#new'+taxonomy+'_parent'); $( '#' + taxonomy + '-add-submit' ).prop( 'disabled', false ); if ( 'undefined' != s.parsed.responses[0] && (sup = s.parsed.responses[0].supplemental.newcat_parent) ) { drop.before(sup); drop.remove(); } }; $('#' + taxonomy + 'checklist').wpList({ alt: '', response: taxonomy + '-ajax-response', addBefore: catAddBefore, addAfter: catAddAfter }); // Add new taxonomy button toggles input form visibility. $('#' + taxonomy + '-add-toggle').on( 'click', function( e ) { e.preventDefault(); $('#' + taxonomy + '-adder').toggleClass( 'wp-hidden-children' ); $('a[href="#' + taxonomy + '-all"]', '#' + taxonomy + '-tabs').trigger( 'click' ); $('#new'+taxonomy).trigger( 'focus' ); }); // Sync checked items between "All {taxonomy}" and "Most used" lists. $('#' + taxonomy + 'checklist, #' + taxonomy + 'checklist-pop').on( 'click', 'li.popular-category > label input[type="checkbox"]', function() { var t = $(this), c = t.is(':checked'), id = t.val(); if ( id && t.parents('#taxonomy-'+taxonomy).length ) { $('input#in-' + taxonomy + '-' + id + ', input[id^="in-' + taxonomy + '-' + id + '-"]').prop('checked', c); $('input#in-popular-' + taxonomy + '-' + id).prop('checked', c); } } ); }); // End cats. // Custom Fields postbox. if ( $('#postcustom').length ) { $( '#the-list' ).wpList( { /** * Add current post_ID to request to fetch custom fields * * @ignore * * @param {Object} s Request object. * * @return {Object} Data modified with post_ID attached. */ addBefore: function( s ) { s.data += '&post_id=' + $('#post_ID').val(); return s; }, /** * Show the listing of custom fields after fetching. * * @ignore */ addAfter: function() { $('table#list-table').show(); } }); } /* * Publish Post box (#submitdiv) */ if ( $('#submitdiv').length ) { stamp = $('#timestamp').html(); visibility = $('#post-visibility-display').html(); /** * When the visibility of a post changes sub-options should be shown or hidden. * * @ignore * * @return {void} */ updateVisibility = function() { // Show sticky for public posts. if ( $postVisibilitySelect.find('input:radio:checked').val() != 'public' ) { $('#sticky').prop('checked', false); $('#sticky-span').hide(); } else { $('#sticky-span').show(); } // Show password input field for password protected post. if ( $postVisibilitySelect.find('input:radio:checked').val() != 'password' ) { $('#password-span').hide(); } else { $('#password-span').show(); } }; /** * Make sure all labels represent the current settings. * * @ignore * * @return {boolean} False when an invalid timestamp has been selected, otherwise True. */ updateText = function() { if ( ! $timestampdiv.length ) return true; var attemptedDate, originalDate, currentDate, publishOn, postStatus = $('#post_status'), optPublish = $('option[value="publish"]', postStatus), aa = $('#aa').val(), mm = $('#mm').val(), jj = $('#jj').val(), hh = $('#hh').val(), mn = $('#mn').val(); attemptedDate = new Date( aa, mm - 1, jj, hh, mn ); originalDate = new Date( $('#hidden_aa').val(), $('#hidden_mm').val() -1, $('#hidden_jj').val(), $('#hidden_hh').val(), $('#hidden_mn').val() ); currentDate = new Date( $('#cur_aa').val(), $('#cur_mm').val() -1, $('#cur_jj').val(), $('#cur_hh').val(), $('#cur_mn').val() ); // Catch unexpected date problems. if ( attemptedDate.getFullYear() != aa || (1 + attemptedDate.getMonth()) != mm || attemptedDate.getDate() != jj || attemptedDate.getMinutes() != mn ) { $timestampdiv.find('.timestamp-wrap').addClass('form-invalid'); return false; } else { $timestampdiv.find('.timestamp-wrap').removeClass('form-invalid'); } // Determine what the publish should be depending on the date and post status. if ( attemptedDate > currentDate ) { publishOn = __( 'Schedule for:' ); $('#publish').val( _x( 'Schedule', 'post action/button label' ) ); } else if ( attemptedDate <= currentDate && $('#original_post_status').val() != 'publish' ) { publishOn = __( 'Publish on:' ); $('#publish').val( __( 'Publish' ) ); } else { publishOn = __( 'Published on:' ); $('#publish').val( __( 'Update' ) ); } // If the date is the same, set it to trigger update events. if ( originalDate.toUTCString() == attemptedDate.toUTCString() ) { // Re-set to the current value. $('#timestamp').html(stamp); } else { $('#timestamp').html( '\n' + publishOn + ' ' + // translators: 1: Month, 2: Day, 3: Year, 4: Hour, 5: Minute. __( '%1$s %2$s, %3$s at %4$s:%5$s' ) .replace( '%1$s', $( 'option[value="' + mm + '"]', '#mm' ).attr( 'data-text' ) ) .replace( '%2$s', parseInt( jj, 10 ) ) .replace( '%3$s', aa ) .replace( '%4$s', ( '00' + hh ).slice( -2 ) ) .replace( '%5$s', ( '00' + mn ).slice( -2 ) ) + ' ' ); } // Add "privately published" to post status when applies. if ( $postVisibilitySelect.find('input:radio:checked').val() == 'private' ) { $('#publish').val( __( 'Update' ) ); if ( 0 === optPublish.length ) { postStatus.append(''); } else { optPublish.html( __( 'Privately Published' ) ); } $('option[value="publish"]', postStatus).prop('selected', true); $('#misc-publishing-actions .edit-post-status').hide(); } else { if ( $('#original_post_status').val() == 'future' || $('#original_post_status').val() == 'draft' ) { if ( optPublish.length ) { optPublish.remove(); postStatus.val($('#hidden_post_status').val()); } } else { optPublish.html( __( 'Published' ) ); } if ( postStatus.is(':hidden') ) $('#misc-publishing-actions .edit-post-status').show(); } // Update "Status:" to currently selected status. $('#post-status-display').text( // Remove any potential tags from post status text. wp.sanitize.stripTagsAndEncodeText( $('option:selected', postStatus).text() ) ); // Show or hide the "Save Draft" button. if ( $('option:selected', postStatus).val() == 'private' || $('option:selected', postStatus).val() == 'publish' ) { $('#save-post').hide(); } else { $('#save-post').show(); if ( $('option:selected', postStatus).val() == 'pending' ) { $('#save-post').show().val( __( 'Save as Pending' ) ); } else { $('#save-post').show().val( __( 'Save Draft' ) ); } } return true; }; // Show the visibility options and hide the toggle button when opened. $( '#visibility .edit-visibility').on( 'click', function( e ) { e.preventDefault(); if ( $postVisibilitySelect.is(':hidden') ) { updateVisibility(); $postVisibilitySelect.slideDown( 'fast', function() { $postVisibilitySelect.find( 'input[type="radio"]' ).first().trigger( 'focus' ); } ); $(this).hide(); } }); // Cancel visibility selection area and hide it from view. $postVisibilitySelect.find('.cancel-post-visibility').on( 'click', function( event ) { $postVisibilitySelect.slideUp('fast'); $('#visibility-radio-' + $('#hidden-post-visibility').val()).prop('checked', true); $('#post_password').val($('#hidden-post-password').val()); $('#sticky').prop('checked', $('#hidden-post-sticky').prop('checked')); $('#post-visibility-display').html(visibility); $('#visibility .edit-visibility').show().trigger( 'focus' ); updateText(); event.preventDefault(); }); // Set the selected visibility as current. $postVisibilitySelect.find('.save-post-visibility').on( 'click', function( event ) { // Crazyhorse branch - multiple OK cancels. var visibilityLabel = '', selectedVisibility = $postVisibilitySelect.find('input:radio:checked').val(); $postVisibilitySelect.slideUp('fast'); $('#visibility .edit-visibility').show().trigger( 'focus' ); updateText(); if ( 'public' !== selectedVisibility ) { $('#sticky').prop('checked', false); } switch ( selectedVisibility ) { case 'public': visibilityLabel = $( '#sticky' ).prop( 'checked' ) ? __( 'Public, Sticky' ) : __( 'Public' ); break; case 'private': visibilityLabel = __( 'Private' ); break; case 'password': visibilityLabel = __( 'Password Protected' ); break; } $('#post-visibility-display').text( visibilityLabel ); event.preventDefault(); }); // When the selection changes, update labels. $postVisibilitySelect.find('input:radio').on( 'change', function() { updateVisibility(); }); // Edit publish time click. $timestampdiv.siblings('a.edit-timestamp').on( 'click', function( event ) { if ( $timestampdiv.is( ':hidden' ) ) { $timestampdiv.slideDown( 'fast', function() { $( 'input, select', $timestampdiv.find( '.timestamp-wrap' ) ).first().trigger( 'focus' ); } ); $(this).hide(); } event.preventDefault(); }); // Cancel editing the publish time and hide the settings. $timestampdiv.find('.cancel-timestamp').on( 'click', function( event ) { $timestampdiv.slideUp('fast').siblings('a.edit-timestamp').show().trigger( 'focus' ); $('#mm').val($('#hidden_mm').val()); $('#jj').val($('#hidden_jj').val()); $('#aa').val($('#hidden_aa').val()); $('#hh').val($('#hidden_hh').val()); $('#mn').val($('#hidden_mn').val()); updateText(); event.preventDefault(); }); // Save the changed timestamp. $timestampdiv.find('.save-timestamp').on( 'click', function( event ) { // Crazyhorse branch - multiple OK cancels. if ( updateText() ) { $timestampdiv.slideUp('fast'); $timestampdiv.siblings('a.edit-timestamp').show().trigger( 'focus' ); } event.preventDefault(); }); // Cancel submit when an invalid timestamp has been selected. $('#post').on( 'submit', function( event ) { if ( ! updateText() ) { event.preventDefault(); $timestampdiv.show(); if ( wp.autosave ) { wp.autosave.enableButtons(); } $( '#publishing-action .spinner' ).removeClass( 'is-active' ); } }); // Post Status edit click. $postStatusSelect.siblings('a.edit-post-status').on( 'click', function( event ) { if ( $postStatusSelect.is( ':hidden' ) ) { $postStatusSelect.slideDown( 'fast', function() { $postStatusSelect.find('select').trigger( 'focus' ); } ); $(this).hide(); } event.preventDefault(); }); // Save the Post Status changes and hide the options. $postStatusSelect.find('.save-post-status').on( 'click', function( event ) { $postStatusSelect.slideUp( 'fast' ).siblings( 'a.edit-post-status' ).show().trigger( 'focus' ); updateText(); event.preventDefault(); }); // Cancel Post Status editing and hide the options. $postStatusSelect.find('.cancel-post-status').on( 'click', function( event ) { $postStatusSelect.slideUp( 'fast' ).siblings( 'a.edit-post-status' ).show().trigger( 'focus' ); $('#post_status').val( $('#hidden_post_status').val() ); updateText(); event.preventDefault(); }); } /** * Handle the editing of the post_name. Create the required HTML elements and * update the changes via Ajax. * * @global * * @return {void} */ function editPermalink() { var i, slug_value, slug_label, $el, revert_e, c = 0, real_slug = $('#post_name'), revert_slug = real_slug.val(), permalink = $( '#sample-permalink' ), permalinkOrig = permalink.html(), permalinkInner = $( '#sample-permalink a' ).html(), buttons = $('#edit-slug-buttons'), buttonsOrig = buttons.html(), full = $('#editable-post-name-full'); // Deal with Twemoji in the post-name. full.find( 'img' ).replaceWith( function() { return this.alt; } ); full = full.html(); permalink.html( permalinkInner ); // Save current content to revert to when cancelling. $el = $( '#editable-post-name' ); revert_e = $el.html(); buttons.html( ' ' + '' ); // Save permalink changes. buttons.children( '.save' ).on( 'click', function() { var new_slug = $el.children( 'input' ).val(); if ( new_slug == $('#editable-post-name-full').text() ) { buttons.children('.cancel').trigger( 'click' ); return; } $.post( ajaxurl, { action: 'sample-permalink', post_id: postId, new_slug: new_slug, new_title: $('#title').val(), samplepermalinknonce: $('#samplepermalinknonce').val() }, function(data) { var box = $('#edit-slug-box'); box.html(data); if (box.hasClass('hidden')) { box.fadeIn('fast', function () { box.removeClass('hidden'); }); } buttons.html(buttonsOrig); permalink.html(permalinkOrig); real_slug.val(new_slug); $( '.edit-slug' ).trigger( 'focus' ); wp.a11y.speak( __( 'Permalink saved' ) ); } ); }); // Cancel editing of permalink. buttons.children( '.cancel' ).on( 'click', function() { $('#view-post-btn').show(); $el.html(revert_e); buttons.html(buttonsOrig); permalink.html(permalinkOrig); real_slug.val(revert_slug); $( '.edit-slug' ).trigger( 'focus' ); }); // If more than 1/4th of 'full' is '%', make it empty. for ( i = 0; i < full.length; ++i ) { if ( '%' == full.charAt(i) ) c++; } slug_value = ( c > full.length / 4 ) ? '' : full; slug_label = __( 'URL Slug' ); $el.html( '' + '' ).children( 'input' ).on( 'keydown', function( e ) { var key = e.which; // On [Enter], just save the new slug, don't save the post. if ( 13 === key ) { e.preventDefault(); buttons.children( '.save' ).trigger( 'click' ); } // On [Esc] cancel the editing. if ( 27 === key ) { buttons.children( '.cancel' ).trigger( 'click' ); } } ).on( 'keyup', function() { real_slug.val( this.value ); }).trigger( 'focus' ); } $( '#titlediv' ).on( 'click', '.edit-slug', function() { editPermalink(); }); /** * Adds screen reader text to the title label when needed. * * Use the 'screen-reader-text' class to emulate a placeholder attribute * and hide the label when entering a value. * * @param {string} id Optional. HTML ID to add the screen reader helper text to. * * @global * * @return {void} */ window.wptitlehint = function( id ) { id = id || 'title'; var title = $( '#' + id ), titleprompt = $( '#' + id + '-prompt-text' ); if ( '' === title.val() ) { titleprompt.removeClass( 'screen-reader-text' ); } title.on( 'input', function() { if ( '' === this.value ) { titleprompt.removeClass( 'screen-reader-text' ); return; } titleprompt.addClass( 'screen-reader-text' ); } ); }; wptitlehint(); // Resize the WYSIWYG and plain text editors. ( function() { var editor, offset, mce, $handle = $('#post-status-info'), $postdivrich = $('#postdivrich'); // If there are no textareas or we are on a touch device, we can't do anything. if ( ! $textarea.length || 'ontouchstart' in window ) { // Hide the resize handle. $('#content-resize-handle').hide(); return; } /** * Handle drag event. * * @param {Object} event Event containing details about the drag. */ function dragging( event ) { if ( $postdivrich.hasClass( 'wp-editor-expand' ) ) { return; } if ( mce ) { editor.theme.resizeTo( null, offset + event.pageY ); } else { $textarea.height( Math.max( 50, offset + event.pageY ) ); } event.preventDefault(); } /** * When the dragging stopped make sure we return focus and do a confidence check on the height. */ function endDrag() { var height, toolbarHeight; if ( $postdivrich.hasClass( 'wp-editor-expand' ) ) { return; } if ( mce ) { editor.focus(); toolbarHeight = parseInt( $( '#wp-content-editor-container .mce-toolbar-grp' ).height(), 10 ); if ( toolbarHeight < 10 || toolbarHeight > 200 ) { toolbarHeight = 30; } height = parseInt( $('#content_ifr').css('height'), 10 ) + toolbarHeight - 28; } else { $textarea.trigger( 'focus' ); height = parseInt( $textarea.css('height'), 10 ); } $document.off( '.wp-editor-resize' ); // Confidence check: normalize height to stay within acceptable ranges. if ( height && height > 50 && height < 5000 ) { setUserSetting( 'ed_size', height ); } } $handle.on( 'mousedown.wp-editor-resize', function( event ) { if ( typeof tinymce !== 'undefined' ) { editor = tinymce.get('content'); } if ( editor && ! editor.isHidden() ) { mce = true; offset = $('#content_ifr').height() - event.pageY; } else { mce = false; offset = $textarea.height() - event.pageY; $textarea.trigger( 'blur' ); } $document.on( 'mousemove.wp-editor-resize', dragging ) .on( 'mouseup.wp-editor-resize mouseleave.wp-editor-resize', endDrag ); event.preventDefault(); }).on( 'mouseup.wp-editor-resize', endDrag ); })(); // TinyMCE specific handling of Post Format changes to reflect in the editor. if ( typeof tinymce !== 'undefined' ) { // When changing post formats, change the editor body class. $( '#post-formats-select input.post-format' ).on( 'change.set-editor-class', function() { var editor, body, format = this.id; if ( format && $( this ).prop( 'checked' ) && ( editor = tinymce.get( 'content' ) ) ) { body = editor.getBody(); body.className = body.className.replace( /\bpost-format-[^ ]+/, '' ); editor.dom.addClass( body, format == 'post-format-0' ? 'post-format-standard' : format ); $( document ).trigger( 'editor-classchange' ); } }); // When changing page template, change the editor body class. $( '#page_template' ).on( 'change.set-editor-class', function() { var editor, body, pageTemplate = $( this ).val() || ''; pageTemplate = pageTemplate.substr( pageTemplate.lastIndexOf( '/' ) + 1, pageTemplate.length ) .replace( /\.php$/, '' ) .replace( /\./g, '-' ); if ( pageTemplate && ( editor = tinymce.get( 'content' ) ) ) { body = editor.getBody(); body.className = body.className.replace( /\bpage-template-[^ ]+/, '' ); editor.dom.addClass( body, 'page-template-' + pageTemplate ); $( document ).trigger( 'editor-classchange' ); } }); } // Save on pressing [Ctrl]/[Command] + [S] in the Text editor. $textarea.on( 'keydown.wp-autosave', function( event ) { // Key [S] has code 83. if ( event.which === 83 ) { if ( event.shiftKey || event.altKey || ( isMac && ( ! event.metaKey || event.ctrlKey ) ) || ( ! isMac && ! event.ctrlKey ) ) { return; } wp.autosave && wp.autosave.server.triggerSave(); event.preventDefault(); } }); // If the last status was auto-draft and the save is triggered, edit the current URL. if ( $( '#original_post_status' ).val() === 'auto-draft' && window.history.replaceState ) { var location; $( '#publish' ).on( 'click', function() { location = window.location.href; location += ( location.indexOf( '?' ) !== -1 ) ? '&' : '?'; location += 'wp-post-new-reload=true'; window.history.replaceState( null, null, location ); }); } /** * Copies the attachment URL in the Edit Media page to the clipboard. * * @since 5.5.0 * * @param {MouseEvent} event A click event. * * @return {void} */ copyAttachmentURLClipboard.on( 'success', function( event ) { var triggerElement = $( event.trigger ), successElement = $( '.success', triggerElement.closest( '.copy-to-clipboard-container' ) ); // Clear the selection and move focus back to the trigger. event.clearSelection(); // Show success visual feedback. clearTimeout( copyAttachmentURLSuccessTimeout ); successElement.removeClass( 'hidden' ); // Hide success visual feedback after 3 seconds since last success. copyAttachmentURLSuccessTimeout = setTimeout( function() { successElement.addClass( 'hidden' ); }, 3000 ); // Handle success audible feedback. wp.a11y.speak( __( 'The file URL has been copied to your clipboard' ) ); } ); } ); /** * TinyMCE word count display */ ( function( $, counter ) { $( function() { var $content = $( '#content' ), $count = $( '#wp-word-count' ).find( '.word-count' ), prevCount = 0, contentEditor; /** * Get the word count from TinyMCE and display it */ function update() { var text, count; if ( ! contentEditor || contentEditor.isHidden() ) { text = $content.val(); } else { text = contentEditor.getContent( { format: 'raw' } ); } count = counter.count( text ); if ( count !== prevCount ) { $count.text( count ); } prevCount = count; } /** * Bind the word count update triggers. * * When a node change in the main TinyMCE editor has been triggered. * When a key has been released in the plain text content editor. */ $( document ).on( 'tinymce-editor-init', function( event, editor ) { if ( editor.id !== 'content' ) { return; } contentEditor = editor; editor.on( 'nodechange keyup', _.debounce( update, 1000 ) ); } ); $content.on( 'input keyup', _.debounce( update, 1000 ) ); update(); } ); } )( jQuery, new wp.utils.WordCounter() ); comment.js000064400000005547147573140730006572 0ustar00/** * @output wp-admin/js/comment.js */ /* global postboxes */ /** * Binds to the document ready event. * * @since 2.5.0 * * @param {jQuery} $ The jQuery object. */ jQuery( function($) { postboxes.add_postbox_toggles('comment'); var $timestampdiv = $('#timestampdiv'), $timestamp = $( '#timestamp' ), stamp = $timestamp.html(), $timestampwrap = $timestampdiv.find( '.timestamp-wrap' ), $edittimestamp = $timestampdiv.siblings( 'a.edit-timestamp' ); /** * Adds event that opens the time stamp form if the form is hidden. * * @listens $edittimestamp:click * * @param {Event} event The event object. * @return {void} */ $edittimestamp.on( 'click', function( event ) { if ( $timestampdiv.is( ':hidden' ) ) { // Slide down the form and set focus on the first field. $timestampdiv.slideDown( 'fast', function() { $( 'input, select', $timestampwrap ).first().trigger( 'focus' ); } ); $(this).hide(); } event.preventDefault(); }); /** * Resets the time stamp values when the cancel button is clicked. * * @listens .cancel-timestamp:click * * @param {Event} event The event object. * @return {void} */ $timestampdiv.find('.cancel-timestamp').on( 'click', function( event ) { // Move focus back to the Edit link. $edittimestamp.show().trigger( 'focus' ); $timestampdiv.slideUp( 'fast' ); $('#mm').val($('#hidden_mm').val()); $('#jj').val($('#hidden_jj').val()); $('#aa').val($('#hidden_aa').val()); $('#hh').val($('#hidden_hh').val()); $('#mn').val($('#hidden_mn').val()); $timestamp.html( stamp ); event.preventDefault(); }); /** * Sets the time stamp values when the ok button is clicked. * * @listens .save-timestamp:click * * @param {Event} event The event object. * @return {void} */ $timestampdiv.find('.save-timestamp').on( 'click', function( event ) { // Crazyhorse branch - multiple OK cancels. var aa = $('#aa').val(), mm = $('#mm').val(), jj = $('#jj').val(), hh = $('#hh').val(), mn = $('#mn').val(), newD = new Date( aa, mm - 1, jj, hh, mn ); event.preventDefault(); if ( newD.getFullYear() != aa || (1 + newD.getMonth()) != mm || newD.getDate() != jj || newD.getMinutes() != mn ) { $timestampwrap.addClass( 'form-invalid' ); return; } else { $timestampwrap.removeClass( 'form-invalid' ); } $timestamp.html( wp.i18n.__( 'Submitted on:' ) + ' ' + /* translators: 1: Month, 2: Day, 3: Year, 4: Hour, 5: Minute. */ wp.i18n.__( '%1$s %2$s, %3$s at %4$s:%5$s' ) .replace( '%1$s', $( 'option[value="' + mm + '"]', '#mm' ).attr( 'data-text' ) ) .replace( '%2$s', parseInt( jj, 10 ) ) .replace( '%3$s', aa ) .replace( '%4$s', ( '00' + hh ).slice( -2 ) ) .replace( '%5$s', ( '00' + mn ).slice( -2 ) ) + ' ' ); // Move focus back to the Edit link. $edittimestamp.show().trigger( 'focus' ); $timestampdiv.slideUp( 'fast' ); }); }); custom-background.js000064400000006553147573140730010555 0ustar00/** * @output wp-admin/js/custom-background.js */ /* global ajaxurl */ /** * Registers all events for customizing the background. * * @since 3.0.0 * * @requires jQuery */ (function($) { $( function() { var frame, bgImage = $( '#custom-background-image' ); /** * Instantiates the WordPress color picker and binds the change and clear events. * * @since 3.5.0 * * @return {void} */ $('#background-color').wpColorPicker({ change: function( event, ui ) { bgImage.css('background-color', ui.color.toString()); }, clear: function() { bgImage.css('background-color', ''); } }); /** * Alters the background size CSS property whenever the background size input has changed. * * @since 4.7.0 * * @return {void} */ $( 'select[name="background-size"]' ).on( 'change', function() { bgImage.css( 'background-size', $( this ).val() ); }); /** * Alters the background position CSS property whenever the background position input has changed. * * @since 4.7.0 * * @return {void} */ $( 'input[name="background-position"]' ).on( 'change', function() { bgImage.css( 'background-position', $( this ).val() ); }); /** * Alters the background repeat CSS property whenever the background repeat input has changed. * * @since 3.0.0 * * @return {void} */ $( 'input[name="background-repeat"]' ).on( 'change', function() { bgImage.css( 'background-repeat', $( this ).is( ':checked' ) ? 'repeat' : 'no-repeat' ); }); /** * Alters the background attachment CSS property whenever the background attachment input has changed. * * @since 4.7.0 * * @return {void} */ $( 'input[name="background-attachment"]' ).on( 'change', function() { bgImage.css( 'background-attachment', $( this ).is( ':checked' ) ? 'scroll' : 'fixed' ); }); /** * Binds the event for opening the WP Media dialog. * * @since 3.5.0 * * @return {void} */ $('#choose-from-library-link').on( 'click', function( event ) { var $el = $(this); event.preventDefault(); // If the media frame already exists, reopen it. if ( frame ) { frame.open(); return; } // Create the media frame. frame = wp.media.frames.customBackground = wp.media({ // Set the title of the modal. title: $el.data('choose'), // Tell the modal to show only images. library: { type: 'image' }, // Customize the submit button. button: { // Set the text of the button. text: $el.data('update'), /* * Tell the button not to close the modal, since we're * going to refresh the page when the image is selected. */ close: false } }); /** * When an image is selected, run a callback. * * @since 3.5.0 * * @return {void} */ frame.on( 'select', function() { // Grab the selected attachment. var attachment = frame.state().get('selection').first(); var nonceValue = $( '#_wpnonce' ).val() || ''; // Run an Ajax request to set the background image. $.post( ajaxurl, { action: 'set-background-image', attachment_id: attachment.id, _ajax_nonce: nonceValue, size: 'full' }).done( function() { // When the request completes, reload the window. window.location.reload(); }); }); // Finally, open the modal. frame.open(); }); }); })(jQuery); edit-comments.js000064400000111262147573140730007670 0ustar00/** * Handles updating and editing comments. * * @file This file contains functionality for the admin comments page. * @since 2.1.0 * @output wp-admin/js/edit-comments.js */ /* global adminCommentsSettings, thousandsSeparator, list_args, QTags, ajaxurl, wpAjax */ /* global commentReply, theExtraList, theList, setCommentsList */ (function($) { var getCount, updateCount, updateCountText, updatePending, updateApproved, updateHtmlTitle, updateDashboardText, updateInModerationText, adminTitle = document.title, isDashboard = $('#dashboard_right_now').length, titleDiv, titleRegEx, __ = wp.i18n.__; /** * Extracts a number from the content of a jQuery element. * * @since 2.9.0 * @access private * * @param {jQuery} el jQuery element. * * @return {number} The number found in the given element. */ getCount = function(el) { var n = parseInt( el.html().replace(/[^0-9]+/g, ''), 10 ); if ( isNaN(n) ) { return 0; } return n; }; /** * Updates an html element with a localized number string. * * @since 2.9.0 * @access private * * @param {jQuery} el The jQuery element to update. * @param {number} n Number to be put in the element. * * @return {void} */ updateCount = function(el, n) { var n1 = ''; if ( isNaN(n) ) { return; } n = n < 1 ? '0' : n.toString(); if ( n.length > 3 ) { while ( n.length > 3 ) { n1 = thousandsSeparator + n.substr(n.length - 3) + n1; n = n.substr(0, n.length - 3); } n = n + n1; } el.html(n); }; /** * Updates the number of approved comments on a specific post and the filter bar. * * @since 4.4.0 * @access private * * @param {number} diff The amount to lower or raise the approved count with. * @param {number} commentPostId The ID of the post to be updated. * * @return {void} */ updateApproved = function( diff, commentPostId ) { var postSelector = '.post-com-count-' + commentPostId, noClass = 'comment-count-no-comments', approvedClass = 'comment-count-approved', approved, noComments; updateCountText( 'span.approved-count', diff ); if ( ! commentPostId ) { return; } // Cache selectors to not get duplicates. approved = $( 'span.' + approvedClass, postSelector ); noComments = $( 'span.' + noClass, postSelector ); approved.each(function() { var a = $(this), n = getCount(a) + diff; if ( n < 1 ) n = 0; if ( 0 === n ) { a.removeClass( approvedClass ).addClass( noClass ); } else { a.addClass( approvedClass ).removeClass( noClass ); } updateCount( a, n ); }); noComments.each(function() { var a = $(this); if ( diff > 0 ) { a.removeClass( noClass ).addClass( approvedClass ); } else { a.addClass( noClass ).removeClass( approvedClass ); } updateCount( a, diff ); }); }; /** * Updates a number count in all matched HTML elements * * @since 4.4.0 * @access private * * @param {string} selector The jQuery selector for elements to update a count * for. * @param {number} diff The amount to lower or raise the count with. * * @return {void} */ updateCountText = function( selector, diff ) { $( selector ).each(function() { var a = $(this), n = getCount(a) + diff; if ( n < 1 ) { n = 0; } updateCount( a, n ); }); }; /** * Updates a text about comment count on the dashboard. * * @since 4.4.0 * @access private * * @param {Object} response Ajax response from the server that includes a * translated "comment count" message. * * @return {void} */ updateDashboardText = function( response ) { if ( ! isDashboard || ! response || ! response.i18n_comments_text ) { return; } $( '.comment-count a', '#dashboard_right_now' ).text( response.i18n_comments_text ); }; /** * Updates the "comments in moderation" text across the UI. * * @since 5.2.0 * * @param {Object} response Ajax response from the server that includes a * translated "comments in moderation" message. * * @return {void} */ updateInModerationText = function( response ) { if ( ! response || ! response.i18n_moderation_text ) { return; } // Update the "comment in moderation" text across the UI. $( '.comments-in-moderation-text' ).text( response.i18n_moderation_text ); // Hide the "comment in moderation" text in the Dashboard "At a Glance" widget. if ( isDashboard && response.in_moderation ) { $( '.comment-mod-count', '#dashboard_right_now' ) [ response.in_moderation > 0 ? 'removeClass' : 'addClass' ]( 'hidden' ); } }; /** * Updates the title of the document with the number comments to be approved. * * @since 4.4.0 * @access private * * @param {number} diff The amount to lower or raise the number of to be * approved comments with. * * @return {void} */ updateHtmlTitle = function( diff ) { var newTitle, regExMatch, titleCount, commentFrag; /* translators: %s: Comments count. */ titleRegEx = titleRegEx || new RegExp( __( 'Comments (%s)' ).replace( '%s', '\\([0-9' + thousandsSeparator + ']+\\)' ) + '?' ); // Count funcs operate on a $'d element. titleDiv = titleDiv || $( '
    ' ); newTitle = adminTitle; commentFrag = titleRegEx.exec( document.title ); if ( commentFrag ) { commentFrag = commentFrag[0]; titleDiv.html( commentFrag ); titleCount = getCount( titleDiv ) + diff; } else { titleDiv.html( 0 ); titleCount = diff; } if ( titleCount >= 1 ) { updateCount( titleDiv, titleCount ); regExMatch = titleRegEx.exec( document.title ); if ( regExMatch ) { /* translators: %s: Comments count. */ newTitle = document.title.replace( regExMatch[0], __( 'Comments (%s)' ).replace( '%s', titleDiv.text() ) + ' ' ); } } else { regExMatch = titleRegEx.exec( newTitle ); if ( regExMatch ) { newTitle = newTitle.replace( regExMatch[0], __( 'Comments' ) ); } } document.title = newTitle; }; /** * Updates the number of pending comments on a specific post and the filter bar. * * @since 3.2.0 * @access private * * @param {number} diff The amount to lower or raise the pending count with. * @param {number} commentPostId The ID of the post to be updated. * * @return {void} */ updatePending = function( diff, commentPostId ) { var postSelector = '.post-com-count-' + commentPostId, noClass = 'comment-count-no-pending', noParentClass = 'post-com-count-no-pending', pendingClass = 'comment-count-pending', pending, noPending; if ( ! isDashboard ) { updateHtmlTitle( diff ); } $( 'span.pending-count' ).each(function() { var a = $(this), n = getCount(a) + diff; if ( n < 1 ) n = 0; a.closest('.awaiting-mod')[ 0 === n ? 'addClass' : 'removeClass' ]('count-0'); updateCount( a, n ); }); if ( ! commentPostId ) { return; } // Cache selectors to not get dupes. pending = $( 'span.' + pendingClass, postSelector ); noPending = $( 'span.' + noClass, postSelector ); pending.each(function() { var a = $(this), n = getCount(a) + diff; if ( n < 1 ) n = 0; if ( 0 === n ) { a.parent().addClass( noParentClass ); a.removeClass( pendingClass ).addClass( noClass ); } else { a.parent().removeClass( noParentClass ); a.addClass( pendingClass ).removeClass( noClass ); } updateCount( a, n ); }); noPending.each(function() { var a = $(this); if ( diff > 0 ) { a.parent().removeClass( noParentClass ); a.removeClass( noClass ).addClass( pendingClass ); } else { a.parent().addClass( noParentClass ); a.addClass( noClass ).removeClass( pendingClass ); } updateCount( a, diff ); }); }; /** * Initializes the comments list. * * @since 4.4.0 * * @global * * @return {void} */ window.setCommentsList = function() { var totalInput, perPageInput, pageInput, dimAfter, delBefore, updateTotalCount, delAfter, refillTheExtraList, diff, lastConfidentTime = 0; totalInput = $('input[name="_total"]', '#comments-form'); perPageInput = $('input[name="_per_page"]', '#comments-form'); pageInput = $('input[name="_page"]', '#comments-form'); /** * Updates the total with the latest count. * * The time parameter makes sure that we only update the total if this value is * a newer value than we previously received. * * The time and setConfidentTime parameters make sure that we only update the * total when necessary. So a value that has been generated earlier will not * update the total. * * @since 2.8.0 * @access private * * @param {number} total Total number of comments. * @param {number} time Unix timestamp of response. * @param {boolean} setConfidentTime Whether to update the last confident time * with the given time. * * @return {void} */ updateTotalCount = function( total, time, setConfidentTime ) { if ( time < lastConfidentTime ) return; if ( setConfidentTime ) lastConfidentTime = time; totalInput.val( total.toString() ); }; /** * Changes DOM that need to be changed after a list item has been dimmed. * * @since 2.5.0 * @access private * * @param {Object} r Ajax response object. * @param {Object} settings Settings for the wpList object. * * @return {void} */ dimAfter = function( r, settings ) { var editRow, replyID, replyButton, response, c = $( '#' + settings.element ); if ( true !== settings.parsed ) { response = settings.parsed.responses[0]; } editRow = $('#replyrow'); replyID = $('#comment_ID', editRow).val(); replyButton = $('#replybtn', editRow); if ( c.is('.unapproved') ) { if ( settings.data.id == replyID ) replyButton.text( __( 'Approve and Reply' ) ); c.find( '.row-actions span.view' ).addClass( 'hidden' ).end() .find( 'div.comment_status' ).html( '0' ); } else { if ( settings.data.id == replyID ) replyButton.text( __( 'Reply' ) ); c.find( '.row-actions span.view' ).removeClass( 'hidden' ).end() .find( 'div.comment_status' ).html( '1' ); } diff = $('#' + settings.element).is('.' + settings.dimClass) ? 1 : -1; if ( response ) { updateDashboardText( response.supplemental ); updateInModerationText( response.supplemental ); updatePending( diff, response.supplemental.postId ); updateApproved( -1 * diff, response.supplemental.postId ); } else { updatePending( diff ); updateApproved( -1 * diff ); } }; /** * Handles marking a comment as spam or trashing the comment. * * Is executed in the list delBefore hook. * * @since 2.8.0 * @access private * * @param {Object} settings Settings for the wpList object. * @param {HTMLElement} list Comments table element. * * @return {Object} The settings object. */ delBefore = function( settings, list ) { var note, id, el, n, h, a, author, action = false, wpListsData = $( settings.target ).attr( 'data-wp-lists' ); settings.data._total = totalInput.val() || 0; settings.data._per_page = perPageInput.val() || 0; settings.data._page = pageInput.val() || 0; settings.data._url = document.location.href; settings.data.comment_status = $('input[name="comment_status"]', '#comments-form').val(); if ( wpListsData.indexOf(':trash=1') != -1 ) action = 'trash'; else if ( wpListsData.indexOf(':spam=1') != -1 ) action = 'spam'; if ( action ) { id = wpListsData.replace(/.*?comment-([0-9]+).*/, '$1'); el = $('#comment-' + id); note = $('#' + action + '-undo-holder').html(); el.find('.check-column :checkbox').prop('checked', false); // Uncheck the row so as not to be affected by Bulk Edits. if ( el.siblings('#replyrow').length && commentReply.cid == id ) commentReply.close(); if ( el.is('tr') ) { n = el.children(':visible').length; author = $('.author strong', el).text(); h = $('' + note + ''); } else { author = $('.comment-author', el).text(); h = $(''); } el.before(h); $('strong', '#undo-' + id).text(author); a = $('.undo a', '#undo-' + id); a.attr('href', 'comment.php?action=un' + action + 'comment&c=' + id + '&_wpnonce=' + settings.data._ajax_nonce); a.attr('data-wp-lists', 'delete:the-comment-list:comment-' + id + '::un' + action + '=1'); a.attr('class', 'vim-z vim-destructive aria-button-if-js'); $('.avatar', el).first().clone().prependTo('#undo-' + id + ' .' + action + '-undo-inside'); a.on( 'click', function( e ){ e.preventDefault(); e.stopPropagation(); // Ticket #35904. list.wpList.del(this); $('#undo-' + id).css( {backgroundColor:'#ceb'} ).fadeOut(350, function(){ $(this).remove(); $('#comment-' + id).css('backgroundColor', '').fadeIn(300, function(){ $(this).show(); }); }); }); } return settings; }; /** * Handles actions that need to be done after marking as spam or thrashing a * comment. * * The ajax requests return the unix time stamp a comment was marked as spam or * trashed. We use this to have a correct total amount of comments. * * @since 2.5.0 * @access private * * @param {Object} r Ajax response object. * @param {Object} settings Settings for the wpList object. * * @return {void} */ delAfter = function( r, settings ) { var total_items_i18n, total, animated, animatedCallback, response = true === settings.parsed ? {} : settings.parsed.responses[0], commentStatus = true === settings.parsed ? '' : response.supplemental.status, commentPostId = true === settings.parsed ? '' : response.supplemental.postId, newTotal = true === settings.parsed ? '' : response.supplemental, targetParent = $( settings.target ).parent(), commentRow = $('#' + settings.element), spamDiff, trashDiff, pendingDiff, approvedDiff, /* * As `wpList` toggles only the `unapproved` class, the approved comment * rows can have both the `approved` and `unapproved` classes. */ approved = commentRow.hasClass( 'approved' ) && ! commentRow.hasClass( 'unapproved' ), unapproved = commentRow.hasClass( 'unapproved' ), spammed = commentRow.hasClass( 'spam' ), trashed = commentRow.hasClass( 'trash' ), undoing = false; // Ticket #35904. updateDashboardText( newTotal ); updateInModerationText( newTotal ); /* * The order of these checks is important. * .unspam can also have .approve or .unapprove. * .untrash can also have .approve or .unapprove. */ if ( targetParent.is( 'span.undo' ) ) { // The comment was spammed. if ( targetParent.hasClass( 'unspam' ) ) { spamDiff = -1; if ( 'trash' === commentStatus ) { trashDiff = 1; } else if ( '1' === commentStatus ) { approvedDiff = 1; } else if ( '0' === commentStatus ) { pendingDiff = 1; } // The comment was trashed. } else if ( targetParent.hasClass( 'untrash' ) ) { trashDiff = -1; if ( 'spam' === commentStatus ) { spamDiff = 1; } else if ( '1' === commentStatus ) { approvedDiff = 1; } else if ( '0' === commentStatus ) { pendingDiff = 1; } } undoing = true; // User clicked "Spam". } else if ( targetParent.is( 'span.spam' ) ) { // The comment is currently approved. if ( approved ) { approvedDiff = -1; // The comment is currently pending. } else if ( unapproved ) { pendingDiff = -1; // The comment was in the Trash. } else if ( trashed ) { trashDiff = -1; } // You can't spam an item on the Spam screen. spamDiff = 1; // User clicked "Unspam". } else if ( targetParent.is( 'span.unspam' ) ) { if ( approved ) { pendingDiff = 1; } else if ( unapproved ) { approvedDiff = 1; } else if ( trashed ) { // The comment was previously approved. if ( targetParent.hasClass( 'approve' ) ) { approvedDiff = 1; // The comment was previously pending. } else if ( targetParent.hasClass( 'unapprove' ) ) { pendingDiff = 1; } } else if ( spammed ) { if ( targetParent.hasClass( 'approve' ) ) { approvedDiff = 1; } else if ( targetParent.hasClass( 'unapprove' ) ) { pendingDiff = 1; } } // You can unspam an item on the Spam screen. spamDiff = -1; // User clicked "Trash". } else if ( targetParent.is( 'span.trash' ) ) { if ( approved ) { approvedDiff = -1; } else if ( unapproved ) { pendingDiff = -1; // The comment was in the spam queue. } else if ( spammed ) { spamDiff = -1; } // You can't trash an item on the Trash screen. trashDiff = 1; // User clicked "Restore". } else if ( targetParent.is( 'span.untrash' ) ) { if ( approved ) { pendingDiff = 1; } else if ( unapproved ) { approvedDiff = 1; } else if ( trashed ) { if ( targetParent.hasClass( 'approve' ) ) { approvedDiff = 1; } else if ( targetParent.hasClass( 'unapprove' ) ) { pendingDiff = 1; } } // You can't go from Trash to Spam. // You can untrash on the Trash screen. trashDiff = -1; // User clicked "Approve". } else if ( targetParent.is( 'span.approve:not(.unspam):not(.untrash)' ) ) { approvedDiff = 1; pendingDiff = -1; // User clicked "Unapprove". } else if ( targetParent.is( 'span.unapprove:not(.unspam):not(.untrash)' ) ) { approvedDiff = -1; pendingDiff = 1; // User clicked "Delete Permanently". } else if ( targetParent.is( 'span.delete' ) ) { if ( spammed ) { spamDiff = -1; } else if ( trashed ) { trashDiff = -1; } } if ( pendingDiff ) { updatePending( pendingDiff, commentPostId ); updateCountText( 'span.all-count', pendingDiff ); } if ( approvedDiff ) { updateApproved( approvedDiff, commentPostId ); updateCountText( 'span.all-count', approvedDiff ); } if ( spamDiff ) { updateCountText( 'span.spam-count', spamDiff ); } if ( trashDiff ) { updateCountText( 'span.trash-count', trashDiff ); } if ( ( ( 'trash' === settings.data.comment_status ) && !getCount( $( 'span.trash-count' ) ) ) || ( ( 'spam' === settings.data.comment_status ) && !getCount( $( 'span.spam-count' ) ) ) ) { $( '#delete_all' ).hide(); } if ( ! isDashboard ) { total = totalInput.val() ? parseInt( totalInput.val(), 10 ) : 0; if ( $(settings.target).parent().is('span.undo') ) total++; else total--; if ( total < 0 ) total = 0; if ( 'object' === typeof r ) { if ( response.supplemental.total_items_i18n && lastConfidentTime < response.supplemental.time ) { total_items_i18n = response.supplemental.total_items_i18n || ''; if ( total_items_i18n ) { $('.displaying-num').text( total_items_i18n.replace( ' ', String.fromCharCode( 160 ) ) ); $('.total-pages').text( response.supplemental.total_pages_i18n.replace( ' ', String.fromCharCode( 160 ) ) ); $('.tablenav-pages').find('.next-page, .last-page').toggleClass('disabled', response.supplemental.total_pages == $('.current-page').val()); } updateTotalCount( total, response.supplemental.time, true ); } else if ( response.supplemental.time ) { updateTotalCount( total, response.supplemental.time, false ); } } else { updateTotalCount( total, r, false ); } } if ( ! theExtraList || theExtraList.length === 0 || theExtraList.children().length === 0 || undoing ) { return; } theList.get(0).wpList.add( theExtraList.children( ':eq(0):not(.no-items)' ).remove().clone() ); refillTheExtraList(); animated = $( ':animated', '#the-comment-list' ); animatedCallback = function() { if ( ! $( '#the-comment-list tr:visible' ).length ) { theList.get(0).wpList.add( theExtraList.find( '.no-items' ).clone() ); } }; if ( animated.length ) { animated.promise().done( animatedCallback ); } else { animatedCallback(); } }; /** * Retrieves additional comments to populate the extra list. * * @since 3.1.0 * @access private * * @param {boolean} [ev] Repopulate the extra comments list if true. * * @return {void} */ refillTheExtraList = function(ev) { var args = $.query.get(), total_pages = $('.total-pages').text(), per_page = $('input[name="_per_page"]', '#comments-form').val(); if (! args.paged) args.paged = 1; if (args.paged > total_pages) { return; } if (ev) { theExtraList.empty(); args.number = Math.min(8, per_page); // See WP_Comments_List_Table::prepare_items() in class-wp-comments-list-table.php. } else { args.number = 1; args.offset = Math.min(8, per_page) - 1; // Fetch only the next item on the extra list. } args.no_placeholder = true; args.paged ++; // $.query.get() needs some correction to be sent into an Ajax request. if ( true === args.comment_type ) args.comment_type = ''; args = $.extend(args, { 'action': 'fetch-list', 'list_args': list_args, '_ajax_fetch_list_nonce': $('#_ajax_fetch_list_nonce').val() }); $.ajax({ url: ajaxurl, global: false, dataType: 'json', data: args, success: function(response) { theExtraList.get(0).wpList.add( response.rows ); } }); }; /** * Globally available jQuery object referring to the extra comments list. * * @global */ window.theExtraList = $('#the-extra-comment-list').wpList( { alt: '', delColor: 'none', addColor: 'none' } ); /** * Globally available jQuery object referring to the comments list. * * @global */ window.theList = $('#the-comment-list').wpList( { alt: '', delBefore: delBefore, dimAfter: dimAfter, delAfter: delAfter, addColor: 'none' } ) .on('wpListDelEnd', function(e, s){ var wpListsData = $(s.target).attr('data-wp-lists'), id = s.element.replace(/[^0-9]+/g, ''); if ( wpListsData.indexOf(':trash=1') != -1 || wpListsData.indexOf(':spam=1') != -1 ) $('#undo-' + id).fadeIn(300, function(){ $(this).show(); }); }); }; /** * Object containing functionality regarding the comment quick editor and reply * editor. * * @since 2.7.0 * * @global */ window.commentReply = { cid : '', act : '', originalContent : '', /** * Initializes the comment reply functionality. * * @since 2.7.0 * * @memberof commentReply */ init : function() { var row = $('#replyrow'); $( '.cancel', row ).on( 'click', function() { return commentReply.revert(); } ); $( '.save', row ).on( 'click', function() { return commentReply.send(); } ); $( 'input#author-name, input#author-email, input#author-url', row ).on( 'keypress', function( e ) { if ( e.which == 13 ) { commentReply.send(); e.preventDefault(); return false; } }); // Add events. $('#the-comment-list .column-comment > p').on( 'dblclick', function(){ commentReply.toggle($(this).parent()); }); $('#doaction, #post-query-submit').on( 'click', function(){ if ( $('#the-comment-list #replyrow').length > 0 ) commentReply.close(); }); this.comments_listing = $('#comments-form > input[name="comment_status"]').val() || ''; }, /** * Adds doubleclick event handler to the given comment list row. * * The double-click event will toggle the comment edit or reply form. * * @since 2.7.0 * * @memberof commentReply * * @param {Object} r The row to add double click handlers to. * * @return {void} */ addEvents : function(r) { r.each(function() { $(this).find('.column-comment > p').on( 'dblclick', function(){ commentReply.toggle($(this).parent()); }); }); }, /** * Opens the quick edit for the given element. * * @since 2.7.0 * * @memberof commentReply * * @param {HTMLElement} el The element you want to open the quick editor for. * * @return {void} */ toggle : function(el) { if ( 'none' !== $( el ).css( 'display' ) && ( $( '#replyrow' ).parent().is('#com-reply') || window.confirm( __( 'Are you sure you want to edit this comment?\nThe changes you made will be lost.' ) ) ) ) { $( el ).find( 'button.vim-q' ).trigger( 'click' ); } }, /** * Closes the comment quick edit or reply form and undoes any changes. * * @since 2.7.0 * * @memberof commentReply * * @return {void} */ revert : function() { if ( $('#the-comment-list #replyrow').length < 1 ) return false; $('#replyrow').fadeOut('fast', function(){ commentReply.close(); }); }, /** * Closes the comment quick edit or reply form and undoes any changes. * * @since 2.7.0 * * @memberof commentReply * * @return {void} */ close : function() { var commentRow = $(), replyRow = $( '#replyrow' ); // Return if the replyrow is not showing. if ( replyRow.parent().is( '#com-reply' ) ) { return; } if ( this.cid ) { commentRow = $( '#comment-' + this.cid ); } /* * When closing the Quick Edit form, show the comment row and move focus * back to the Quick Edit button. */ if ( 'edit-comment' === this.act ) { commentRow.fadeIn( 300, function() { commentRow .show() .find( '.vim-q' ) .attr( 'aria-expanded', 'false' ) .trigger( 'focus' ); } ).css( 'backgroundColor', '' ); } // When closing the Reply form, move focus back to the Reply button. if ( 'replyto-comment' === this.act ) { commentRow.find( '.vim-r' ) .attr( 'aria-expanded', 'false' ) .trigger( 'focus' ); } // Reset the Quicktags buttons. if ( typeof QTags != 'undefined' ) QTags.closeAllTags('replycontent'); $('#add-new-comment').css('display', ''); replyRow.hide(); $( '#com-reply' ).append( replyRow ); $('#replycontent').css('height', '').val(''); $('#edithead input').val(''); $( '.notice-error', replyRow ) .addClass( 'hidden' ) .find( '.error' ).empty(); $( '.spinner', replyRow ).removeClass( 'is-active' ); this.cid = ''; this.originalContent = ''; }, /** * Opens the comment quick edit or reply form. * * @since 2.7.0 * * @memberof commentReply * * @param {number} comment_id The comment ID to open an editor for. * @param {number} post_id The post ID to open an editor for. * @param {string} action The action to perform. Either 'edit' or 'replyto'. * * @return {boolean} Always false. */ open : function(comment_id, post_id, action) { var editRow, rowData, act, replyButton, editHeight, t = this, c = $('#comment-' + comment_id), h = c.height(), colspanVal = 0; if ( ! this.discardCommentChanges() ) { return false; } t.close(); t.cid = comment_id; editRow = $('#replyrow'); rowData = $('#inline-'+comment_id); action = action || 'replyto'; act = 'edit' == action ? 'edit' : 'replyto'; act = t.act = act + '-comment'; t.originalContent = $('textarea.comment', rowData).val(); colspanVal = $( '> th:visible, > td:visible', c ).length; // Make sure it's actually a table and there's a `colspan` value to apply. if ( editRow.hasClass( 'inline-edit-row' ) && 0 !== colspanVal ) { $( 'td', editRow ).attr( 'colspan', colspanVal ); } $('#action', editRow).val(act); $('#comment_post_ID', editRow).val(post_id); $('#comment_ID', editRow).val(comment_id); if ( action == 'edit' ) { $( '#author-name', editRow ).val( $( 'div.author', rowData ).text() ); $('#author-email', editRow).val( $('div.author-email', rowData).text() ); $('#author-url', editRow).val( $('div.author-url', rowData).text() ); $('#status', editRow).val( $('div.comment_status', rowData).text() ); $('#replycontent', editRow).val( $('textarea.comment', rowData).val() ); $( '#edithead, #editlegend, #savebtn', editRow ).show(); $('#replyhead, #replybtn, #addhead, #addbtn', editRow).hide(); if ( h > 120 ) { // Limit the maximum height when editing very long comments to make it more manageable. // The textarea is resizable in most browsers, so the user can adjust it if needed. editHeight = h > 500 ? 500 : h; $('#replycontent', editRow).css('height', editHeight + 'px'); } c.after( editRow ).fadeOut('fast', function(){ $('#replyrow').fadeIn(300, function(){ $(this).show(); }); }); } else if ( action == 'add' ) { $('#addhead, #addbtn', editRow).show(); $( '#replyhead, #replybtn, #edithead, #editlegend, #savebtn', editRow ) .hide(); $('#the-comment-list').prepend(editRow); $('#replyrow').fadeIn(300); } else { replyButton = $('#replybtn', editRow); $( '#edithead, #editlegend, #savebtn, #addhead, #addbtn', editRow ).hide(); $('#replyhead, #replybtn', editRow).show(); c.after(editRow); if ( c.hasClass('unapproved') ) { replyButton.text( __( 'Approve and Reply' ) ); } else { replyButton.text( __( 'Reply' ) ); } $('#replyrow').fadeIn(300, function(){ $(this).show(); }); } setTimeout(function() { var rtop, rbottom, scrollTop, vp, scrollBottom, isComposing = false; rtop = $('#replyrow').offset().top; rbottom = rtop + $('#replyrow').height(); scrollTop = window.pageYOffset || document.documentElement.scrollTop; vp = document.documentElement.clientHeight || window.innerHeight || 0; scrollBottom = scrollTop + vp; if ( scrollBottom - 20 < rbottom ) window.scroll(0, rbottom - vp + 35); else if ( rtop - 20 < scrollTop ) window.scroll(0, rtop - 35); $( '#replycontent' ) .trigger( 'focus' ) .on( 'keyup', function( e ) { // Close on Escape except when Input Method Editors (IMEs) are in use. if ( e.which === 27 && ! isComposing ) { commentReply.revert(); } } ) .on( 'compositionstart', function() { isComposing = true; } ); }, 600); return false; }, /** * Submits the comment quick edit or reply form. * * @since 2.7.0 * * @memberof commentReply * * @return {void} */ send : function() { var post = {}, $errorNotice = $( '#replysubmit .error-notice' ); $errorNotice.addClass( 'hidden' ); $( '#replysubmit .spinner' ).addClass( 'is-active' ); $('#replyrow input').not(':button').each(function() { var t = $(this); post[ t.attr('name') ] = t.val(); }); post.content = $('#replycontent').val(); post.id = post.comment_post_ID; post.comments_listing = this.comments_listing; post.p = $('[name="p"]').val(); if ( $('#comment-' + $('#comment_ID').val()).hasClass('unapproved') ) post.approve_parent = 1; $.ajax({ type : 'POST', url : ajaxurl, data : post, success : function(x) { commentReply.show(x); }, error : function(r) { commentReply.error(r); } }); }, /** * Shows the new or updated comment or reply. * * This function needs to be passed the ajax result as received from the server. * It will handle the response and show the comment that has just been saved to * the server. * * @since 2.7.0 * * @memberof commentReply * * @param {Object} xml Ajax response object. * * @return {void} */ show : function(xml) { var t = this, r, c, id, bg, pid; if ( typeof(xml) == 'string' ) { t.error({'responseText': xml}); return false; } r = wpAjax.parseAjaxResponse(xml); if ( r.errors ) { t.error({'responseText': wpAjax.broken}); return false; } t.revert(); r = r.responses[0]; id = '#comment-' + r.id; if ( 'edit-comment' == t.act ) $(id).remove(); if ( r.supplemental.parent_approved ) { pid = $('#comment-' + r.supplemental.parent_approved); updatePending( -1, r.supplemental.parent_post_id ); if ( this.comments_listing == 'moderated' ) { pid.animate( { 'backgroundColor':'#CCEEBB' }, 400, function(){ pid.fadeOut(); }); return; } } if ( r.supplemental.i18n_comments_text ) { updateDashboardText( r.supplemental ); updateInModerationText( r.supplemental ); updateApproved( 1, r.supplemental.parent_post_id ); updateCountText( 'span.all-count', 1 ); } r.data = r.data || ''; c = r.data.toString().trim(); // Trim leading whitespaces. $(c).hide(); $('#replyrow').after(c); id = $(id); t.addEvents(id); bg = id.hasClass('unapproved') ? '#FFFFE0' : id.closest('.widefat, .postbox').css('backgroundColor'); id.animate( { 'backgroundColor':'#CCEEBB' }, 300 ) .animate( { 'backgroundColor': bg }, 300, function() { if ( pid && pid.length ) { pid.animate( { 'backgroundColor':'#CCEEBB' }, 300 ) .animate( { 'backgroundColor': bg }, 300 ) .removeClass('unapproved').addClass('approved') .find('div.comment_status').html('1'); } }); }, /** * Shows an error for the failed comment update or reply. * * @since 2.7.0 * * @memberof commentReply * * @param {string} r The Ajax response. * * @return {void} */ error : function(r) { var er = r.statusText, $errorNotice = $( '#replysubmit .notice-error' ), $error = $errorNotice.find( '.error' ); $( '#replysubmit .spinner' ).removeClass( 'is-active' ); if ( r.responseText ) er = r.responseText.replace( /<.[^<>]*?>/g, '' ); if ( er ) { $errorNotice.removeClass( 'hidden' ); $error.html( er ); wp.a11y.speak( er ); } }, /** * Opens the add comments form in the comments metabox on the post edit page. * * @since 3.4.0 * * @memberof commentReply * * @param {number} post_id The post ID. * * @return {void} */ addcomment: function(post_id) { var t = this; $('#add-new-comment').fadeOut(200, function(){ t.open(0, post_id, 'add'); $('table.comments-box').css('display', ''); $('#no-comments').remove(); }); }, /** * Alert the user if they have unsaved changes on a comment that will be lost if * they proceed with the intended action. * * @since 4.6.0 * * @memberof commentReply * * @return {boolean} Whether it is safe the continue with the intended action. */ discardCommentChanges: function() { var editRow = $( '#replyrow' ); if ( '' === $( '#replycontent', editRow ).val() || this.originalContent === $( '#replycontent', editRow ).val() ) { return true; } return window.confirm( __( 'Are you sure you want to do this?\nThe comment changes you made will be lost.' ) ); } }; $( function(){ var make_hotkeys_redirect, edit_comment, toggle_all, make_bulk; setCommentsList(); commentReply.init(); $(document).on( 'click', 'span.delete a.delete', function( e ) { e.preventDefault(); }); if ( typeof $.table_hotkeys != 'undefined' ) { /** * Creates a function that navigates to a previous or next page. * * @since 2.7.0 * @access private * * @param {string} which What page to navigate to: either next or prev. * * @return {Function} The function that executes the navigation. */ make_hotkeys_redirect = function(which) { return function() { var first_last, l; first_last = 'next' == which? 'first' : 'last'; l = $('.tablenav-pages .'+which+'-page:not(.disabled)'); if (l.length) window.location = l[0].href.replace(/\&hotkeys_highlight_(first|last)=1/g, '')+'&hotkeys_highlight_'+first_last+'=1'; }; }; /** * Navigates to the edit page for the selected comment. * * @since 2.7.0 * @access private * * @param {Object} event The event that triggered this action. * @param {Object} current_row A jQuery object of the selected row. * * @return {void} */ edit_comment = function(event, current_row) { window.location = $('span.edit a', current_row).attr('href'); }; /** * Toggles all comments on the screen, for bulk actions. * * @since 2.7.0 * @access private * * @return {void} */ toggle_all = function() { $('#cb-select-all-1').data( 'wp-toggle', 1 ).trigger( 'click' ).removeData( 'wp-toggle' ); }; /** * Creates a bulk action function that is executed on all selected comments. * * @since 2.7.0 * @access private * * @param {string} value The name of the action to execute. * * @return {Function} The function that executes the bulk action. */ make_bulk = function(value) { return function() { var scope = $('select[name="action"]'); $('option[value="' + value + '"]', scope).prop('selected', true); $('#doaction').trigger( 'click' ); }; }; $.table_hotkeys( $('table.widefat'), [ 'a', 'u', 's', 'd', 'r', 'q', 'z', ['e', edit_comment], ['shift+x', toggle_all], ['shift+a', make_bulk('approve')], ['shift+s', make_bulk('spam')], ['shift+d', make_bulk('delete')], ['shift+t', make_bulk('trash')], ['shift+z', make_bulk('untrash')], ['shift+u', make_bulk('unapprove')] ], { highlight_first: adminCommentsSettings.hotkeys_highlight_first, highlight_last: adminCommentsSettings.hotkeys_highlight_last, prev_page_link_cb: make_hotkeys_redirect('prev'), next_page_link_cb: make_hotkeys_redirect('next'), hotkeys_opts: { disableInInput: true, type: 'keypress', noDisable: '.check-column input[type="checkbox"]' }, cycle_expr: '#the-comment-list tr', start_row_index: 0 } ); } // Quick Edit and Reply have an inline comment editor. $( '#the-comment-list' ).on( 'click', '.comment-inline', function() { var $el = $( this ), action = 'replyto'; if ( 'undefined' !== typeof $el.data( 'action' ) ) { action = $el.data( 'action' ); } $( this ).attr( 'aria-expanded', 'true' ); commentReply.open( $el.data( 'commentId' ), $el.data( 'postId' ), action ); } ); }); })(jQuery); accordion.js000064400000005565147573140730007071 0ustar00/** * Accordion-folding functionality. * * Markup with the appropriate classes will be automatically hidden, * with one section opening at a time when its title is clicked. * Use the following markup structure for accordion behavior: * *
    *
    *

    *
    *
    *
    *
    *

    *
    *
    *
    *
    *

    *
    *
    *
    *
    * * Note that any appropriate tags may be used, as long as the above classes are present. * * @since 3.6.0 * @output wp-admin/js/accordion.js */ ( function( $ ){ $( function () { // Expand/Collapse accordion sections on click. $( '.accordion-container' ).on( 'click', '.accordion-section-title button', function() { accordionSwitch( $( this ) ); }); }); /** * Close the current accordion section and open a new one. * * @param {Object} el Title element of the accordion section to toggle. * @since 3.6.0 */ function accordionSwitch ( el ) { var section = el.closest( '.accordion-section' ), container = section.closest( '.accordion-container' ), siblings = container.find( '.open' ), siblingsToggleControl = siblings.find( '[aria-expanded]' ).first(), content = section.find( '.accordion-section-content' ); // This section has no content and cannot be expanded. if ( section.hasClass( 'cannot-expand' ) ) { return; } // Add a class to the container to let us know something is happening inside. // This helps in cases such as hiding a scrollbar while animations are executing. container.addClass( 'opening' ); if ( section.hasClass( 'open' ) ) { section.toggleClass( 'open' ); content.toggle( true ).slideToggle( 150 ); } else { siblingsToggleControl.attr( 'aria-expanded', 'false' ); siblings.removeClass( 'open' ); siblings.find( '.accordion-section-content' ).show().slideUp( 150 ); content.toggle( false ).slideToggle( 150 ); section.toggleClass( 'open' ); } // We have to wait for the animations to finish. setTimeout(function(){ container.removeClass( 'opening' ); }, 150); // If there's an element with an aria-expanded attribute, assume it's a toggle control and toggle the aria-expanded value. if ( el ) { el.attr( 'aria-expanded', String( el.attr( 'aria-expanded' ) === 'false' ) ); } } })(jQuery); inline-edit-tax.js000064400000017165147573140730010122 0ustar00/** * This file is used on the term overview page to power quick-editing terms. * * @output wp-admin/js/inline-edit-tax.js */ /* global ajaxurl, inlineEditTax */ window.wp = window.wp || {}; /** * Consists of functions relevant to the inline taxonomy editor. * * @namespace inlineEditTax * * @property {string} type The type of inline edit we are currently on. * @property {string} what The type property with a hash prefixed and a dash * suffixed. */ ( function( $, wp ) { window.inlineEditTax = { /** * Initializes the inline taxonomy editor by adding event handlers to be able to * quick edit. * * @since 2.7.0 * * @this inlineEditTax * @memberof inlineEditTax * @return {void} */ init : function() { var t = this, row = $('#inline-edit'); t.type = $('#the-list').attr('data-wp-lists').substr(5); t.what = '#'+t.type+'-'; $( '#the-list' ).on( 'click', '.editinline', function() { $( this ).attr( 'aria-expanded', 'true' ); inlineEditTax.edit( this ); }); /** * Cancels inline editing when pressing Escape inside the inline editor. * * @param {Object} e The keyup event that has been triggered. */ row.on( 'keyup', function( e ) { // 27 = [Escape]. if ( e.which === 27 ) { return inlineEditTax.revert(); } }); /** * Cancels inline editing when clicking the cancel button. */ $( '.cancel', row ).on( 'click', function() { return inlineEditTax.revert(); }); /** * Saves the inline edits when clicking the save button. */ $( '.save', row ).on( 'click', function() { return inlineEditTax.save(this); }); /** * Saves the inline edits when pressing Enter inside the inline editor. */ $( 'input, select', row ).on( 'keydown', function( e ) { // 13 = [Enter]. if ( e.which === 13 ) { return inlineEditTax.save( this ); } }); /** * Saves the inline edits on submitting the inline edit form. */ $( '#posts-filter input[type="submit"]' ).on( 'mousedown', function() { t.revert(); }); }, /** * Toggles the quick edit based on if it is currently shown or hidden. * * @since 2.7.0 * * @this inlineEditTax * @memberof inlineEditTax * * @param {HTMLElement} el An element within the table row or the table row * itself that we want to quick edit. * @return {void} */ toggle : function(el) { var t = this; $(t.what+t.getId(el)).css('display') === 'none' ? t.revert() : t.edit(el); }, /** * Shows the quick editor * * @since 2.7.0 * * @this inlineEditTax * @memberof inlineEditTax * * @param {string|HTMLElement} id The ID of the term we want to quick edit or an * element within the table row or the * table row itself. * @return {boolean} Always returns false. */ edit : function(id) { var editRow, rowData, val, t = this; t.revert(); // Makes sure we can pass an HTMLElement as the ID. if ( typeof(id) === 'object' ) { id = t.getId(id); } editRow = $('#inline-edit').clone(true), rowData = $('#inline_'+id); $( 'td', editRow ).attr( 'colspan', $( 'th:visible, td:visible', '.wp-list-table.widefat:first thead' ).length ); $(t.what+id).hide().after(editRow).after(''); val = $('.name', rowData); val.find( 'img' ).replaceWith( function() { return this.alt; } ); val = val.text(); $(':input[name="name"]', editRow).val( val ); val = $('.slug', rowData); val.find( 'img' ).replaceWith( function() { return this.alt; } ); val = val.text(); $(':input[name="slug"]', editRow).val( val ); $(editRow).attr('id', 'edit-'+id).addClass('inline-editor').show(); $('.ptitle', editRow).eq(0).trigger( 'focus' ); return false; }, /** * Saves the quick edit data. * * Saves the quick edit data to the server and replaces the table row with the * HTML retrieved from the server. * * @since 2.7.0 * * @this inlineEditTax * @memberof inlineEditTax * * @param {string|HTMLElement} id The ID of the term we want to quick edit or an * element within the table row or the * table row itself. * @return {boolean} Always returns false. */ save : function(id) { var params, fields, tax = $('input[name="taxonomy"]').val() || ''; // Makes sure we can pass an HTMLElement as the ID. if( typeof(id) === 'object' ) { id = this.getId(id); } $( 'table.widefat .spinner' ).addClass( 'is-active' ); params = { action: 'inline-save-tax', tax_type: this.type, tax_ID: id, taxonomy: tax }; fields = $('#edit-'+id).find(':input').serialize(); params = fields + '&' + $.param(params); // Do the Ajax request to save the data to the server. $.post( ajaxurl, params, /** * Handles the response from the server * * Handles the response from the server, replaces the table row with the response * from the server. * * @param {string} r The string with which to replace the table row. */ function(r) { var row, new_id, option_value, $errorNotice = $( '#edit-' + id + ' .inline-edit-save .notice-error' ), $error = $errorNotice.find( '.error' ); $( 'table.widefat .spinner' ).removeClass( 'is-active' ); if (r) { if ( -1 !== r.indexOf( '', { role: 'alert' } ); // Set up the notice div. resultDiv.addClass( 'notice inline' ); // Add a class indicating success or failure. resultDiv.addClass( 'notice-' + ( success ? 'success' : 'error' ) ); // Add the message, wrapping in a p tag, with a fadein to highlight each message. resultDiv.text( $( $.parseHTML( message ) ).text() ).wrapInner( '

    '); // Disable the button when the callback has succeeded. $this.prop( 'disabled', success ); // Remove any previous notices. $this.siblings( '.notice' ).remove(); // Insert the notice. $this.before( resultDiv ); } function bindPasswordForm() { var $generateButton, $cancelButton; $pass1Row = $( '.user-pass1-wrap, .user-pass-wrap, .mailserver-pass-wrap, .reset-pass-submit' ); // Hide the confirm password field when JavaScript support is enabled. $('.user-pass2-wrap').hide(); $submitButton = $( '#submit, #wp-submit' ).on( 'click', function () { updateLock = false; }); $submitButtons = $submitButton.add( ' #createusersub' ); $weakRow = $( '.pw-weak' ); $weakCheckbox = $weakRow.find( '.pw-checkbox' ); $weakCheckbox.on( 'change', function() { $submitButtons.prop( 'disabled', ! $weakCheckbox.prop( 'checked' ) ); } ); $pass1 = $('#pass1, #mailserver_pass'); if ( $pass1.length ) { bindPass1(); } else { // Password field for the login form. $pass1 = $( '#user_pass' ); } /* * Fix a LastPass mismatch issue, LastPass only changes pass2. * * This fixes the issue by copying any changes from the hidden * pass2 field to the pass1 field, then running check_pass_strength. */ $pass2 = $( '#pass2' ).on( 'input', function () { if ( $pass2.val().length > 0 ) { $pass1.val( $pass2.val() ); $pass2.val(''); currentPass = ''; $pass1.trigger( 'pwupdate' ); } } ); // Disable hidden inputs to prevent autofill and submission. if ( $pass1.is( ':hidden' ) ) { $pass1.prop( 'disabled', true ); $pass2.prop( 'disabled', true ); } $passwordWrapper = $pass1Row.find( '.wp-pwd' ); $generateButton = $pass1Row.find( 'button.wp-generate-pw' ); bindToggleButton(); $generateButton.show(); $generateButton.on( 'click', function () { updateLock = true; // Make sure the password fields are shown. $generateButton.not( '.skip-aria-expanded' ).attr( 'aria-expanded', 'true' ); $passwordWrapper .show() .addClass( 'is-open' ); // Enable the inputs when showing. $pass1.attr( 'disabled', false ); $pass2.attr( 'disabled', false ); // Set the password to the generated value. generatePassword(); // Show generated password in plaintext by default. resetToggle ( false ); // Generate the next password and cache. wp.ajax.post( 'generate-password' ) .done( function( data ) { $pass1.data( 'pw', data ); } ); } ); $cancelButton = $pass1Row.find( 'button.wp-cancel-pw' ); $cancelButton.on( 'click', function () { updateLock = false; // Disable the inputs when hiding to prevent autofill and submission. $pass1.prop( 'disabled', true ); $pass2.prop( 'disabled', true ); // Clear password field and update the UI. $pass1.val( '' ).trigger( 'pwupdate' ); resetToggle( false ); // Hide password controls. $passwordWrapper .hide() .removeClass( 'is-open' ); // Stop an empty password from being submitted as a change. $submitButtons.prop( 'disabled', false ); $generateButton.attr( 'aria-expanded', 'false' ); } ); $pass1Row.closest( 'form' ).on( 'submit', function () { updateLock = false; $pass1.prop( 'disabled', false ); $pass2.prop( 'disabled', false ); $pass2.val( $pass1.val() ); }); } function check_pass_strength() { var pass1 = $('#pass1').val(), strength; $('#pass-strength-result').removeClass('short bad good strong empty'); if ( ! pass1 || '' === pass1.trim() ) { $( '#pass-strength-result' ).addClass( 'empty' ).html( ' ' ); return; } strength = wp.passwordStrength.meter( pass1, wp.passwordStrength.userInputDisallowedList(), pass1 ); switch ( strength ) { case -1: $( '#pass-strength-result' ).addClass( 'bad' ).html( pwsL10n.unknown ); break; case 2: $('#pass-strength-result').addClass('bad').html( pwsL10n.bad ); break; case 3: $('#pass-strength-result').addClass('good').html( pwsL10n.good ); break; case 4: $('#pass-strength-result').addClass('strong').html( pwsL10n.strong ); break; case 5: $('#pass-strength-result').addClass('short').html( pwsL10n.mismatch ); break; default: $('#pass-strength-result').addClass('short').html( pwsL10n.short ); } } function showOrHideWeakPasswordCheckbox() { var passStrengthResult = $('#pass-strength-result'); if ( passStrengthResult.length ) { var passStrength = passStrengthResult[0]; if ( passStrength.className ) { $pass1.addClass( passStrength.className ); if ( $( passStrength ).is( '.short, .bad' ) ) { if ( ! $weakCheckbox.prop( 'checked' ) ) { $submitButtons.prop( 'disabled', true ); } $weakRow.show(); } else { if ( $( passStrength ).is( '.empty' ) ) { $submitButtons.prop( 'disabled', true ); $weakCheckbox.prop( 'checked', false ); } else { $submitButtons.prop( 'disabled', false ); } $weakRow.hide(); } } } } // Debug information copy section. clipboard.on( 'success', function( e ) { var triggerElement = $( e.trigger ), successElement = $( '.success', triggerElement.closest( '.application-password-display' ) ); // Clear the selection and move focus back to the trigger. e.clearSelection(); // Show success visual feedback. clearTimeout( successTimeout ); successElement.removeClass( 'hidden' ); // Hide success visual feedback after 3 seconds since last success. successTimeout = setTimeout( function() { successElement.addClass( 'hidden' ); }, 3000 ); // Handle success audible feedback. wp.a11y.speak( __( 'Application password has been copied to your clipboard.' ) ); } ); $( function() { var $colorpicker, $stylesheet, user_id, current_user_id, select = $( '#display_name' ), current_name = select.val(), greeting = $( '#wp-admin-bar-my-account' ).find( '.display-name' ); $( '#pass1' ).val( '' ).on( 'input' + ' pwupdate', check_pass_strength ); $('#pass-strength-result').show(); $('.color-palette').on( 'click', function() { $(this).siblings('input[name="admin_color"]').prop('checked', true); }); if ( select.length ) { $('#first_name, #last_name, #nickname').on( 'blur.user_profile', function() { var dub = [], inputs = { display_nickname : $('#nickname').val() || '', display_username : $('#user_login').val() || '', display_firstname : $('#first_name').val() || '', display_lastname : $('#last_name').val() || '' }; if ( inputs.display_firstname && inputs.display_lastname ) { inputs.display_firstlast = inputs.display_firstname + ' ' + inputs.display_lastname; inputs.display_lastfirst = inputs.display_lastname + ' ' + inputs.display_firstname; } $.each( $('option', select), function( i, el ){ dub.push( el.value ); }); $.each(inputs, function( id, value ) { if ( ! value ) { return; } var val = value.replace(/<\/?[a-z][^>]*>/gi, ''); if ( inputs[id].length && $.inArray( val, dub ) === -1 ) { dub.push(val); $('

    ' ); }).fail( function( response ) { $this.siblings( '.notice' ).remove(); $this.before( '' ); }); e.preventDefault(); }); window.generatePassword = generatePassword; // Warn the user if password was generated but not saved. $( window ).on( 'beforeunload', function () { if ( true === updateLock ) { return __( 'Your new password has not been saved.' ); } if ( originalFormContent !== $form.serialize() && ! isSubmitting ) { return __( 'The changes you made will be lost if you navigate away from this page.' ); } }); /* * We need to generate a password as soon as the Reset Password page is loaded, * to avoid double clicking the button to retrieve the first generated password. * See ticket #39638. */ $( function() { if ( $( '.reset-pass-submit' ).length ) { $( '.reset-pass-submit button.wp-generate-pw' ).trigger( 'click' ); } }); })(jQuery); site-health.js000064400000032231147573140730007325 0ustar00/** * Interactions used by the Site Health modules in WordPress. * * @output wp-admin/js/site-health.js */ /* global ajaxurl, ClipboardJS, SiteHealth, wp */ jQuery( function( $ ) { var __ = wp.i18n.__, _n = wp.i18n._n, sprintf = wp.i18n.sprintf, clipboard = new ClipboardJS( '.site-health-copy-buttons .copy-button' ), isStatusTab = $( '.health-check-body.health-check-status-tab' ).length, isDebugTab = $( '.health-check-body.health-check-debug-tab' ).length, pathsSizesSection = $( '#health-check-accordion-block-wp-paths-sizes' ), menuCounterWrapper = $( '#adminmenu .site-health-counter' ), menuCounter = $( '#adminmenu .site-health-counter .count' ), successTimeout; // Debug information copy section. clipboard.on( 'success', function( e ) { var triggerElement = $( e.trigger ), successElement = $( '.success', triggerElement.closest( 'div' ) ); // Clear the selection and move focus back to the trigger. e.clearSelection(); // Show success visual feedback. clearTimeout( successTimeout ); successElement.removeClass( 'hidden' ); // Hide success visual feedback after 3 seconds since last success. successTimeout = setTimeout( function() { successElement.addClass( 'hidden' ); }, 3000 ); // Handle success audible feedback. wp.a11y.speak( __( 'Site information has been copied to your clipboard.' ) ); } ); // Accordion handling in various areas. $( '.health-check-accordion' ).on( 'click', '.health-check-accordion-trigger', function() { var isExpanded = ( 'true' === $( this ).attr( 'aria-expanded' ) ); if ( isExpanded ) { $( this ).attr( 'aria-expanded', 'false' ); $( '#' + $( this ).attr( 'aria-controls' ) ).attr( 'hidden', true ); } else { $( this ).attr( 'aria-expanded', 'true' ); $( '#' + $( this ).attr( 'aria-controls' ) ).attr( 'hidden', false ); } } ); // Site Health test handling. $( '.site-health-view-passed' ).on( 'click', function() { var goodIssuesWrapper = $( '#health-check-issues-good' ); goodIssuesWrapper.toggleClass( 'hidden' ); $( this ).attr( 'aria-expanded', ! goodIssuesWrapper.hasClass( 'hidden' ) ); } ); /** * Validates the Site Health test result format. * * @since 5.6.0 * * @param {Object} issue * * @return {boolean} */ function validateIssueData( issue ) { // Expected minimum format of a valid SiteHealth test response. var minimumExpected = { test: 'string', label: 'string', description: 'string' }, passed = true, key, value, subKey, subValue; // If the issue passed is not an object, return a `false` state early. if ( 'object' !== typeof( issue ) ) { return false; } // Loop over expected data and match the data types. for ( key in minimumExpected ) { value = minimumExpected[ key ]; if ( 'object' === typeof( value ) ) { for ( subKey in value ) { subValue = value[ subKey ]; if ( 'undefined' === typeof( issue[ key ] ) || 'undefined' === typeof( issue[ key ][ subKey ] ) || subValue !== typeof( issue[ key ][ subKey ] ) ) { passed = false; } } } else { if ( 'undefined' === typeof( issue[ key ] ) || value !== typeof( issue[ key ] ) ) { passed = false; } } } return passed; } /** * Appends a new issue to the issue list. * * @since 5.2.0 * * @param {Object} issue The issue data. */ function appendIssue( issue ) { var template = wp.template( 'health-check-issue' ), issueWrapper = $( '#health-check-issues-' + issue.status ), heading, count; /* * Validate the issue data format before using it. * If the output is invalid, discard it. */ if ( ! validateIssueData( issue ) ) { return false; } SiteHealth.site_status.issues[ issue.status ]++; count = SiteHealth.site_status.issues[ issue.status ]; // If no test name is supplied, append a placeholder for markup references. if ( typeof issue.test === 'undefined' ) { issue.test = issue.status + count; } if ( 'critical' === issue.status ) { heading = sprintf( _n( '%s critical issue', '%s critical issues', count ), '' + count + '' ); } else if ( 'recommended' === issue.status ) { heading = sprintf( _n( '%s recommended improvement', '%s recommended improvements', count ), '' + count + '' ); } else if ( 'good' === issue.status ) { heading = sprintf( _n( '%s item with no issues detected', '%s items with no issues detected', count ), '' + count + '' ); } if ( heading ) { $( '.site-health-issue-count-title', issueWrapper ).html( heading ); } menuCounter.text( SiteHealth.site_status.issues.critical ); if ( 0 < parseInt( SiteHealth.site_status.issues.critical, 0 ) ) { $( '#health-check-issues-critical' ).removeClass( 'hidden' ); menuCounterWrapper.removeClass( 'count-0' ); } else { menuCounterWrapper.addClass( 'count-0' ); } if ( 0 < parseInt( SiteHealth.site_status.issues.recommended, 0 ) ) { $( '#health-check-issues-recommended' ).removeClass( 'hidden' ); } $( '.issues', '#health-check-issues-' + issue.status ).append( template( issue ) ); } /** * Updates site health status indicator as asynchronous tests are run and returned. * * @since 5.2.0 */ function recalculateProgression() { var r, c, pct; var $progress = $( '.site-health-progress' ); var $wrapper = $progress.closest( '.site-health-progress-wrapper' ); var $progressLabel = $( '.site-health-progress-label', $wrapper ); var $circle = $( '.site-health-progress svg #bar' ); var totalTests = parseInt( SiteHealth.site_status.issues.good, 0 ) + parseInt( SiteHealth.site_status.issues.recommended, 0 ) + ( parseInt( SiteHealth.site_status.issues.critical, 0 ) * 1.5 ); var failedTests = ( parseInt( SiteHealth.site_status.issues.recommended, 0 ) * 0.5 ) + ( parseInt( SiteHealth.site_status.issues.critical, 0 ) * 1.5 ); var val = 100 - Math.ceil( ( failedTests / totalTests ) * 100 ); if ( 0 === totalTests ) { $progress.addClass( 'hidden' ); return; } $wrapper.removeClass( 'loading' ); r = $circle.attr( 'r' ); c = Math.PI * ( r * 2 ); if ( 0 > val ) { val = 0; } if ( 100 < val ) { val = 100; } pct = ( ( 100 - val ) / 100 ) * c + 'px'; $circle.css( { strokeDashoffset: pct } ); if ( 80 <= val && 0 === parseInt( SiteHealth.site_status.issues.critical, 0 ) ) { $wrapper.addClass( 'green' ).removeClass( 'orange' ); $progressLabel.text( __( 'Good' ) ); announceTestsProgression( 'good' ); } else { $wrapper.addClass( 'orange' ).removeClass( 'green' ); $progressLabel.text( __( 'Should be improved' ) ); announceTestsProgression( 'improvable' ); } if ( isStatusTab ) { $.post( ajaxurl, { 'action': 'health-check-site-status-result', '_wpnonce': SiteHealth.nonce.site_status_result, 'counts': SiteHealth.site_status.issues } ); if ( 100 === val ) { $( '.site-status-all-clear' ).removeClass( 'hide' ); $( '.site-status-has-issues' ).addClass( 'hide' ); } } } /** * Queues the next asynchronous test when we're ready to run it. * * @since 5.2.0 */ function maybeRunNextAsyncTest() { var doCalculation = true; if ( 1 <= SiteHealth.site_status.async.length ) { $.each( SiteHealth.site_status.async, function() { var data = { 'action': 'health-check-' + this.test.replace( '_', '-' ), '_wpnonce': SiteHealth.nonce.site_status }; if ( this.completed ) { return true; } doCalculation = false; this.completed = true; if ( 'undefined' !== typeof( this.has_rest ) && this.has_rest ) { wp.apiRequest( { url: wp.url.addQueryArgs( this.test, { _locale: 'user' } ), headers: this.headers } ) .done( function( response ) { /** This filter is documented in wp-admin/includes/class-wp-site-health.php */ appendIssue( wp.hooks.applyFilters( 'site_status_test_result', response ) ); } ) .fail( function( response ) { var description; if ( 'undefined' !== typeof( response.responseJSON ) && 'undefined' !== typeof( response.responseJSON.message ) ) { description = response.responseJSON.message; } else { description = __( 'No details available' ); } addFailedSiteHealthCheckNotice( this.url, description ); } ) .always( function() { maybeRunNextAsyncTest(); } ); } else { $.post( ajaxurl, data ).done( function( response ) { /** This filter is documented in wp-admin/includes/class-wp-site-health.php */ appendIssue( wp.hooks.applyFilters( 'site_status_test_result', response.data ) ); } ).fail( function( response ) { var description; if ( 'undefined' !== typeof( response.responseJSON ) && 'undefined' !== typeof( response.responseJSON.message ) ) { description = response.responseJSON.message; } else { description = __( 'No details available' ); } addFailedSiteHealthCheckNotice( this.url, description ); } ).always( function() { maybeRunNextAsyncTest(); } ); } return false; } ); } if ( doCalculation ) { recalculateProgression(); } } /** * Add the details of a failed asynchronous test to the list of test results. * * @since 5.6.0 */ function addFailedSiteHealthCheckNotice( url, description ) { var issue; issue = { 'status': 'recommended', 'label': __( 'A test is unavailable' ), 'badge': { 'color': 'red', 'label': __( 'Unavailable' ) }, 'description': '

    ' + url + '

    ' + description + '

    ', 'actions': '' }; /** This filter is documented in wp-admin/includes/class-wp-site-health.php */ appendIssue( wp.hooks.applyFilters( 'site_status_test_result', issue ) ); } if ( 'undefined' !== typeof SiteHealth ) { if ( 0 === SiteHealth.site_status.direct.length && 0 === SiteHealth.site_status.async.length ) { recalculateProgression(); } else { SiteHealth.site_status.issues = { 'good': 0, 'recommended': 0, 'critical': 0 }; } if ( 0 < SiteHealth.site_status.direct.length ) { $.each( SiteHealth.site_status.direct, function() { appendIssue( this ); } ); } if ( 0 < SiteHealth.site_status.async.length ) { maybeRunNextAsyncTest(); } else { recalculateProgression(); } } function getDirectorySizes() { var timestamp = ( new Date().getTime() ); // After 3 seconds announce that we're still waiting for directory sizes. var timeout = window.setTimeout( function() { announceTestsProgression( 'waiting-for-directory-sizes' ); }, 3000 ); wp.apiRequest( { path: '/wp-site-health/v1/directory-sizes' } ).done( function( response ) { updateDirSizes( response || {} ); } ).always( function() { var delay = ( new Date().getTime() ) - timestamp; $( '.health-check-wp-paths-sizes.spinner' ).css( 'visibility', 'hidden' ); if ( delay > 3000 ) { /* * We have announced that we're waiting. * Announce that we're ready after giving at least 3 seconds * for the first announcement to be read out, or the two may collide. */ if ( delay > 6000 ) { delay = 0; } else { delay = 6500 - delay; } window.setTimeout( function() { recalculateProgression(); }, delay ); } else { // Cancel the announcement. window.clearTimeout( timeout ); } $( document ).trigger( 'site-health-info-dirsizes-done' ); } ); } function updateDirSizes( data ) { var copyButton = $( 'button.button.copy-button' ); var clipboardText = copyButton.attr( 'data-clipboard-text' ); $.each( data, function( name, value ) { var text = value.debug || value.size; if ( typeof text !== 'undefined' ) { clipboardText = clipboardText.replace( name + ': loading...', name + ': ' + text ); } } ); copyButton.attr( 'data-clipboard-text', clipboardText ); pathsSizesSection.find( 'td[class]' ).each( function( i, element ) { var td = $( element ); var name = td.attr( 'class' ); if ( data.hasOwnProperty( name ) && data[ name ].size ) { td.text( data[ name ].size ); } } ); } if ( isDebugTab ) { if ( pathsSizesSection.length ) { getDirectorySizes(); } else { recalculateProgression(); } } // Trigger a class toggle when the extended menu button is clicked. $( '.health-check-offscreen-nav-wrapper' ).on( 'click', function() { $( this ).toggleClass( 'visible' ); } ); /** * Announces to assistive technologies the tests progression status. * * @since 6.4.0 * * @param {string} type The type of message to be announced. * * @return {void} */ function announceTestsProgression( type ) { // Only announce the messages in the Site Health pages. if ( 'site-health' !== SiteHealth.screen ) { return; } switch ( type ) { case 'good': wp.a11y.speak( __( 'All site health tests have finished running. Your site is looking good.' ) ); break; case 'improvable': wp.a11y.speak( __( 'All site health tests have finished running. There are items that should be addressed.' ) ); break; case 'waiting-for-directory-sizes': wp.a11y.speak( __( 'Running additional tests... please wait.' ) ); break; default: return; } } } ); inline-edit-post.js000064400000050252147573140730010305 0ustar00/** * This file contains the functions needed for the inline editing of posts. * * @since 2.7.0 * @output wp-admin/js/inline-edit-post.js */ /* global ajaxurl, typenow, inlineEditPost */ window.wp = window.wp || {}; /** * Manages the quick edit and bulk edit windows for editing posts or pages. * * @namespace inlineEditPost * * @since 2.7.0 * * @type {Object} * * @property {string} type The type of inline editor. * @property {string} what The prefix before the post ID. * */ ( function( $, wp ) { window.inlineEditPost = { /** * Initializes the inline and bulk post editor. * * Binds event handlers to the Escape key to close the inline editor * and to the save and close buttons. Changes DOM to be ready for inline * editing. Adds event handler to bulk edit. * * @since 2.7.0 * * @memberof inlineEditPost * * @return {void} */ init : function(){ var t = this, qeRow = $('#inline-edit'), bulkRow = $('#bulk-edit'); t.type = $('table.widefat').hasClass('pages') ? 'page' : 'post'; // Post ID prefix. t.what = '#post-'; /** * Binds the Escape key to revert the changes and close the quick editor. * * @return {boolean} The result of revert. */ qeRow.on( 'keyup', function(e){ // Revert changes if Escape key is pressed. if ( e.which === 27 ) { return inlineEditPost.revert(); } }); /** * Binds the Escape key to revert the changes and close the bulk editor. * * @return {boolean} The result of revert. */ bulkRow.on( 'keyup', function(e){ // Revert changes if Escape key is pressed. if ( e.which === 27 ) { return inlineEditPost.revert(); } }); /** * Reverts changes and close the quick editor if the cancel button is clicked. * * @return {boolean} The result of revert. */ $( '.cancel', qeRow ).on( 'click', function() { return inlineEditPost.revert(); }); /** * Saves changes in the quick editor if the save(named: update) button is clicked. * * @return {boolean} The result of save. */ $( '.save', qeRow ).on( 'click', function() { return inlineEditPost.save(this); }); /** * If Enter is pressed, and the target is not the cancel button, save the post. * * @return {boolean} The result of save. */ $('td', qeRow).on( 'keydown', function(e){ if ( e.which === 13 && ! $( e.target ).hasClass( 'cancel' ) ) { return inlineEditPost.save(this); } }); /** * Reverts changes and close the bulk editor if the cancel button is clicked. * * @return {boolean} The result of revert. */ $( '.cancel', bulkRow ).on( 'click', function() { return inlineEditPost.revert(); }); /** * Disables the password input field when the private post checkbox is checked. */ $('#inline-edit .inline-edit-private input[value="private"]').on( 'click', function(){ var pw = $('input.inline-edit-password-input'); if ( $(this).prop('checked') ) { pw.val('').prop('disabled', true); } else { pw.prop('disabled', false); } }); /** * Binds click event to the .editinline button which opens the quick editor. */ $( '#the-list' ).on( 'click', '.editinline', function() { $( this ).attr( 'aria-expanded', 'true' ); inlineEditPost.edit( this ); }); // Clone quick edit categories for the bulk editor. var beCategories = $( '#inline-edit fieldset.inline-edit-categories' ).clone(); // Make "id" attributes globally unique. beCategories.find( '*[id]' ).each( function() { this.id = 'bulk-edit-' + this.id; }); $('#bulk-edit').find('fieldset:first').after( beCategories ).siblings( 'fieldset:last' ).prepend( $( '#inline-edit .inline-edit-tags-wrap' ).clone() ); $('select[name="_status"] option[value="future"]', bulkRow).remove(); /** * Adds onclick events to the apply buttons. */ $('#doaction').on( 'click', function(e){ var n, $itemsSelected = $( '#posts-filter .check-column input[type="checkbox"]:checked' ); if ( $itemsSelected.length < 1 ) { return; } t.whichBulkButtonId = $( this ).attr( 'id' ); n = t.whichBulkButtonId.substr( 2 ); if ( 'edit' === $( 'select[name="' + n + '"]' ).val() ) { e.preventDefault(); t.setBulk(); } else if ( $('form#posts-filter tr.inline-editor').length > 0 ) { t.revert(); } }); }, /** * Toggles the quick edit window, hiding it when it's active and showing it when * inactive. * * @since 2.7.0 * * @memberof inlineEditPost * * @param {Object} el Element within a post table row. */ toggle : function(el){ var t = this; $( t.what + t.getId( el ) ).css( 'display' ) === 'none' ? t.revert() : t.edit( el ); }, /** * Creates the bulk editor row to edit multiple posts at once. * * @since 2.7.0 * * @memberof inlineEditPost */ setBulk : function(){ var te = '', type = this.type, c = true; var checkedPosts = $( 'tbody th.check-column input[type="checkbox"]:checked' ); var categories = {}; this.revert(); $( '#bulk-edit td' ).attr( 'colspan', $( 'th:visible, td:visible', '.widefat:first thead' ).length ); // Insert the editor at the top of the table with an empty row above to maintain zebra striping. $('table.widefat tbody').prepend( $('#bulk-edit') ).prepend(''); $('#bulk-edit').addClass('inline-editor').show(); /** * Create a HTML div with the title and a link(delete-icon) for each selected * post. * * Get the selected posts based on the checked checkboxes in the post table. */ $( 'tbody th.check-column input[type="checkbox"]' ).each( function() { // If the checkbox for a post is selected, add the post to the edit list. if ( $(this).prop('checked') ) { c = false; var id = $( this ).val(), theTitle = $( '#inline_' + id + ' .post_title' ).html() || wp.i18n.__( '(no title)' ), buttonVisuallyHiddenText = wp.i18n.sprintf( /* translators: %s: Post title. */ wp.i18n.__( 'Remove “%s” from Bulk Edit' ), theTitle ); te += '
  • '; } }); // If no checkboxes where checked, just hide the quick/bulk edit rows. if ( c ) { return this.revert(); } // Populate the list of items to bulk edit. $( '#bulk-titles' ).html( '
      ' + te + '
    ' ); // Gather up some statistics on which of these checked posts are in which categories. checkedPosts.each( function() { var id = $( this ).val(); var checked = $( '#category_' + id ).text().split( ',' ); checked.map( function( cid ) { categories[ cid ] || ( categories[ cid ] = 0 ); // Just record that this category is checked. categories[ cid ]++; } ); } ); // Compute initial states. $( '.inline-edit-categories input[name="post_category[]"]' ).each( function() { if ( categories[ $( this ).val() ] == checkedPosts.length ) { // If the number of checked categories matches the number of selected posts, then all posts are in this category. $( this ).prop( 'checked', true ); } else if ( categories[ $( this ).val() ] > 0 ) { // If the number is less than the number of selected posts, then it's indeterminate. $( this ).prop( 'indeterminate', true ); if ( ! $( this ).parent().find( 'input[name="indeterminate_post_category[]"]' ).length ) { // Get the term label text. var label = $( this ).parent().text(); // Set indeterminate states for the backend. Add accessible text for indeterminate inputs. $( this ).after( '' ).attr( 'aria-label', label.trim() + ': ' + wp.i18n.__( 'Some selected posts have this category' ) ); } } } ); $( '.inline-edit-categories input[name="post_category[]"]:indeterminate' ).on( 'change', function() { // Remove accessible label text. Remove the indeterminate flags as there was a specific state change. $( this ).removeAttr( 'aria-label' ).parent().find( 'input[name="indeterminate_post_category[]"]' ).remove(); } ); $( '.inline-edit-save button' ).on( 'click', function() { $( '.inline-edit-categories input[name="post_category[]"]' ).prop( 'indeterminate', false ); } ); /** * Binds on click events to handle the list of items to bulk edit. * * @listens click */ $( '#bulk-titles .ntdelbutton' ).click( function() { var $this = $( this ), id = $this.attr( 'id' ).substr( 1 ), $prev = $this.parent().prev().children( '.ntdelbutton' ), $next = $this.parent().next().children( '.ntdelbutton' ); $( 'input#cb-select-all-1, input#cb-select-all-2' ).prop( 'checked', false ); $( 'table.widefat input[value="' + id + '"]' ).prop( 'checked', false ); $( '#_' + id ).parent().remove(); wp.a11y.speak( wp.i18n.__( 'Item removed.' ), 'assertive' ); // Move focus to a proper place when items are removed. if ( $next.length ) { $next.focus(); } else if ( $prev.length ) { $prev.focus(); } else { $( '#bulk-titles-list' ).remove(); inlineEditPost.revert(); wp.a11y.speak( wp.i18n.__( 'All selected items have been removed. Select new items to use Bulk Actions.' ) ); } }); // Enable auto-complete for tags when editing posts. if ( 'post' === type ) { $( 'tr.inline-editor textarea[data-wp-taxonomy]' ).each( function ( i, element ) { /* * While Quick Edit clones the form each time, Bulk Edit always re-uses * the same form. Let's check if an autocomplete instance already exists. */ if ( $( element ).autocomplete( 'instance' ) ) { // jQuery equivalent of `continue` within an `each()` loop. return; } $( element ).wpTagsSuggest(); } ); } // Set initial focus on the Bulk Edit region. $( '#bulk-edit .inline-edit-wrapper' ).attr( 'tabindex', '-1' ).focus(); // Scrolls to the top of the table where the editor is rendered. $('html, body').animate( { scrollTop: 0 }, 'fast' ); }, /** * Creates a quick edit window for the post that has been clicked. * * @since 2.7.0 * * @memberof inlineEditPost * * @param {number|Object} id The ID of the clicked post or an element within a post * table row. * @return {boolean} Always returns false at the end of execution. */ edit : function(id) { var t = this, fields, editRow, rowData, status, pageOpt, pageLevel, nextPage, pageLoop = true, nextLevel, f, val, pw; t.revert(); if ( typeof(id) === 'object' ) { id = t.getId(id); } fields = ['post_title', 'post_name', 'post_author', '_status', 'jj', 'mm', 'aa', 'hh', 'mn', 'ss', 'post_password', 'post_format', 'menu_order', 'page_template']; if ( t.type === 'page' ) { fields.push('post_parent'); } // Add the new edit row with an extra blank row underneath to maintain zebra striping. editRow = $('#inline-edit').clone(true); $( 'td', editRow ).attr( 'colspan', $( 'th:visible, td:visible', '.widefat:first thead' ).length ); // Remove the ID from the copied row and let the `for` attribute reference the hidden ID. $( 'td', editRow ).find('#quick-edit-legend').removeAttr('id'); $( 'td', editRow ).find('p[id^="quick-edit-"]').removeAttr('id'); $(t.what+id).removeClass('is-expanded').hide().after(editRow).after(''); // Populate fields in the quick edit window. rowData = $('#inline_'+id); if ( !$(':input[name="post_author"] option[value="' + $('.post_author', rowData).text() + '"]', editRow).val() ) { // The post author no longer has edit capabilities, so we need to add them to the list of authors. $(':input[name="post_author"]', editRow).prepend(''); } if ( $( ':input[name="post_author"] option', editRow ).length === 1 ) { $('label.inline-edit-author', editRow).hide(); } for ( f = 0; f < fields.length; f++ ) { val = $('.'+fields[f], rowData); /** * Replaces the image for a Twemoji(Twitter emoji) with it's alternate text. * * @return {string} Alternate text from the image. */ val.find( 'img' ).replaceWith( function() { return this.alt; } ); val = val.text(); $(':input[name="' + fields[f] + '"]', editRow).val( val ); } if ( $( '.comment_status', rowData ).text() === 'open' ) { $( 'input[name="comment_status"]', editRow ).prop( 'checked', true ); } if ( $( '.ping_status', rowData ).text() === 'open' ) { $( 'input[name="ping_status"]', editRow ).prop( 'checked', true ); } if ( $( '.sticky', rowData ).text() === 'sticky' ) { $( 'input[name="sticky"]', editRow ).prop( 'checked', true ); } /** * Creates the select boxes for the categories. */ $('.post_category', rowData).each(function(){ var taxname, term_ids = $(this).text(); if ( term_ids ) { taxname = $(this).attr('id').replace('_'+id, ''); $('ul.'+taxname+'-checklist :checkbox', editRow).val(term_ids.split(',')); } }); /** * Gets all the taxonomies for live auto-fill suggestions when typing the name * of a tag. */ $('.tags_input', rowData).each(function(){ var terms = $(this), taxname = $(this).attr('id').replace('_' + id, ''), textarea = $('textarea.tax_input_' + taxname, editRow), comma = wp.i18n._x( ',', 'tag delimiter' ).trim(); // Ensure the textarea exists. if ( ! textarea.length ) { return; } terms.find( 'img' ).replaceWith( function() { return this.alt; } ); terms = terms.text(); if ( terms ) { if ( ',' !== comma ) { terms = terms.replace(/,/g, comma); } textarea.val(terms); } textarea.wpTagsSuggest(); }); // Handle the post status. var post_date_string = $(':input[name="aa"]').val() + '-' + $(':input[name="mm"]').val() + '-' + $(':input[name="jj"]').val(); post_date_string += ' ' + $(':input[name="hh"]').val() + ':' + $(':input[name="mn"]').val() + ':' + $(':input[name="ss"]').val(); var post_date = new Date( post_date_string ); status = $('._status', rowData).text(); if ( 'future' !== status && Date.now() > post_date ) { $('select[name="_status"] option[value="future"]', editRow).remove(); } else { $('select[name="_status"] option[value="publish"]', editRow).remove(); } pw = $( '.inline-edit-password-input' ).prop( 'disabled', false ); if ( 'private' === status ) { $('input[name="keep_private"]', editRow).prop('checked', true); pw.val( '' ).prop( 'disabled', true ); } // Remove the current page and children from the parent dropdown. pageOpt = $('select[name="post_parent"] option[value="' + id + '"]', editRow); if ( pageOpt.length > 0 ) { pageLevel = pageOpt[0].className.split('-')[1]; nextPage = pageOpt; while ( pageLoop ) { nextPage = nextPage.next('option'); if ( nextPage.length === 0 ) { break; } nextLevel = nextPage[0].className.split('-')[1]; if ( nextLevel <= pageLevel ) { pageLoop = false; } else { nextPage.remove(); nextPage = pageOpt; } } pageOpt.remove(); } $(editRow).attr('id', 'edit-'+id).addClass('inline-editor').show(); $('.ptitle', editRow).trigger( 'focus' ); return false; }, /** * Saves the changes made in the quick edit window to the post. * Ajax saving is only for Quick Edit and not for bulk edit. * * @since 2.7.0 * * @param {number} id The ID for the post that has been changed. * @return {boolean} False, so the form does not submit when pressing * Enter on a focused field. */ save : function(id) { var params, fields, page = $('.post_status_page').val() || ''; if ( typeof(id) === 'object' ) { id = this.getId(id); } $( 'table.widefat .spinner' ).addClass( 'is-active' ); params = { action: 'inline-save', post_type: typenow, post_ID: id, edit_date: 'true', post_status: page }; fields = $('#edit-'+id).find(':input').serialize(); params = fields + '&' + $.param(params); // Make Ajax request. $.post( ajaxurl, params, function(r) { var $errorNotice = $( '#edit-' + id + ' .inline-edit-save .notice-error' ), $error = $errorNotice.find( '.error' ); $( 'table.widefat .spinner' ).removeClass( 'is-active' ); if (r) { if ( -1 !== r.indexOf( ']*?>/g, '' ); $errorNotice.removeClass( 'hidden' ); $error.html( r ); wp.a11y.speak( $error.text() ); } } else { $errorNotice.removeClass( 'hidden' ); $error.text( wp.i18n.__( 'Error while saving the changes.' ) ); wp.a11y.speak( wp.i18n.__( 'Error while saving the changes.' ) ); } }, 'html'); // Prevent submitting the form when pressing Enter on a focused field. return false; }, /** * Hides and empties the Quick Edit and/or Bulk Edit windows. * * @since 2.7.0 * * @memberof inlineEditPost * * @return {boolean} Always returns false. */ revert : function(){ var $tableWideFat = $( '.widefat' ), id = $( '.inline-editor', $tableWideFat ).attr( 'id' ); if ( id ) { $( '.spinner', $tableWideFat ).removeClass( 'is-active' ); if ( 'bulk-edit' === id ) { // Hide the bulk editor. $( '#bulk-edit', $tableWideFat ).removeClass( 'inline-editor' ).hide().siblings( '.hidden' ).remove(); $('#bulk-titles').empty(); // Store the empty bulk editor in a hidden element. $('#inlineedit').append( $('#bulk-edit') ); // Move focus back to the Bulk Action button that was activated. $( '#' + inlineEditPost.whichBulkButtonId ).trigger( 'focus' ); } else { // Remove both the inline-editor and its hidden tr siblings. $('#'+id).siblings('tr.hidden').addBack().remove(); id = id.substr( id.lastIndexOf('-') + 1 ); // Show the post row and move focus back to the Quick Edit button. $( this.what + id ).show().find( '.editinline' ) .attr( 'aria-expanded', 'false' ) .trigger( 'focus' ); } } return false; }, /** * Gets the ID for a the post that you want to quick edit from the row in the quick * edit table. * * @since 2.7.0 * * @memberof inlineEditPost * * @param {Object} o DOM row object to get the ID for. * @return {string} The post ID extracted from the table row in the object. */ getId : function(o) { var id = $(o).closest('tr').attr('id'), parts = id.split('-'); return parts[parts.length - 1]; } }; $( function() { inlineEditPost.init(); } ); // Show/hide locks on posts. $( function() { // Set the heartbeat interval to 10 seconds. if ( typeof wp !== 'undefined' && wp.heartbeat ) { wp.heartbeat.interval( 10 ); } }).on( 'heartbeat-tick.wp-check-locked-posts', function( e, data ) { var locked = data['wp-check-locked-posts'] || {}; $('#the-list tr').each( function(i, el) { var key = el.id, row = $(el), lock_data, avatar; if ( locked.hasOwnProperty( key ) ) { if ( ! row.hasClass('wp-locked') ) { lock_data = locked[key]; row.find('.column-title .locked-text').text( lock_data.text ); row.find('.check-column checkbox').prop('checked', false); if ( lock_data.avatar_src ) { avatar = $( '', { 'class': 'avatar avatar-18 photo', width: 18, height: 18, alt: '', src: lock_data.avatar_src, srcset: lock_data.avatar_src_2x ? lock_data.avatar_src_2x + ' 2x' : undefined } ); row.find('.column-title .locked-avatar').empty().append( avatar ); } row.addClass('wp-locked'); } } else if ( row.hasClass('wp-locked') ) { row.removeClass( 'wp-locked' ).find( '.locked-info span' ).empty(); } }); }).on( 'heartbeat-send.wp-check-locked-posts', function( e, data ) { var check = []; $('#the-list tr').each( function(i, el) { if ( el.id ) { check.push( el.id ); } }); if ( check.length ) { data['wp-check-locked-posts'] = check; } }); })( jQuery, window.wp ); password-strength-meter.js000064400000010214147573140730011723 0ustar00/** * @output wp-admin/js/password-strength-meter.js */ /* global zxcvbn */ window.wp = window.wp || {}; (function($){ var __ = wp.i18n.__, sprintf = wp.i18n.sprintf; /** * Contains functions to determine the password strength. * * @since 3.7.0 * * @namespace */ wp.passwordStrength = { /** * Determines the strength of a given password. * * Compares first password to the password confirmation. * * @since 3.7.0 * * @param {string} password1 The subject password. * @param {Array} disallowedList An array of words that will lower the entropy of * the password. * @param {string} password2 The password confirmation. * * @return {number} The password strength score. */ meter : function( password1, disallowedList, password2 ) { if ( ! Array.isArray( disallowedList ) ) disallowedList = [ disallowedList.toString() ]; if (password1 != password2 && password2 && password2.length > 0) return 5; if ( 'undefined' === typeof window.zxcvbn ) { // Password strength unknown. return -1; } var result = zxcvbn( password1, disallowedList ); return result.score; }, /** * Builds an array of words that should be penalized. * * Certain words need to be penalized because it would lower the entropy of a * password if they were used. The disallowedList is based on user input fields such * as username, first name, email etc. * * @since 3.7.0 * @deprecated 5.5.0 Use {@see 'userInputDisallowedList()'} instead. * * @return {string[]} The array of words to be disallowed. */ userInputBlacklist : function() { window.console.log( sprintf( /* translators: 1: Deprecated function name, 2: Version number, 3: Alternative function name. */ __( '%1$s is deprecated since version %2$s! Use %3$s instead. Please consider writing more inclusive code.' ), 'wp.passwordStrength.userInputBlacklist()', '5.5.0', 'wp.passwordStrength.userInputDisallowedList()' ) ); return wp.passwordStrength.userInputDisallowedList(); }, /** * Builds an array of words that should be penalized. * * Certain words need to be penalized because it would lower the entropy of a * password if they were used. The disallowed list is based on user input fields such * as username, first name, email etc. * * @since 5.5.0 * * @return {string[]} The array of words to be disallowed. */ userInputDisallowedList : function() { var i, userInputFieldsLength, rawValuesLength, currentField, rawValues = [], disallowedList = [], userInputFields = [ 'user_login', 'first_name', 'last_name', 'nickname', 'display_name', 'email', 'url', 'description', 'weblog_title', 'admin_email' ]; // Collect all the strings we want to disallow. rawValues.push( document.title ); rawValues.push( document.URL ); userInputFieldsLength = userInputFields.length; for ( i = 0; i < userInputFieldsLength; i++ ) { currentField = $( '#' + userInputFields[ i ] ); if ( 0 === currentField.length ) { continue; } rawValues.push( currentField[0].defaultValue ); rawValues.push( currentField.val() ); } /* * Strip out non-alphanumeric characters and convert each word to an * individual entry. */ rawValuesLength = rawValues.length; for ( i = 0; i < rawValuesLength; i++ ) { if ( rawValues[ i ] ) { disallowedList = disallowedList.concat( rawValues[ i ].replace( /\W/g, ' ' ).split( ' ' ) ); } } /* * Remove empty values, short words and duplicates. Short words are likely to * cause many false positives. */ disallowedList = $.grep( disallowedList, function( value, key ) { if ( '' === value || 4 > value.length ) { return false; } return $.inArray( value, disallowedList ) === key; }); return disallowedList; } }; // Backward compatibility. /** * Password strength meter function. * * @since 2.5.0 * @deprecated 3.7.0 Use wp.passwordStrength.meter instead. * * @global * * @type {wp.passwordStrength.meter} */ window.passwordStrength = wp.passwordStrength.meter; })(jQuery); accordion.min.js000064400000001366147573140730007646 0ustar00/*! This file is auto-generated */ !function(s){s(function(){s(".accordion-container").on("click",".accordion-section-title button",function(){var n,o,e,a,t,i;n=s(this),o=n.closest(".accordion-section"),e=o.closest(".accordion-container"),a=e.find(".open"),t=a.find("[aria-expanded]").first(),i=o.find(".accordion-section-content"),o.hasClass("cannot-expand")||(e.addClass("opening"),o.hasClass("open")?(o.toggleClass("open"),i.toggle(!0).slideToggle(150)):(t.attr("aria-expanded","false"),a.removeClass("open"),a.find(".accordion-section-content").show().slideUp(150),i.toggle(!1).slideToggle(150),o.toggleClass("open")),setTimeout(function(){e.removeClass("opening")},150),n&&n.attr("aria-expanded",String("false"===n.attr("aria-expanded"))))})})}(jQuery);xfn.js000064400000001344147573140730005712 0ustar00/** * Generates the XHTML Friends Network 'rel' string from the inputs. * * @deprecated 3.5.0 * @output wp-admin/js/xfn.js */ jQuery( function( $ ) { $( '#link_rel' ).prop( 'readonly', true ); $( '#linkxfndiv input' ).on( 'click keyup', function() { var isMe = $( '#me' ).is( ':checked' ), inputs = ''; $( 'input.valinp' ).each( function() { if ( isMe ) { $( this ).prop( 'disabled', true ).parent().addClass( 'disabled' ); } else { $( this ).removeAttr( 'disabled' ).parent().removeClass( 'disabled' ); if ( $( this ).is( ':checked' ) && $( this ).val() !== '') { inputs += $( this ).val() + ' '; } } }); $( '#link_rel' ).val( ( isMe ) ? 'me' : inputs.substr( 0,inputs.length - 1 ) ); }); }); password-toggle.js000064400000002473147573140730010244 0ustar00/** * Adds functionality for password visibility buttons to toggle between text and password input types. * * @since 6.3.0 * @output wp-admin/js/password-toggle.js */ ( function () { var toggleElements, status, input, icon, label, __ = wp.i18n.__; toggleElements = document.querySelectorAll( '.pwd-toggle' ); toggleElements.forEach( function (toggle) { toggle.classList.remove( 'hide-if-no-js' ); toggle.addEventListener( 'click', togglePassword ); } ); function togglePassword() { status = this.getAttribute( 'data-toggle' ); input = this.parentElement.children.namedItem( 'pwd' ); icon = this.getElementsByClassName( 'dashicons' )[ 0 ]; label = this.getElementsByClassName( 'text' )[ 0 ]; if ( 0 === parseInt( status, 10 ) ) { this.setAttribute( 'data-toggle', 1 ); this.setAttribute( 'aria-label', __( 'Hide password' ) ); input.setAttribute( 'type', 'text' ); label.innerHTML = __( 'Hide' ); icon.classList.remove( 'dashicons-visibility' ); icon.classList.add( 'dashicons-hidden' ); } else { this.setAttribute( 'data-toggle', 0 ); this.setAttribute( 'aria-label', __( 'Show password' ) ); input.setAttribute( 'type', 'password' ); label.innerHTML = __( 'Show' ); icon.classList.remove( 'dashicons-hidden' ); icon.classList.add( 'dashicons-visibility' ); } } } )(); theme.js000064400000155235147573140730006232 0ustar00/** * @output wp-admin/js/theme.js */ /* global _wpThemeSettings, confirm, tb_position */ window.wp = window.wp || {}; ( function($) { // Set up our namespace... var themes, l10n; themes = wp.themes = wp.themes || {}; // Store the theme data and settings for organized and quick access. // themes.data.settings, themes.data.themes, themes.data.l10n. themes.data = _wpThemeSettings; l10n = themes.data.l10n; // Shortcut for isInstall check. themes.isInstall = !! themes.data.settings.isInstall; // Setup app structure. _.extend( themes, { model: {}, view: {}, routes: {}, router: {}, template: wp.template }); themes.Model = Backbone.Model.extend({ // Adds attributes to the default data coming through the .org themes api. // Map `id` to `slug` for shared code. initialize: function() { var description; if ( this.get( 'slug' ) ) { // If the theme is already installed, set an attribute. if ( _.indexOf( themes.data.installedThemes, this.get( 'slug' ) ) !== -1 ) { this.set({ installed: true }); } // If the theme is active, set an attribute. if ( themes.data.activeTheme === this.get( 'slug' ) ) { this.set({ active: true }); } } // Set the attributes. this.set({ // `slug` is for installation, `id` is for existing. id: this.get( 'slug' ) || this.get( 'id' ) }); // Map `section.description` to `description` // as the API sometimes returns it differently. if ( this.has( 'sections' ) ) { description = this.get( 'sections' ).description; this.set({ description: description }); } } }); // Main view controller for themes.php. // Unifies and renders all available views. themes.view.Appearance = wp.Backbone.View.extend({ el: '#wpbody-content .wrap .theme-browser', window: $( window ), // Pagination instance. page: 0, // Sets up a throttler for binding to 'scroll'. initialize: function( options ) { // Scroller checks how far the scroll position is. _.bindAll( this, 'scroller' ); this.SearchView = options.SearchView ? options.SearchView : themes.view.Search; // Bind to the scroll event and throttle // the results from this.scroller. this.window.on( 'scroll', _.throttle( this.scroller, 300 ) ); }, // Main render control. render: function() { // Setup the main theme view // with the current theme collection. this.view = new themes.view.Themes({ collection: this.collection, parent: this }); // Render search form. this.search(); this.$el.removeClass( 'search-loading' ); // Render and append. this.view.render(); this.$el.empty().append( this.view.el ).addClass( 'rendered' ); }, // Defines search element container. searchContainer: $( '.search-form' ), // Search input and view // for current theme collection. search: function() { var view, self = this; // Don't render the search if there is only one theme. if ( themes.data.themes.length === 1 ) { return; } view = new this.SearchView({ collection: self.collection, parent: this }); self.SearchView = view; // Render and append after screen title. view.render(); this.searchContainer .find( '.search-box' ) .append( $.parseHTML( '' ) ) .append( view.el ); this.searchContainer.on( 'submit', function( event ) { event.preventDefault(); }); }, // Checks when the user gets close to the bottom // of the mage and triggers a theme:scroll event. scroller: function() { var self = this, bottom, threshold; bottom = this.window.scrollTop() + self.window.height(); threshold = self.$el.offset().top + self.$el.outerHeight( false ) - self.window.height(); threshold = Math.round( threshold * 0.9 ); if ( bottom > threshold ) { this.trigger( 'theme:scroll' ); } } }); // Set up the Collection for our theme data. // @has 'id' 'name' 'screenshot' 'author' 'authorURI' 'version' 'active' ... themes.Collection = Backbone.Collection.extend({ model: themes.Model, // Search terms. terms: '', // Controls searching on the current theme collection // and triggers an update event. doSearch: function( value ) { // Don't do anything if we've already done this search. // Useful because the Search handler fires multiple times per keystroke. if ( this.terms === value ) { return; } // Updates terms with the value passed. this.terms = value; // If we have terms, run a search... if ( this.terms.length > 0 ) { this.search( this.terms ); } // If search is blank, show all themes. // Useful for resetting the views when you clean the input. if ( this.terms === '' ) { this.reset( themes.data.themes ); $( 'body' ).removeClass( 'no-results' ); } // Trigger a 'themes:update' event. this.trigger( 'themes:update' ); }, /** * Performs a search within the collection. * * @uses RegExp */ search: function( term ) { var match, results, haystack, name, description, author; // Start with a full collection. this.reset( themes.data.themes, { silent: true } ); // Trim the term. term = term.trim(); // Escape the term string for RegExp meta characters. term = term.replace( /[-\/\\^$*+?.()|[\]{}]/g, '\\$&' ); // Consider spaces as word delimiters and match the whole string // so matching terms can be combined. term = term.replace( / /g, ')(?=.*' ); match = new RegExp( '^(?=.*' + term + ').+', 'i' ); // Find results. // _.filter() and .test(). results = this.filter( function( data ) { name = data.get( 'name' ).replace( /(<([^>]+)>)/ig, '' ); description = data.get( 'description' ).replace( /(<([^>]+)>)/ig, '' ); author = data.get( 'author' ).replace( /(<([^>]+)>)/ig, '' ); haystack = _.union( [ name, data.get( 'id' ), description, author, data.get( 'tags' ) ] ); if ( match.test( data.get( 'author' ) ) && term.length > 2 ) { data.set( 'displayAuthor', true ); } return match.test( haystack ); }); if ( results.length === 0 ) { this.trigger( 'query:empty' ); } else { $( 'body' ).removeClass( 'no-results' ); } this.reset( results ); }, // Paginates the collection with a helper method // that slices the collection. paginate: function( instance ) { var collection = this; instance = instance || 0; // Themes per instance are set at 20. collection = _( collection.rest( 20 * instance ) ); collection = _( collection.first( 20 ) ); return collection; }, count: false, /* * Handles requests for more themes and caches results. * * * When we are missing a cache object we fire an apiCall() * which triggers events of `query:success` or `query:fail`. */ query: function( request ) { /** * @static * @type Array */ var queries = this.queries, self = this, query, isPaginated, count; // Store current query request args // for later use with the event `theme:end`. this.currentQuery.request = request; // Search the query cache for matches. query = _.find( queries, function( query ) { return _.isEqual( query.request, request ); }); // If the request matches the stored currentQuery.request // it means we have a paginated request. isPaginated = _.has( request, 'page' ); // Reset the internal api page counter for non-paginated queries. if ( ! isPaginated ) { this.currentQuery.page = 1; } // Otherwise, send a new API call and add it to the cache. if ( ! query && ! isPaginated ) { query = this.apiCall( request ).done( function( data ) { // Update the collection with the queried data. if ( data.themes ) { self.reset( data.themes ); count = data.info.results; // Store the results and the query request. queries.push( { themes: data.themes, request: request, total: count } ); } // Trigger a collection refresh event // and a `query:success` event with a `count` argument. self.trigger( 'themes:update' ); self.trigger( 'query:success', count ); if ( data.themes && data.themes.length === 0 ) { self.trigger( 'query:empty' ); } }).fail( function() { self.trigger( 'query:fail' ); }); } else { // If it's a paginated request we need to fetch more themes... if ( isPaginated ) { return this.apiCall( request, isPaginated ).done( function( data ) { // Add the new themes to the current collection. // @todo Update counter. self.add( data.themes ); self.trigger( 'query:success' ); // We are done loading themes for now. self.loadingThemes = false; }).fail( function() { self.trigger( 'query:fail' ); }); } if ( query.themes.length === 0 ) { self.trigger( 'query:empty' ); } else { $( 'body' ).removeClass( 'no-results' ); } // Only trigger an update event since we already have the themes // on our cached object. if ( _.isNumber( query.total ) ) { this.count = query.total; } this.reset( query.themes ); if ( ! query.total ) { this.count = this.length; } this.trigger( 'themes:update' ); this.trigger( 'query:success', this.count ); } }, // Local cache array for API queries. queries: [], // Keep track of current query so we can handle pagination. currentQuery: { page: 1, request: {} }, // Send request to api.wordpress.org/themes. apiCall: function( request, paginated ) { return wp.ajax.send( 'query-themes', { data: { // Request data. request: _.extend({ per_page: 100 }, request) }, beforeSend: function() { if ( ! paginated ) { // Spin it. $( 'body' ).addClass( 'loading-content' ).removeClass( 'no-results' ); } } }); }, // Static status controller for when we are loading themes. loadingThemes: false }); // This is the view that controls each theme item // that will be displayed on the screen. themes.view.Theme = wp.Backbone.View.extend({ // Wrap theme data on a div.theme element. className: 'theme', // Reflects which theme view we have. // 'grid' (default) or 'detail'. state: 'grid', // The HTML template for each element to be rendered. html: themes.template( 'theme' ), events: { 'click': themes.isInstall ? 'preview': 'expand', 'keydown': themes.isInstall ? 'preview': 'expand', 'touchend': themes.isInstall ? 'preview': 'expand', 'keyup': 'addFocus', 'touchmove': 'preventExpand', 'click .theme-install': 'installTheme', 'click .update-message': 'updateTheme' }, touchDrag: false, initialize: function() { this.model.on( 'change', this.render, this ); }, render: function() { var data = this.model.toJSON(); // Render themes using the html template. this.$el.html( this.html( data ) ).attr( 'data-slug', data.id ); // Renders active theme styles. this.activeTheme(); if ( this.model.get( 'displayAuthor' ) ) { this.$el.addClass( 'display-author' ); } }, // Adds a class to the currently active theme // and to the overlay in detailed view mode. activeTheme: function() { if ( this.model.get( 'active' ) ) { this.$el.addClass( 'active' ); } }, // Add class of focus to the theme we are focused on. addFocus: function() { var $themeToFocus = ( $( ':focus' ).hasClass( 'theme' ) ) ? $( ':focus' ) : $(':focus').parents('.theme'); $('.theme.focus').removeClass('focus'); $themeToFocus.addClass('focus'); }, // Single theme overlay screen. // It's shown when clicking a theme. expand: function( event ) { var self = this; event = event || window.event; // 'Enter' and 'Space' keys expand the details view when a theme is :focused. if ( event.type === 'keydown' && ( event.which !== 13 && event.which !== 32 ) ) { return; } // Bail if the user scrolled on a touch device. if ( this.touchDrag === true ) { return this.touchDrag = false; } // Prevent the modal from showing when the user clicks // one of the direct action buttons. if ( $( event.target ).is( '.theme-actions a' ) ) { return; } // Prevent the modal from showing when the user clicks one of the direct action buttons. if ( $( event.target ).is( '.theme-actions a, .update-message, .button-link, .notice-dismiss' ) ) { return; } // Set focused theme to current element. themes.focusedTheme = this.$el; this.trigger( 'theme:expand', self.model.cid ); }, preventExpand: function() { this.touchDrag = true; }, preview: function( event ) { var self = this, current, preview; event = event || window.event; // Bail if the user scrolled on a touch device. if ( this.touchDrag === true ) { return this.touchDrag = false; } // Allow direct link path to installing a theme. if ( $( event.target ).not( '.install-theme-preview' ).parents( '.theme-actions' ).length ) { return; } // 'Enter' and 'Space' keys expand the details view when a theme is :focused. if ( event.type === 'keydown' && ( event.which !== 13 && event.which !== 32 ) ) { return; } // Pressing Enter while focused on the buttons shouldn't open the preview. if ( event.type === 'keydown' && event.which !== 13 && $( ':focus' ).hasClass( 'button' ) ) { return; } event.preventDefault(); event = event || window.event; // Set focus to current theme. themes.focusedTheme = this.$el; // Construct a new Preview view. themes.preview = preview = new themes.view.Preview({ model: this.model }); // Render the view and append it. preview.render(); this.setNavButtonsState(); // Hide previous/next navigation if there is only one theme. if ( this.model.collection.length === 1 ) { preview.$el.addClass( 'no-navigation' ); } else { preview.$el.removeClass( 'no-navigation' ); } // Append preview. $( 'div.wrap' ).append( preview.el ); // Listen to our preview object // for `theme:next` and `theme:previous` events. this.listenTo( preview, 'theme:next', function() { // Keep local track of current theme model. current = self.model; // If we have ventured away from current model update the current model position. if ( ! _.isUndefined( self.current ) ) { current = self.current; } // Get next theme model. self.current = self.model.collection.at( self.model.collection.indexOf( current ) + 1 ); // If we have no more themes, bail. if ( _.isUndefined( self.current ) ) { self.options.parent.parent.trigger( 'theme:end' ); return self.current = current; } preview.model = self.current; // Render and append. preview.render(); this.setNavButtonsState(); $( '.next-theme' ).trigger( 'focus' ); }) .listenTo( preview, 'theme:previous', function() { // Keep track of current theme model. current = self.model; // Bail early if we are at the beginning of the collection. if ( self.model.collection.indexOf( self.current ) === 0 ) { return; } // If we have ventured away from current model update the current model position. if ( ! _.isUndefined( self.current ) ) { current = self.current; } // Get previous theme model. self.current = self.model.collection.at( self.model.collection.indexOf( current ) - 1 ); // If we have no more themes, bail. if ( _.isUndefined( self.current ) ) { return; } preview.model = self.current; // Render and append. preview.render(); this.setNavButtonsState(); $( '.previous-theme' ).trigger( 'focus' ); }); this.listenTo( preview, 'preview:close', function() { self.current = self.model; }); }, // Handles .disabled classes for previous/next buttons in theme installer preview. setNavButtonsState: function() { var $themeInstaller = $( '.theme-install-overlay' ), current = _.isUndefined( this.current ) ? this.model : this.current, previousThemeButton = $themeInstaller.find( '.previous-theme' ), nextThemeButton = $themeInstaller.find( '.next-theme' ); // Disable previous at the zero position. if ( 0 === this.model.collection.indexOf( current ) ) { previousThemeButton .addClass( 'disabled' ) .prop( 'disabled', true ); nextThemeButton.trigger( 'focus' ); } // Disable next if the next model is undefined. if ( _.isUndefined( this.model.collection.at( this.model.collection.indexOf( current ) + 1 ) ) ) { nextThemeButton .addClass( 'disabled' ) .prop( 'disabled', true ); previousThemeButton.trigger( 'focus' ); } }, installTheme: function( event ) { var _this = this; event.preventDefault(); wp.updates.maybeRequestFilesystemCredentials( event ); $( document ).on( 'wp-theme-install-success', function( event, response ) { if ( _this.model.get( 'id' ) === response.slug ) { _this.model.set( { 'installed': true } ); } if ( response.blockTheme ) { _this.model.set( { 'block_theme': true } ); } } ); wp.updates.installTheme( { slug: $( event.target ).data( 'slug' ) } ); }, updateTheme: function( event ) { var _this = this; if ( ! this.model.get( 'hasPackage' ) ) { return; } event.preventDefault(); wp.updates.maybeRequestFilesystemCredentials( event ); $( document ).on( 'wp-theme-update-success', function( event, response ) { _this.model.off( 'change', _this.render, _this ); if ( _this.model.get( 'id' ) === response.slug ) { _this.model.set( { hasUpdate: false, version: response.newVersion } ); } _this.model.on( 'change', _this.render, _this ); } ); wp.updates.updateTheme( { slug: $( event.target ).parents( 'div.theme' ).first().data( 'slug' ) } ); } }); // Theme Details view. // Sets up a modal overlay with the expanded theme data. themes.view.Details = wp.Backbone.View.extend({ // Wrap theme data on a div.theme element. className: 'theme-overlay', events: { 'click': 'collapse', 'click .delete-theme': 'deleteTheme', 'click .left': 'previousTheme', 'click .right': 'nextTheme', 'click #update-theme': 'updateTheme', 'click .toggle-auto-update': 'autoupdateState' }, // The HTML template for the theme overlay. html: themes.template( 'theme-single' ), render: function() { var data = this.model.toJSON(); this.$el.html( this.html( data ) ); // Renders active theme styles. this.activeTheme(); // Set up navigation events. this.navigation(); // Checks screenshot size. this.screenshotCheck( this.$el ); // Contain "tabbing" inside the overlay. this.containFocus( this.$el ); }, // Adds a class to the currently active theme // and to the overlay in detailed view mode. activeTheme: function() { // Check the model has the active property. this.$el.toggleClass( 'active', this.model.get( 'active' ) ); }, // Set initial focus and constrain tabbing within the theme browser modal. containFocus: function( $el ) { // Set initial focus on the primary action control. _.delay( function() { $( '.theme-overlay' ).trigger( 'focus' ); }, 100 ); // Constrain tabbing within the modal. $el.on( 'keydown.wp-themes', function( event ) { var $firstFocusable = $el.find( '.theme-header button:not(.disabled)' ).first(), $lastFocusable = $el.find( '.theme-actions a:visible' ).last(); // Check for the Tab key. if ( 9 === event.which ) { if ( $firstFocusable[0] === event.target && event.shiftKey ) { $lastFocusable.trigger( 'focus' ); event.preventDefault(); } else if ( $lastFocusable[0] === event.target && ! event.shiftKey ) { $firstFocusable.trigger( 'focus' ); event.preventDefault(); } } }); }, // Single theme overlay screen. // It's shown when clicking a theme. collapse: function( event ) { var self = this, scroll; event = event || window.event; // Prevent collapsing detailed view when there is only one theme available. if ( themes.data.themes.length === 1 ) { return; } // Detect if the click is inside the overlay and don't close it // unless the target was the div.back button. if ( $( event.target ).is( '.theme-backdrop' ) || $( event.target ).is( '.close' ) || event.keyCode === 27 ) { // Add a temporary closing class while overlay fades out. $( 'body' ).addClass( 'closing-overlay' ); // With a quick fade out animation. this.$el.fadeOut( 130, function() { // Clicking outside the modal box closes the overlay. $( 'body' ).removeClass( 'closing-overlay' ); // Handle event cleanup. self.closeOverlay(); // Get scroll position to avoid jumping to the top. scroll = document.body.scrollTop; // Clean the URL structure. themes.router.navigate( themes.router.baseUrl( '' ) ); // Restore scroll position. document.body.scrollTop = scroll; // Return focus to the theme div. if ( themes.focusedTheme ) { themes.focusedTheme.find('.more-details').trigger( 'focus' ); } }); } }, // Handles .disabled classes for next/previous buttons. navigation: function() { // Disable Left/Right when at the start or end of the collection. if ( this.model.cid === this.model.collection.at(0).cid ) { this.$el.find( '.left' ) .addClass( 'disabled' ) .prop( 'disabled', true ); } if ( this.model.cid === this.model.collection.at( this.model.collection.length - 1 ).cid ) { this.$el.find( '.right' ) .addClass( 'disabled' ) .prop( 'disabled', true ); } }, // Performs the actions to effectively close // the theme details overlay. closeOverlay: function() { $( 'body' ).removeClass( 'modal-open' ); this.remove(); this.unbind(); this.trigger( 'theme:collapse' ); }, // Set state of the auto-update settings link after it has been changed and saved. autoupdateState: function() { var callback, _this = this; // Support concurrent clicks in different Theme Details overlays. callback = function( event, data ) { var autoupdate; if ( _this.model.get( 'id' ) === data.asset ) { autoupdate = _this.model.get( 'autoupdate' ); autoupdate.enabled = 'enable' === data.state; _this.model.set( { autoupdate: autoupdate } ); $( document ).off( 'wp-auto-update-setting-changed', callback ); } }; // Triggered in updates.js $( document ).on( 'wp-auto-update-setting-changed', callback ); }, updateTheme: function( event ) { var _this = this; event.preventDefault(); wp.updates.maybeRequestFilesystemCredentials( event ); $( document ).on( 'wp-theme-update-success', function( event, response ) { if ( _this.model.get( 'id' ) === response.slug ) { _this.model.set( { hasUpdate: false, version: response.newVersion } ); } _this.render(); } ); wp.updates.updateTheme( { slug: $( event.target ).data( 'slug' ) } ); }, deleteTheme: function( event ) { var _this = this, _collection = _this.model.collection, _themes = themes; event.preventDefault(); // Confirmation dialog for deleting a theme. if ( ! window.confirm( wp.themes.data.settings.confirmDelete ) ) { return; } wp.updates.maybeRequestFilesystemCredentials( event ); $( document ).one( 'wp-theme-delete-success', function( event, response ) { _this.$el.find( '.close' ).trigger( 'click' ); $( '[data-slug="' + response.slug + '"]' ).css( { backgroundColor:'#faafaa' } ).fadeOut( 350, function() { $( this ).remove(); _themes.data.themes = _.without( _themes.data.themes, _.findWhere( _themes.data.themes, { id: response.slug } ) ); $( '.wp-filter-search' ).val( '' ); _collection.doSearch( '' ); _collection.remove( _this.model ); _collection.trigger( 'themes:update' ); } ); } ); wp.updates.deleteTheme( { slug: this.model.get( 'id' ) } ); }, nextTheme: function() { var self = this; self.trigger( 'theme:next', self.model.cid ); return false; }, previousTheme: function() { var self = this; self.trigger( 'theme:previous', self.model.cid ); return false; }, // Checks if the theme screenshot is the old 300px width version // and adds a corresponding class if it's true. screenshotCheck: function( el ) { var screenshot, image; screenshot = el.find( '.screenshot img' ); image = new Image(); image.src = screenshot.attr( 'src' ); // Width check. if ( image.width && image.width <= 300 ) { el.addClass( 'small-screenshot' ); } } }); // Theme Preview view. // Sets up a modal overlay with the expanded theme data. themes.view.Preview = themes.view.Details.extend({ className: 'wp-full-overlay expanded', el: '.theme-install-overlay', events: { 'click .close-full-overlay': 'close', 'click .collapse-sidebar': 'collapse', 'click .devices button': 'previewDevice', 'click .previous-theme': 'previousTheme', 'click .next-theme': 'nextTheme', 'keyup': 'keyEvent', 'click .theme-install': 'installTheme' }, // The HTML template for the theme preview. html: themes.template( 'theme-preview' ), render: function() { var self = this, currentPreviewDevice, data = this.model.toJSON(), $body = $( document.body ); $body.attr( 'aria-busy', 'true' ); this.$el.removeClass( 'iframe-ready' ).html( this.html( data ) ); currentPreviewDevice = this.$el.data( 'current-preview-device' ); if ( currentPreviewDevice ) { self.togglePreviewDeviceButtons( currentPreviewDevice ); } themes.router.navigate( themes.router.baseUrl( themes.router.themePath + this.model.get( 'id' ) ), { replace: false } ); this.$el.fadeIn( 200, function() { $body.addClass( 'theme-installer-active full-overlay-active' ); }); this.$el.find( 'iframe' ).one( 'load', function() { self.iframeLoaded(); }); }, iframeLoaded: function() { this.$el.addClass( 'iframe-ready' ); $( document.body ).attr( 'aria-busy', 'false' ); }, close: function() { this.$el.fadeOut( 200, function() { $( 'body' ).removeClass( 'theme-installer-active full-overlay-active' ); // Return focus to the theme div. if ( themes.focusedTheme ) { themes.focusedTheme.find('.more-details').trigger( 'focus' ); } }).removeClass( 'iframe-ready' ); // Restore the previous browse tab if available. if ( themes.router.selectedTab ) { themes.router.navigate( themes.router.baseUrl( '?browse=' + themes.router.selectedTab ) ); themes.router.selectedTab = false; } else { themes.router.navigate( themes.router.baseUrl( '' ) ); } this.trigger( 'preview:close' ); this.undelegateEvents(); this.unbind(); return false; }, collapse: function( event ) { var $button = $( event.currentTarget ); if ( 'true' === $button.attr( 'aria-expanded' ) ) { $button.attr({ 'aria-expanded': 'false', 'aria-label': l10n.expandSidebar }); } else { $button.attr({ 'aria-expanded': 'true', 'aria-label': l10n.collapseSidebar }); } this.$el.toggleClass( 'collapsed' ).toggleClass( 'expanded' ); return false; }, previewDevice: function( event ) { var device = $( event.currentTarget ).data( 'device' ); this.$el .removeClass( 'preview-desktop preview-tablet preview-mobile' ) .addClass( 'preview-' + device ) .data( 'current-preview-device', device ); this.togglePreviewDeviceButtons( device ); }, togglePreviewDeviceButtons: function( newDevice ) { var $devices = $( '.wp-full-overlay-footer .devices' ); $devices.find( 'button' ) .removeClass( 'active' ) .attr( 'aria-pressed', false ); $devices.find( 'button.preview-' + newDevice ) .addClass( 'active' ) .attr( 'aria-pressed', true ); }, keyEvent: function( event ) { // The escape key closes the preview. if ( event.keyCode === 27 ) { this.undelegateEvents(); this.close(); } // The right arrow key, next theme. if ( event.keyCode === 39 ) { _.once( this.nextTheme() ); } // The left arrow key, previous theme. if ( event.keyCode === 37 ) { this.previousTheme(); } }, installTheme: function( event ) { var _this = this, $target = $( event.target ); event.preventDefault(); if ( $target.hasClass( 'disabled' ) ) { return; } wp.updates.maybeRequestFilesystemCredentials( event ); $( document ).on( 'wp-theme-install-success', function() { _this.model.set( { 'installed': true } ); } ); wp.updates.installTheme( { slug: $target.data( 'slug' ) } ); } }); // Controls the rendering of div.themes, // a wrapper that will hold all the theme elements. themes.view.Themes = wp.Backbone.View.extend({ className: 'themes wp-clearfix', $overlay: $( 'div.theme-overlay' ), // Number to keep track of scroll position // while in theme-overlay mode. index: 0, // The theme count element. count: $( '.wrap .theme-count' ), // The live themes count. liveThemeCount: 0, initialize: function( options ) { var self = this; // Set up parent. this.parent = options.parent; // Set current view to [grid]. this.setView( 'grid' ); // Move the active theme to the beginning of the collection. self.currentTheme(); // When the collection is updated by user input... this.listenTo( self.collection, 'themes:update', function() { self.parent.page = 0; self.currentTheme(); self.render( this ); } ); // Update theme count to full result set when available. this.listenTo( self.collection, 'query:success', function( count ) { if ( _.isNumber( count ) ) { self.count.text( count ); self.announceSearchResults( count ); } else { self.count.text( self.collection.length ); self.announceSearchResults( self.collection.length ); } }); this.listenTo( self.collection, 'query:empty', function() { $( 'body' ).addClass( 'no-results' ); }); this.listenTo( this.parent, 'theme:scroll', function() { self.renderThemes( self.parent.page ); }); this.listenTo( this.parent, 'theme:close', function() { if ( self.overlay ) { self.overlay.closeOverlay(); } } ); // Bind keyboard events. $( 'body' ).on( 'keyup', function( event ) { if ( ! self.overlay ) { return; } // Bail if the filesystem credentials dialog is shown. if ( $( '#request-filesystem-credentials-dialog' ).is( ':visible' ) ) { return; } // Pressing the right arrow key fires a theme:next event. if ( event.keyCode === 39 ) { self.overlay.nextTheme(); } // Pressing the left arrow key fires a theme:previous event. if ( event.keyCode === 37 ) { self.overlay.previousTheme(); } // Pressing the escape key fires a theme:collapse event. if ( event.keyCode === 27 ) { self.overlay.collapse( event ); } }); }, // Manages rendering of theme pages // and keeping theme count in sync. render: function() { // Clear the DOM, please. this.$el.empty(); // If the user doesn't have switch capabilities or there is only one theme // in the collection, render the detailed view of the active theme. if ( themes.data.themes.length === 1 ) { // Constructs the view. this.singleTheme = new themes.view.Details({ model: this.collection.models[0] }); // Render and apply a 'single-theme' class to our container. this.singleTheme.render(); this.$el.addClass( 'single-theme' ); this.$el.append( this.singleTheme.el ); } // Generate the themes using page instance // while checking the collection has items. if ( this.options.collection.size() > 0 ) { this.renderThemes( this.parent.page ); } // Display a live theme count for the collection. this.liveThemeCount = this.collection.count ? this.collection.count : this.collection.length; this.count.text( this.liveThemeCount ); /* * In the theme installer the themes count is already announced * because `announceSearchResults` is called on `query:success`. */ if ( ! themes.isInstall ) { this.announceSearchResults( this.liveThemeCount ); } }, // Iterates through each instance of the collection // and renders each theme module. renderThemes: function( page ) { var self = this; self.instance = self.collection.paginate( page ); // If we have no more themes, bail. if ( self.instance.size() === 0 ) { // Fire a no-more-themes event. this.parent.trigger( 'theme:end' ); return; } // Make sure the add-new stays at the end. if ( ! themes.isInstall && page >= 1 ) { $( '.add-new-theme' ).remove(); } // Loop through the themes and setup each theme view. self.instance.each( function( theme ) { self.theme = new themes.view.Theme({ model: theme, parent: self }); // Render the views... self.theme.render(); // ...and append them to div.themes. self.$el.append( self.theme.el ); // Binds to theme:expand to show the modal box // with the theme details. self.listenTo( self.theme, 'theme:expand', self.expand, self ); }); // 'Add new theme' element shown at the end of the grid. if ( ! themes.isInstall && themes.data.settings.canInstall ) { this.$el.append( '' ); } this.parent.page++; }, // Grabs current theme and puts it at the beginning of the collection. currentTheme: function() { var self = this, current; current = self.collection.findWhere({ active: true }); // Move the active theme to the beginning of the collection. if ( current ) { self.collection.remove( current ); self.collection.add( current, { at:0 } ); } }, // Sets current view. setView: function( view ) { return view; }, // Renders the overlay with the ThemeDetails view. // Uses the current model data. expand: function( id ) { var self = this, $card, $modal; // Set the current theme model. this.model = self.collection.get( id ); // Trigger a route update for the current model. themes.router.navigate( themes.router.baseUrl( themes.router.themePath + this.model.id ) ); // Sets this.view to 'detail'. this.setView( 'detail' ); $( 'body' ).addClass( 'modal-open' ); // Set up the theme details view. this.overlay = new themes.view.Details({ model: self.model }); this.overlay.render(); if ( this.model.get( 'hasUpdate' ) ) { $card = $( '[data-slug="' + this.model.id + '"]' ); $modal = $( this.overlay.el ); if ( $card.find( '.updating-message' ).length ) { $modal.find( '.notice-warning h3' ).remove(); $modal.find( '.notice-warning' ) .removeClass( 'notice-large' ) .addClass( 'updating-message' ) .find( 'p' ).text( wp.updates.l10n.updating ); } else if ( $card.find( '.notice-error' ).length ) { $modal.find( '.notice-warning' ).remove(); } } this.$overlay.html( this.overlay.el ); // Bind to theme:next and theme:previous triggered by the arrow keys. // Keep track of the current model so we can infer an index position. this.listenTo( this.overlay, 'theme:next', function() { // Renders the next theme on the overlay. self.next( [ self.model.cid ] ); }) .listenTo( this.overlay, 'theme:previous', function() { // Renders the previous theme on the overlay. self.previous( [ self.model.cid ] ); }); }, /* * This method renders the next theme on the overlay modal * based on the current position in the collection. * * @params [model cid] */ next: function( args ) { var self = this, model, nextModel; // Get the current theme. model = self.collection.get( args[0] ); // Find the next model within the collection. nextModel = self.collection.at( self.collection.indexOf( model ) + 1 ); // Confidence check which also serves as a boundary test. if ( nextModel !== undefined ) { // We have a new theme... // Close the overlay. this.overlay.closeOverlay(); // Trigger a route update for the current model. self.theme.trigger( 'theme:expand', nextModel.cid ); } }, /* * This method renders the previous theme on the overlay modal * based on the current position in the collection. * * @params [model cid] */ previous: function( args ) { var self = this, model, previousModel; // Get the current theme. model = self.collection.get( args[0] ); // Find the previous model within the collection. previousModel = self.collection.at( self.collection.indexOf( model ) - 1 ); if ( previousModel !== undefined ) { // We have a new theme... // Close the overlay. this.overlay.closeOverlay(); // Trigger a route update for the current model. self.theme.trigger( 'theme:expand', previousModel.cid ); } }, // Dispatch audible search results feedback message. announceSearchResults: function( count ) { if ( 0 === count ) { wp.a11y.speak( l10n.noThemesFound ); } else { wp.a11y.speak( l10n.themesFound.replace( '%d', count ) ); } } }); // Search input view controller. themes.view.Search = wp.Backbone.View.extend({ tagName: 'input', className: 'wp-filter-search', id: 'wp-filter-search-input', searching: false, attributes: { type: 'search', 'aria-describedby': 'live-search-desc' }, events: { 'input': 'search', 'keyup': 'search', 'blur': 'pushState' }, initialize: function( options ) { this.parent = options.parent; this.listenTo( this.parent, 'theme:close', function() { this.searching = false; } ); }, search: function( event ) { // Clear on escape. if ( event.type === 'keyup' && event.which === 27 ) { event.target.value = ''; } // Since doSearch is debounced, it will only run when user input comes to a rest. this.doSearch( event ); }, // Runs a search on the theme collection. doSearch: function( event ) { var options = {}; this.collection.doSearch( event.target.value.replace( /\+/g, ' ' ) ); // if search is initiated and key is not return. if ( this.searching && event.which !== 13 ) { options.replace = true; } else { this.searching = true; } // Update the URL hash. if ( event.target.value ) { themes.router.navigate( themes.router.baseUrl( themes.router.searchPath + event.target.value ), options ); } else { themes.router.navigate( themes.router.baseUrl( '' ) ); } }, pushState: function( event ) { var url = themes.router.baseUrl( '' ); if ( event.target.value ) { url = themes.router.baseUrl( themes.router.searchPath + encodeURIComponent( event.target.value ) ); } this.searching = false; themes.router.navigate( url ); } }); /** * Navigate router. * * @since 4.9.0 * * @param {string} url - URL to navigate to. * @param {Object} state - State. * @return {void} */ function navigateRouter( url, state ) { var router = this; if ( Backbone.history._hasPushState ) { Backbone.Router.prototype.navigate.call( router, url, state ); } } // Sets up the routes events for relevant url queries. // Listens to [theme] and [search] params. themes.Router = Backbone.Router.extend({ routes: { 'themes.php?theme=:slug': 'theme', 'themes.php?search=:query': 'search', 'themes.php?s=:query': 'search', 'themes.php': 'themes', '': 'themes' }, baseUrl: function( url ) { return 'themes.php' + url; }, themePath: '?theme=', searchPath: '?search=', search: function( query ) { $( '.wp-filter-search' ).val( query.replace( /\+/g, ' ' ) ); }, themes: function() { $( '.wp-filter-search' ).val( '' ); }, navigate: navigateRouter }); // Execute and setup the application. themes.Run = { init: function() { // Initializes the blog's theme library view. // Create a new collection with data. this.themes = new themes.Collection( themes.data.themes ); // Set up the view. this.view = new themes.view.Appearance({ collection: this.themes }); this.render(); // Start debouncing user searches after Backbone.history.start(). this.view.SearchView.doSearch = _.debounce( this.view.SearchView.doSearch, 500 ); }, render: function() { // Render results. this.view.render(); this.routes(); if ( Backbone.History.started ) { Backbone.history.stop(); } Backbone.history.start({ root: themes.data.settings.adminUrl, pushState: true, hashChange: false }); }, routes: function() { var self = this; // Bind to our global thx object // so that the object is available to sub-views. themes.router = new themes.Router(); // Handles theme details route event. themes.router.on( 'route:theme', function( slug ) { self.view.view.expand( slug ); }); themes.router.on( 'route:themes', function() { self.themes.doSearch( '' ); self.view.trigger( 'theme:close' ); }); // Handles search route event. themes.router.on( 'route:search', function() { $( '.wp-filter-search' ).trigger( 'keyup' ); }); this.extraRoutes(); }, extraRoutes: function() { return false; } }; // Extend the main Search view. themes.view.InstallerSearch = themes.view.Search.extend({ events: { 'input': 'search', 'keyup': 'search' }, terms: '', // Handles Ajax request for searching through themes in public repo. search: function( event ) { // Tabbing or reverse tabbing into the search input shouldn't trigger a search. if ( event.type === 'keyup' && ( event.which === 9 || event.which === 16 ) ) { return; } this.collection = this.options.parent.view.collection; // Clear on escape. if ( event.type === 'keyup' && event.which === 27 ) { event.target.value = ''; } this.doSearch( event.target.value ); }, doSearch: function( value ) { var request = {}; // Don't do anything if the search terms haven't changed. if ( this.terms === value ) { return; } // Updates terms with the value passed. this.terms = value; request.search = value; /* * Intercept an [author] search. * * If input value starts with `author:` send a request * for `author` instead of a regular `search`. */ if ( value.substring( 0, 7 ) === 'author:' ) { request.search = ''; request.author = value.slice( 7 ); } /* * Intercept a [tag] search. * * If input value starts with `tag:` send a request * for `tag` instead of a regular `search`. */ if ( value.substring( 0, 4 ) === 'tag:' ) { request.search = ''; request.tag = [ value.slice( 4 ) ]; } $( '.filter-links li > a.current' ) .removeClass( 'current' ) .removeAttr( 'aria-current' ); $( 'body' ).removeClass( 'show-filters filters-applied show-favorites-form' ); $( '.drawer-toggle' ).attr( 'aria-expanded', 'false' ); // Get the themes by sending Ajax POST request to api.wordpress.org/themes // or searching the local cache. this.collection.query( request ); // Set route. themes.router.navigate( themes.router.baseUrl( themes.router.searchPath + encodeURIComponent( value ) ), { replace: true } ); } }); themes.view.Installer = themes.view.Appearance.extend({ el: '#wpbody-content .wrap', // Register events for sorting and filters in theme-navigation. events: { 'click .filter-links li > a': 'onSort', 'click .theme-filter': 'onFilter', 'click .drawer-toggle': 'moreFilters', 'click .filter-drawer .apply-filters': 'applyFilters', 'click .filter-group [type="checkbox"]': 'addFilter', 'click .filter-drawer .clear-filters': 'clearFilters', 'click .edit-filters': 'backToFilters', 'click .favorites-form-submit' : 'saveUsername', 'keyup #wporg-username-input': 'saveUsername' }, // Initial render method. render: function() { var self = this; this.search(); this.uploader(); this.collection = new themes.Collection(); // Bump `collection.currentQuery.page` and request more themes if we hit the end of the page. this.listenTo( this, 'theme:end', function() { // Make sure we are not already loading. if ( self.collection.loadingThemes ) { return; } // Set loadingThemes to true and bump page instance of currentQuery. self.collection.loadingThemes = true; self.collection.currentQuery.page++; // Use currentQuery.page to build the themes request. _.extend( self.collection.currentQuery.request, { page: self.collection.currentQuery.page } ); self.collection.query( self.collection.currentQuery.request ); }); this.listenTo( this.collection, 'query:success', function() { $( 'body' ).removeClass( 'loading-content' ); $( '.theme-browser' ).find( 'div.error' ).remove(); }); this.listenTo( this.collection, 'query:fail', function() { $( 'body' ).removeClass( 'loading-content' ); $( '.theme-browser' ).find( 'div.error' ).remove(); $( '.theme-browser' ).find( 'div.themes' ).before( '

    ' + l10n.error + '

    ' ); $( '.theme-browser .error .try-again' ).on( 'click', function( e ) { e.preventDefault(); $( 'input.wp-filter-search' ).trigger( 'input' ); } ); }); if ( this.view ) { this.view.remove(); } // Sets up the view and passes the section argument. this.view = new themes.view.Themes({ collection: this.collection, parent: this }); // Reset pagination every time the install view handler is run. this.page = 0; // Render and append. this.$el.find( '.themes' ).remove(); this.view.render(); this.$el.find( '.theme-browser' ).append( this.view.el ).addClass( 'rendered' ); }, // Handles all the rendering of the public theme directory. browse: function( section ) { // Create a new collection with the proper theme data // for each section. if ( 'block-themes' === section ) { // Get the themes by sending Ajax POST request to api.wordpress.org/themes // or searching the local cache. this.collection.query( { tag: 'full-site-editing' } ); } else { this.collection.query( { browse: section } ); } }, // Sorting navigation. onSort: function( event ) { var $el = $( event.target ), sort = $el.data( 'sort' ); event.preventDefault(); $( 'body' ).removeClass( 'filters-applied show-filters' ); $( '.drawer-toggle' ).attr( 'aria-expanded', 'false' ); // Bail if this is already active. if ( $el.hasClass( this.activeClass ) ) { return; } this.sort( sort ); // Trigger a router.navigate update. themes.router.navigate( themes.router.baseUrl( themes.router.browsePath + sort ) ); }, sort: function( sort ) { this.clearSearch(); // Track sorting so we can restore the correct tab when closing preview. themes.router.selectedTab = sort; $( '.filter-links li > a, .theme-filter' ) .removeClass( this.activeClass ) .removeAttr( 'aria-current' ); $( '[data-sort="' + sort + '"]' ) .addClass( this.activeClass ) .attr( 'aria-current', 'page' ); if ( 'favorites' === sort ) { $( 'body' ).addClass( 'show-favorites-form' ); } else { $( 'body' ).removeClass( 'show-favorites-form' ); } this.browse( sort ); }, // Filters and Tags. onFilter: function( event ) { var request, $el = $( event.target ), filter = $el.data( 'filter' ); // Bail if this is already active. if ( $el.hasClass( this.activeClass ) ) { return; } $( '.filter-links li > a, .theme-section' ) .removeClass( this.activeClass ) .removeAttr( 'aria-current' ); $el .addClass( this.activeClass ) .attr( 'aria-current', 'page' ); if ( ! filter ) { return; } // Construct the filter request // using the default values. filter = _.union( [ filter, this.filtersChecked() ] ); request = { tag: [ filter ] }; // Get the themes by sending Ajax POST request to api.wordpress.org/themes // or searching the local cache. this.collection.query( request ); }, // Clicking on a checkbox to add another filter to the request. addFilter: function() { this.filtersChecked(); }, // Applying filters triggers a tag request. applyFilters: function( event ) { var name, tags = this.filtersChecked(), request = { tag: tags }, filteringBy = $( '.filtered-by .tags' ); if ( event ) { event.preventDefault(); } if ( ! tags ) { wp.a11y.speak( l10n.selectFeatureFilter ); return; } $( 'body' ).addClass( 'filters-applied' ); $( '.filter-links li > a.current' ) .removeClass( 'current' ) .removeAttr( 'aria-current' ); filteringBy.empty(); _.each( tags, function( tag ) { name = $( 'label[for="filter-id-' + tag + '"]' ).text(); filteringBy.append( '' + name + '' ); }); // Get the themes by sending Ajax POST request to api.wordpress.org/themes // or searching the local cache. this.collection.query( request ); }, // Save the user's WordPress.org username and get his favorite themes. saveUsername: function ( event ) { var username = $( '#wporg-username-input' ).val(), nonce = $( '#wporg-username-nonce' ).val(), request = { browse: 'favorites', user: username }, that = this; if ( event ) { event.preventDefault(); } // Save username on enter. if ( event.type === 'keyup' && event.which !== 13 ) { return; } return wp.ajax.send( 'save-wporg-username', { data: { _wpnonce: nonce, username: username }, success: function () { // Get the themes by sending Ajax POST request to api.wordpress.org/themes // or searching the local cache. that.collection.query( request ); } } ); }, /** * Get the checked filters. * * @return {Array} of tags or false */ filtersChecked: function() { var items = $( '.filter-group' ).find( ':checkbox' ), tags = []; _.each( items.filter( ':checked' ), function( item ) { tags.push( $( item ).prop( 'value' ) ); }); // When no filters are checked, restore initial state and return. if ( tags.length === 0 ) { $( '.filter-drawer .apply-filters' ).find( 'span' ).text( '' ); $( '.filter-drawer .clear-filters' ).hide(); $( 'body' ).removeClass( 'filters-applied' ); return false; } $( '.filter-drawer .apply-filters' ).find( 'span' ).text( tags.length ); $( '.filter-drawer .clear-filters' ).css( 'display', 'inline-block' ); return tags; }, activeClass: 'current', /** * When users press the "Upload Theme" button, show the upload form in place. */ uploader: function() { var uploadViewToggle = $( '.upload-view-toggle' ), $body = $( document.body ); uploadViewToggle.on( 'click', function() { // Toggle the upload view. $body.toggleClass( 'show-upload-view' ); // Toggle the `aria-expanded` button attribute. uploadViewToggle.attr( 'aria-expanded', $body.hasClass( 'show-upload-view' ) ); }); }, // Toggle the full filters navigation. moreFilters: function( event ) { var $body = $( 'body' ), $toggleButton = $( '.drawer-toggle' ); event.preventDefault(); if ( $body.hasClass( 'filters-applied' ) ) { return this.backToFilters(); } this.clearSearch(); themes.router.navigate( themes.router.baseUrl( '' ) ); // Toggle the feature filters view. $body.toggleClass( 'show-filters' ); // Toggle the `aria-expanded` button attribute. $toggleButton.attr( 'aria-expanded', $body.hasClass( 'show-filters' ) ); }, /** * Clears all the checked filters. * * @uses filtersChecked() */ clearFilters: function( event ) { var items = $( '.filter-group' ).find( ':checkbox' ), self = this; event.preventDefault(); _.each( items.filter( ':checked' ), function( item ) { $( item ).prop( 'checked', false ); return self.filtersChecked(); }); }, backToFilters: function( event ) { if ( event ) { event.preventDefault(); } $( 'body' ).removeClass( 'filters-applied' ); }, clearSearch: function() { $( '#wp-filter-search-input').val( '' ); } }); themes.InstallerRouter = Backbone.Router.extend({ routes: { 'theme-install.php?theme=:slug': 'preview', 'theme-install.php?browse=:sort': 'sort', 'theme-install.php?search=:query': 'search', 'theme-install.php': 'sort' }, baseUrl: function( url ) { return 'theme-install.php' + url; }, themePath: '?theme=', browsePath: '?browse=', searchPath: '?search=', search: function( query ) { $( '.wp-filter-search' ).val( query.replace( /\+/g, ' ' ) ); }, navigate: navigateRouter }); themes.RunInstaller = { init: function() { // Set up the view. // Passes the default 'section' as an option. this.view = new themes.view.Installer({ section: 'popular', SearchView: themes.view.InstallerSearch }); // Render results. this.render(); // Start debouncing user searches after Backbone.history.start(). this.view.SearchView.doSearch = _.debounce( this.view.SearchView.doSearch, 500 ); }, render: function() { // Render results. this.view.render(); this.routes(); if ( Backbone.History.started ) { Backbone.history.stop(); } Backbone.history.start({ root: themes.data.settings.adminUrl, pushState: true, hashChange: false }); }, routes: function() { var self = this, request = {}; // Bind to our global `wp.themes` object // so that the router is available to sub-views. themes.router = new themes.InstallerRouter(); // Handles `theme` route event. // Queries the API for the passed theme slug. themes.router.on( 'route:preview', function( slug ) { // Remove existing handlers. if ( themes.preview ) { themes.preview.undelegateEvents(); themes.preview.unbind(); } // If the theme preview is active, set the current theme. if ( self.view.view.theme && self.view.view.theme.preview ) { self.view.view.theme.model = self.view.collection.findWhere( { 'slug': slug } ); self.view.view.theme.preview(); } else { // Select the theme by slug. request.theme = slug; self.view.collection.query( request ); self.view.collection.trigger( 'update' ); // Open the theme preview. self.view.collection.once( 'query:success', function() { $( 'div[data-slug="' + slug + '"]' ).trigger( 'click' ); }); } }); /* * Handles sorting / browsing routes. * Also handles the root URL triggering a sort request * for `popular`, the default view. */ themes.router.on( 'route:sort', function( sort ) { if ( ! sort ) { sort = 'popular'; themes.router.navigate( themes.router.baseUrl( '?browse=popular' ), { replace: true } ); } self.view.sort( sort ); // Close the preview if open. if ( themes.preview ) { themes.preview.close(); } }); // The `search` route event. The router populates the input field. themes.router.on( 'route:search', function() { $( '.wp-filter-search' ).trigger( 'focus' ).trigger( 'keyup' ); }); this.extraRoutes(); }, extraRoutes: function() { return false; } }; // Ready... $( function() { if ( themes.isInstall ) { themes.RunInstaller.init(); } else { themes.Run.init(); } // Update the return param just in time. $( document.body ).on( 'click', '.load-customize', function() { var link = $( this ), urlParser = document.createElement( 'a' ); urlParser.href = link.prop( 'href' ); urlParser.search = $.param( _.extend( wp.customize.utils.parseQueryString( urlParser.search.substr( 1 ) ), { 'return': window.location.href } ) ); link.prop( 'href', urlParser.href ); }); $( '.broken-themes .delete-theme' ).on( 'click', function() { return confirm( _wpThemeSettings.settings.confirmDelete ); }); }); })( jQuery ); // Align theme browser thickbox. jQuery( function($) { window.tb_position = function() { var tbWindow = $('#TB_window'), width = $(window).width(), H = $(window).height(), W = ( 1040 < width ) ? 1040 : width, adminbar_height = 0; if ( $('#wpadminbar').length ) { adminbar_height = parseInt( $('#wpadminbar').css('height'), 10 ); } if ( tbWindow.length >= 1 ) { tbWindow.width( W - 50 ).height( H - 45 - adminbar_height ); $('#TB_iframeContent').width( W - 50 ).height( H - 75 - adminbar_height ); tbWindow.css({'margin-left': '-' + parseInt( ( ( W - 50 ) / 2 ), 10 ) + 'px'}); if ( typeof document.body.style.maxWidth !== 'undefined' ) { tbWindow.css({'top': 20 + adminbar_height + 'px', 'margin-top': '0'}); } } }; $(window).on( 'resize', function(){ tb_position(); }); }); customize-widgets.js000064400000214057147573140730010614 0ustar00/** * @output wp-admin/js/customize-widgets.js */ /* global _wpCustomizeWidgetsSettings */ (function( wp, $ ){ if ( ! wp || ! wp.customize ) { return; } // Set up our namespace... var api = wp.customize, l10n; /** * @namespace wp.customize.Widgets */ api.Widgets = api.Widgets || {}; api.Widgets.savedWidgetIds = {}; // Link settings. api.Widgets.data = _wpCustomizeWidgetsSettings || {}; l10n = api.Widgets.data.l10n; /** * wp.customize.Widgets.WidgetModel * * A single widget model. * * @class wp.customize.Widgets.WidgetModel * @augments Backbone.Model */ api.Widgets.WidgetModel = Backbone.Model.extend(/** @lends wp.customize.Widgets.WidgetModel.prototype */{ id: null, temp_id: null, classname: null, control_tpl: null, description: null, is_disabled: null, is_multi: null, multi_number: null, name: null, id_base: null, transport: null, params: [], width: null, height: null, search_matched: true }); /** * wp.customize.Widgets.WidgetCollection * * Collection for widget models. * * @class wp.customize.Widgets.WidgetCollection * @augments Backbone.Collection */ api.Widgets.WidgetCollection = Backbone.Collection.extend(/** @lends wp.customize.Widgets.WidgetCollection.prototype */{ model: api.Widgets.WidgetModel, // Controls searching on the current widget collection // and triggers an update event. doSearch: function( value ) { // Don't do anything if we've already done this search. // Useful because the search handler fires multiple times per keystroke. if ( this.terms === value ) { return; } // Updates terms with the value passed. this.terms = value; // If we have terms, run a search... if ( this.terms.length > 0 ) { this.search( this.terms ); } // If search is blank, set all the widgets as they matched the search to reset the views. if ( this.terms === '' ) { this.each( function ( widget ) { widget.set( 'search_matched', true ); } ); } }, // Performs a search within the collection. // @uses RegExp search: function( term ) { var match, haystack; // Escape the term string for RegExp meta characters. term = term.replace( /[-\/\\^$*+?.()|[\]{}]/g, '\\$&' ); // Consider spaces as word delimiters and match the whole string // so matching terms can be combined. term = term.replace( / /g, ')(?=.*' ); match = new RegExp( '^(?=.*' + term + ').+', 'i' ); this.each( function ( data ) { haystack = [ data.get( 'name' ), data.get( 'description' ) ].join( ' ' ); data.set( 'search_matched', match.test( haystack ) ); } ); } }); api.Widgets.availableWidgets = new api.Widgets.WidgetCollection( api.Widgets.data.availableWidgets ); /** * wp.customize.Widgets.SidebarModel * * A single sidebar model. * * @class wp.customize.Widgets.SidebarModel * @augments Backbone.Model */ api.Widgets.SidebarModel = Backbone.Model.extend(/** @lends wp.customize.Widgets.SidebarModel.prototype */{ after_title: null, after_widget: null, before_title: null, before_widget: null, 'class': null, description: null, id: null, name: null, is_rendered: false }); /** * wp.customize.Widgets.SidebarCollection * * Collection for sidebar models. * * @class wp.customize.Widgets.SidebarCollection * @augments Backbone.Collection */ api.Widgets.SidebarCollection = Backbone.Collection.extend(/** @lends wp.customize.Widgets.SidebarCollection.prototype */{ model: api.Widgets.SidebarModel }); api.Widgets.registeredSidebars = new api.Widgets.SidebarCollection( api.Widgets.data.registeredSidebars ); api.Widgets.AvailableWidgetsPanelView = wp.Backbone.View.extend(/** @lends wp.customize.Widgets.AvailableWidgetsPanelView.prototype */{ el: '#available-widgets', events: { 'input #widgets-search': 'search', 'focus .widget-tpl' : 'focus', 'click .widget-tpl' : '_submit', 'keypress .widget-tpl' : '_submit', 'keydown' : 'keyboardAccessible' }, // Cache current selected widget. selected: null, // Cache sidebar control which has opened panel. currentSidebarControl: null, $search: null, $clearResults: null, searchMatchesCount: null, /** * View class for the available widgets panel. * * @constructs wp.customize.Widgets.AvailableWidgetsPanelView * @augments wp.Backbone.View */ initialize: function() { var self = this; this.$search = $( '#widgets-search' ); this.$clearResults = this.$el.find( '.clear-results' ); _.bindAll( this, 'close' ); this.listenTo( this.collection, 'change', this.updateList ); this.updateList(); // Set the initial search count to the number of available widgets. this.searchMatchesCount = this.collection.length; /* * If the available widgets panel is open and the customize controls * are interacted with (i.e. available widgets panel is blurred) then * close the available widgets panel. Also close on back button click. */ $( '#customize-controls, #available-widgets .customize-section-title' ).on( 'click keydown', function( e ) { var isAddNewBtn = $( e.target ).is( '.add-new-widget, .add-new-widget *' ); if ( $( 'body' ).hasClass( 'adding-widget' ) && ! isAddNewBtn ) { self.close(); } } ); // Clear the search results and trigger an `input` event to fire a new search. this.$clearResults.on( 'click', function() { self.$search.val( '' ).trigger( 'focus' ).trigger( 'input' ); } ); // Close the panel if the URL in the preview changes. api.previewer.bind( 'url', this.close ); }, /** * Performs a search and handles selected widget. */ search: _.debounce( function( event ) { var firstVisible; this.collection.doSearch( event.target.value ); // Update the search matches count. this.updateSearchMatchesCount(); // Announce how many search results. this.announceSearchMatches(); // Remove a widget from being selected if it is no longer visible. if ( this.selected && ! this.selected.is( ':visible' ) ) { this.selected.removeClass( 'selected' ); this.selected = null; } // If a widget was selected but the filter value has been cleared out, clear selection. if ( this.selected && ! event.target.value ) { this.selected.removeClass( 'selected' ); this.selected = null; } // If a filter has been entered and a widget hasn't been selected, select the first one shown. if ( ! this.selected && event.target.value ) { firstVisible = this.$el.find( '> .widget-tpl:visible:first' ); if ( firstVisible.length ) { this.select( firstVisible ); } } // Toggle the clear search results button. if ( '' !== event.target.value ) { this.$clearResults.addClass( 'is-visible' ); } else if ( '' === event.target.value ) { this.$clearResults.removeClass( 'is-visible' ); } // Set a CSS class on the search container when there are no search results. if ( ! this.searchMatchesCount ) { this.$el.addClass( 'no-widgets-found' ); } else { this.$el.removeClass( 'no-widgets-found' ); } }, 500 ), /** * Updates the count of the available widgets that have the `search_matched` attribute. */ updateSearchMatchesCount: function() { this.searchMatchesCount = this.collection.where({ search_matched: true }).length; }, /** * Sends a message to the aria-live region to announce how many search results. */ announceSearchMatches: function() { var message = l10n.widgetsFound.replace( '%d', this.searchMatchesCount ) ; if ( ! this.searchMatchesCount ) { message = l10n.noWidgetsFound; } wp.a11y.speak( message ); }, /** * Changes visibility of available widgets. */ updateList: function() { this.collection.each( function( widget ) { var widgetTpl = $( '#widget-tpl-' + widget.id ); widgetTpl.toggle( widget.get( 'search_matched' ) && ! widget.get( 'is_disabled' ) ); if ( widget.get( 'is_disabled' ) && widgetTpl.is( this.selected ) ) { this.selected = null; } } ); }, /** * Highlights a widget. */ select: function( widgetTpl ) { this.selected = $( widgetTpl ); this.selected.siblings( '.widget-tpl' ).removeClass( 'selected' ); this.selected.addClass( 'selected' ); }, /** * Highlights a widget on focus. */ focus: function( event ) { this.select( $( event.currentTarget ) ); }, /** * Handles submit for keypress and click on widget. */ _submit: function( event ) { // Only proceed with keypress if it is Enter or Spacebar. if ( event.type === 'keypress' && ( event.which !== 13 && event.which !== 32 ) ) { return; } this.submit( $( event.currentTarget ) ); }, /** * Adds a selected widget to the sidebar. */ submit: function( widgetTpl ) { var widgetId, widget, widgetFormControl; if ( ! widgetTpl ) { widgetTpl = this.selected; } if ( ! widgetTpl || ! this.currentSidebarControl ) { return; } this.select( widgetTpl ); widgetId = $( this.selected ).data( 'widget-id' ); widget = this.collection.findWhere( { id: widgetId } ); if ( ! widget ) { return; } widgetFormControl = this.currentSidebarControl.addWidget( widget.get( 'id_base' ) ); if ( widgetFormControl ) { widgetFormControl.focus(); } this.close(); }, /** * Opens the panel. */ open: function( sidebarControl ) { this.currentSidebarControl = sidebarControl; // Wide widget controls appear over the preview, and so they need to be collapsed when the panel opens. _( this.currentSidebarControl.getWidgetFormControls() ).each( function( control ) { if ( control.params.is_wide ) { control.collapseForm(); } } ); if ( api.section.has( 'publish_settings' ) ) { api.section( 'publish_settings' ).collapse(); } $( 'body' ).addClass( 'adding-widget' ); this.$el.find( '.selected' ).removeClass( 'selected' ); // Reset search. this.collection.doSearch( '' ); if ( ! api.settings.browser.mobile ) { this.$search.trigger( 'focus' ); } }, /** * Closes the panel. */ close: function( options ) { options = options || {}; if ( options.returnFocus && this.currentSidebarControl ) { this.currentSidebarControl.container.find( '.add-new-widget' ).focus(); } this.currentSidebarControl = null; this.selected = null; $( 'body' ).removeClass( 'adding-widget' ); this.$search.val( '' ).trigger( 'input' ); }, /** * Adds keyboard accessibility to the panel. */ keyboardAccessible: function( event ) { var isEnter = ( event.which === 13 ), isEsc = ( event.which === 27 ), isDown = ( event.which === 40 ), isUp = ( event.which === 38 ), isTab = ( event.which === 9 ), isShift = ( event.shiftKey ), selected = null, firstVisible = this.$el.find( '> .widget-tpl:visible:first' ), lastVisible = this.$el.find( '> .widget-tpl:visible:last' ), isSearchFocused = $( event.target ).is( this.$search ), isLastWidgetFocused = $( event.target ).is( '.widget-tpl:visible:last' ); if ( isDown || isUp ) { if ( isDown ) { if ( isSearchFocused ) { selected = firstVisible; } else if ( this.selected && this.selected.nextAll( '.widget-tpl:visible' ).length !== 0 ) { selected = this.selected.nextAll( '.widget-tpl:visible:first' ); } } else if ( isUp ) { if ( isSearchFocused ) { selected = lastVisible; } else if ( this.selected && this.selected.prevAll( '.widget-tpl:visible' ).length !== 0 ) { selected = this.selected.prevAll( '.widget-tpl:visible:first' ); } } this.select( selected ); if ( selected ) { selected.trigger( 'focus' ); } else { this.$search.trigger( 'focus' ); } return; } // If enter pressed but nothing entered, don't do anything. if ( isEnter && ! this.$search.val() ) { return; } if ( isEnter ) { this.submit(); } else if ( isEsc ) { this.close( { returnFocus: true } ); } if ( this.currentSidebarControl && isTab && ( isShift && isSearchFocused || ! isShift && isLastWidgetFocused ) ) { this.currentSidebarControl.container.find( '.add-new-widget' ).focus(); event.preventDefault(); } } }); /** * Handlers for the widget-synced event, organized by widget ID base. * Other widgets may provide their own update handlers by adding * listeners for the widget-synced event. * * @alias wp.customize.Widgets.formSyncHandlers */ api.Widgets.formSyncHandlers = { /** * @param {jQuery.Event} e * @param {jQuery} widget * @param {string} newForm */ rss: function( e, widget, newForm ) { var oldWidgetError = widget.find( '.widget-error:first' ), newWidgetError = $( '
    ' + newForm + '
    ' ).find( '.widget-error:first' ); if ( oldWidgetError.length && newWidgetError.length ) { oldWidgetError.replaceWith( newWidgetError ); } else if ( oldWidgetError.length ) { oldWidgetError.remove(); } else if ( newWidgetError.length ) { widget.find( '.widget-content:first' ).prepend( newWidgetError ); } } }; api.Widgets.WidgetControl = api.Control.extend(/** @lends wp.customize.Widgets.WidgetControl.prototype */{ defaultExpandedArguments: { duration: 'fast', completeCallback: $.noop }, /** * wp.customize.Widgets.WidgetControl * * Customizer control for widgets. * Note that 'widget_form' must match the WP_Widget_Form_Customize_Control::$type * * @since 4.1.0 * * @constructs wp.customize.Widgets.WidgetControl * @augments wp.customize.Control */ initialize: function( id, options ) { var control = this; control.widgetControlEmbedded = false; control.widgetContentEmbedded = false; control.expanded = new api.Value( false ); control.expandedArgumentsQueue = []; control.expanded.bind( function( expanded ) { var args = control.expandedArgumentsQueue.shift(); args = $.extend( {}, control.defaultExpandedArguments, args ); control.onChangeExpanded( expanded, args ); }); control.altNotice = true; api.Control.prototype.initialize.call( control, id, options ); }, /** * Set up the control. * * @since 3.9.0 */ ready: function() { var control = this; /* * Embed a placeholder once the section is expanded. The full widget * form content will be embedded once the control itself is expanded, * and at this point the widget-added event will be triggered. */ if ( ! control.section() ) { control.embedWidgetControl(); } else { api.section( control.section(), function( section ) { var onExpanded = function( isExpanded ) { if ( isExpanded ) { control.embedWidgetControl(); section.expanded.unbind( onExpanded ); } }; if ( section.expanded() ) { onExpanded( true ); } else { section.expanded.bind( onExpanded ); } } ); } }, /** * Embed the .widget element inside the li container. * * @since 4.4.0 */ embedWidgetControl: function() { var control = this, widgetControl; if ( control.widgetControlEmbedded ) { return; } control.widgetControlEmbedded = true; widgetControl = $( control.params.widget_control ); control.container.append( widgetControl ); control._setupModel(); control._setupWideWidget(); control._setupControlToggle(); control._setupWidgetTitle(); control._setupReorderUI(); control._setupHighlightEffects(); control._setupUpdateUI(); control._setupRemoveUI(); }, /** * Embed the actual widget form inside of .widget-content and finally trigger the widget-added event. * * @since 4.4.0 */ embedWidgetContent: function() { var control = this, widgetContent; control.embedWidgetControl(); if ( control.widgetContentEmbedded ) { return; } control.widgetContentEmbedded = true; // Update the notification container element now that the widget content has been embedded. control.notifications.container = control.getNotificationsContainerElement(); control.notifications.render(); widgetContent = $( control.params.widget_content ); control.container.find( '.widget-content:first' ).append( widgetContent ); /* * Trigger widget-added event so that plugins can attach any event * listeners and dynamic UI elements. */ $( document ).trigger( 'widget-added', [ control.container.find( '.widget:first' ) ] ); }, /** * Handle changes to the setting */ _setupModel: function() { var self = this, rememberSavedWidgetId; // Remember saved widgets so we know which to trash (move to inactive widgets sidebar). rememberSavedWidgetId = function() { api.Widgets.savedWidgetIds[self.params.widget_id] = true; }; api.bind( 'ready', rememberSavedWidgetId ); api.bind( 'saved', rememberSavedWidgetId ); this._updateCount = 0; this.isWidgetUpdating = false; this.liveUpdateMode = true; // Update widget whenever model changes. this.setting.bind( function( to, from ) { if ( ! _( from ).isEqual( to ) && ! self.isWidgetUpdating ) { self.updateWidget( { instance: to } ); } } ); }, /** * Add special behaviors for wide widget controls */ _setupWideWidget: function() { var self = this, $widgetInside, $widgetForm, $customizeSidebar, $themeControlsContainer, positionWidget; if ( ! this.params.is_wide || $( window ).width() <= 640 /* max-width breakpoint in customize-controls.css */ ) { return; } $widgetInside = this.container.find( '.widget-inside' ); $widgetForm = $widgetInside.find( '> .form' ); $customizeSidebar = $( '.wp-full-overlay-sidebar-content:first' ); this.container.addClass( 'wide-widget-control' ); this.container.find( '.form:first' ).css( { 'max-width': this.params.width, 'min-height': this.params.height } ); /** * Keep the widget-inside positioned so the top of fixed-positioned * element is at the same top position as the widget-top. When the * widget-top is scrolled out of view, keep the widget-top in view; * likewise, don't allow the widget to drop off the bottom of the window. * If a widget is too tall to fit in the window, don't let the height * exceed the window height so that the contents of the widget control * will become scrollable (overflow:auto). */ positionWidget = function() { var offsetTop = self.container.offset().top, windowHeight = $( window ).height(), formHeight = $widgetForm.outerHeight(), top; $widgetInside.css( 'max-height', windowHeight ); top = Math.max( 0, // Prevent top from going off screen. Math.min( Math.max( offsetTop, 0 ), // Distance widget in panel is from top of screen. windowHeight - formHeight // Flush up against bottom of screen. ) ); $widgetInside.css( 'top', top ); }; $themeControlsContainer = $( '#customize-theme-controls' ); this.container.on( 'expand', function() { positionWidget(); $customizeSidebar.on( 'scroll', positionWidget ); $( window ).on( 'resize', positionWidget ); $themeControlsContainer.on( 'expanded collapsed', positionWidget ); } ); this.container.on( 'collapsed', function() { $customizeSidebar.off( 'scroll', positionWidget ); $( window ).off( 'resize', positionWidget ); $themeControlsContainer.off( 'expanded collapsed', positionWidget ); } ); // Reposition whenever a sidebar's widgets are changed. api.each( function( setting ) { if ( 0 === setting.id.indexOf( 'sidebars_widgets[' ) ) { setting.bind( function() { if ( self.container.hasClass( 'expanded' ) ) { positionWidget(); } } ); } } ); }, /** * Show/hide the control when clicking on the form title, when clicking * the close button */ _setupControlToggle: function() { var self = this, $closeBtn; this.container.find( '.widget-top' ).on( 'click', function( e ) { e.preventDefault(); var sidebarWidgetsControl = self.getSidebarWidgetsControl(); if ( sidebarWidgetsControl.isReordering ) { return; } self.expanded( ! self.expanded() ); } ); $closeBtn = this.container.find( '.widget-control-close' ); $closeBtn.on( 'click', function() { self.collapse(); self.container.find( '.widget-top .widget-action:first' ).focus(); // Keyboard accessibility. } ); }, /** * Update the title of the form if a title field is entered */ _setupWidgetTitle: function() { var self = this, updateTitle; updateTitle = function() { var title = self.setting().title, inWidgetTitle = self.container.find( '.in-widget-title' ); if ( title ) { inWidgetTitle.text( ': ' + title ); } else { inWidgetTitle.text( '' ); } }; this.setting.bind( updateTitle ); updateTitle(); }, /** * Set up the widget-reorder-nav */ _setupReorderUI: function() { var self = this, selectSidebarItem, $moveWidgetArea, $reorderNav, updateAvailableSidebars, template; /** * select the provided sidebar list item in the move widget area * * @param {jQuery} li */ selectSidebarItem = function( li ) { li.siblings( '.selected' ).removeClass( 'selected' ); li.addClass( 'selected' ); var isSelfSidebar = ( li.data( 'id' ) === self.params.sidebar_id ); self.container.find( '.move-widget-btn' ).prop( 'disabled', isSelfSidebar ); }; /** * Add the widget reordering elements to the widget control */ this.container.find( '.widget-title-action' ).after( $( api.Widgets.data.tpl.widgetReorderNav ) ); template = _.template( api.Widgets.data.tpl.moveWidgetArea ); $moveWidgetArea = $( template( { sidebars: _( api.Widgets.registeredSidebars.toArray() ).pluck( 'attributes' ) } ) ); this.container.find( '.widget-top' ).after( $moveWidgetArea ); /** * Update available sidebars when their rendered state changes */ updateAvailableSidebars = function() { var $sidebarItems = $moveWidgetArea.find( 'li' ), selfSidebarItem, renderedSidebarCount = 0; selfSidebarItem = $sidebarItems.filter( function(){ return $( this ).data( 'id' ) === self.params.sidebar_id; } ); $sidebarItems.each( function() { var li = $( this ), sidebarId, sidebar, sidebarIsRendered; sidebarId = li.data( 'id' ); sidebar = api.Widgets.registeredSidebars.get( sidebarId ); sidebarIsRendered = sidebar.get( 'is_rendered' ); li.toggle( sidebarIsRendered ); if ( sidebarIsRendered ) { renderedSidebarCount += 1; } if ( li.hasClass( 'selected' ) && ! sidebarIsRendered ) { selectSidebarItem( selfSidebarItem ); } } ); if ( renderedSidebarCount > 1 ) { self.container.find( '.move-widget' ).show(); } else { self.container.find( '.move-widget' ).hide(); } }; updateAvailableSidebars(); api.Widgets.registeredSidebars.on( 'change:is_rendered', updateAvailableSidebars ); /** * Handle clicks for up/down/move on the reorder nav */ $reorderNav = this.container.find( '.widget-reorder-nav' ); $reorderNav.find( '.move-widget, .move-widget-down, .move-widget-up' ).each( function() { $( this ).prepend( self.container.find( '.widget-title' ).text() + ': ' ); } ).on( 'click keypress', function( event ) { if ( event.type === 'keypress' && ( event.which !== 13 && event.which !== 32 ) ) { return; } $( this ).trigger( 'focus' ); if ( $( this ).is( '.move-widget' ) ) { self.toggleWidgetMoveArea(); } else { var isMoveDown = $( this ).is( '.move-widget-down' ), isMoveUp = $( this ).is( '.move-widget-up' ), i = self.getWidgetSidebarPosition(); if ( ( isMoveUp && i === 0 ) || ( isMoveDown && i === self.getSidebarWidgetsControl().setting().length - 1 ) ) { return; } if ( isMoveUp ) { self.moveUp(); wp.a11y.speak( l10n.widgetMovedUp ); } else { self.moveDown(); wp.a11y.speak( l10n.widgetMovedDown ); } $( this ).trigger( 'focus' ); // Re-focus after the container was moved. } } ); /** * Handle selecting a sidebar to move to */ this.container.find( '.widget-area-select' ).on( 'click keypress', 'li', function( event ) { if ( event.type === 'keypress' && ( event.which !== 13 && event.which !== 32 ) ) { return; } event.preventDefault(); selectSidebarItem( $( this ) ); } ); /** * Move widget to another sidebar */ this.container.find( '.move-widget-btn' ).click( function() { self.getSidebarWidgetsControl().toggleReordering( false ); var oldSidebarId = self.params.sidebar_id, newSidebarId = self.container.find( '.widget-area-select li.selected' ).data( 'id' ), oldSidebarWidgetsSetting, newSidebarWidgetsSetting, oldSidebarWidgetIds, newSidebarWidgetIds, i; oldSidebarWidgetsSetting = api( 'sidebars_widgets[' + oldSidebarId + ']' ); newSidebarWidgetsSetting = api( 'sidebars_widgets[' + newSidebarId + ']' ); oldSidebarWidgetIds = Array.prototype.slice.call( oldSidebarWidgetsSetting() ); newSidebarWidgetIds = Array.prototype.slice.call( newSidebarWidgetsSetting() ); i = self.getWidgetSidebarPosition(); oldSidebarWidgetIds.splice( i, 1 ); newSidebarWidgetIds.push( self.params.widget_id ); oldSidebarWidgetsSetting( oldSidebarWidgetIds ); newSidebarWidgetsSetting( newSidebarWidgetIds ); self.focus(); } ); }, /** * Highlight widgets in preview when interacted with in the Customizer */ _setupHighlightEffects: function() { var self = this; // Highlight whenever hovering or clicking over the form. this.container.on( 'mouseenter click', function() { self.setting.previewer.send( 'highlight-widget', self.params.widget_id ); } ); // Highlight when the setting is updated. this.setting.bind( function() { self.setting.previewer.send( 'highlight-widget', self.params.widget_id ); } ); }, /** * Set up event handlers for widget updating */ _setupUpdateUI: function() { var self = this, $widgetRoot, $widgetContent, $saveBtn, updateWidgetDebounced, formSyncHandler; $widgetRoot = this.container.find( '.widget:first' ); $widgetContent = $widgetRoot.find( '.widget-content:first' ); // Configure update button. $saveBtn = this.container.find( '.widget-control-save' ); $saveBtn.val( l10n.saveBtnLabel ); $saveBtn.attr( 'title', l10n.saveBtnTooltip ); $saveBtn.removeClass( 'button-primary' ); $saveBtn.on( 'click', function( e ) { e.preventDefault(); self.updateWidget( { disable_form: true } ); // @todo disable_form is unused? } ); updateWidgetDebounced = _.debounce( function() { self.updateWidget(); }, 250 ); // Trigger widget form update when hitting Enter within an input. $widgetContent.on( 'keydown', 'input', function( e ) { if ( 13 === e.which ) { // Enter. e.preventDefault(); self.updateWidget( { ignoreActiveElement: true } ); } } ); // Handle widgets that support live previews. $widgetContent.on( 'change input propertychange', ':input', function( e ) { if ( ! self.liveUpdateMode ) { return; } if ( e.type === 'change' || ( this.checkValidity && this.checkValidity() ) ) { updateWidgetDebounced(); } } ); // Remove loading indicators when the setting is saved and the preview updates. this.setting.previewer.channel.bind( 'synced', function() { self.container.removeClass( 'previewer-loading' ); } ); api.previewer.bind( 'widget-updated', function( updatedWidgetId ) { if ( updatedWidgetId === self.params.widget_id ) { self.container.removeClass( 'previewer-loading' ); } } ); formSyncHandler = api.Widgets.formSyncHandlers[ this.params.widget_id_base ]; if ( formSyncHandler ) { $( document ).on( 'widget-synced', function( e, widget ) { if ( $widgetRoot.is( widget ) ) { formSyncHandler.apply( document, arguments ); } } ); } }, /** * Update widget control to indicate whether it is currently rendered. * * Overrides api.Control.toggle() * * @since 4.1.0 * * @param {boolean} active * @param {Object} args * @param {function} args.completeCallback */ onChangeActive: function ( active, args ) { // Note: there is a second 'args' parameter being passed, merged on top of this.defaultActiveArguments. this.container.toggleClass( 'widget-rendered', active ); if ( args.completeCallback ) { args.completeCallback(); } }, /** * Set up event handlers for widget removal */ _setupRemoveUI: function() { var self = this, $removeBtn, replaceDeleteWithRemove; // Configure remove button. $removeBtn = this.container.find( '.widget-control-remove' ); $removeBtn.on( 'click', function() { // Find an adjacent element to add focus to when this widget goes away. var $adjacentFocusTarget; if ( self.container.next().is( '.customize-control-widget_form' ) ) { $adjacentFocusTarget = self.container.next().find( '.widget-action:first' ); } else if ( self.container.prev().is( '.customize-control-widget_form' ) ) { $adjacentFocusTarget = self.container.prev().find( '.widget-action:first' ); } else { $adjacentFocusTarget = self.container.next( '.customize-control-sidebar_widgets' ).find( '.add-new-widget:first' ); } self.container.slideUp( function() { var sidebarsWidgetsControl = api.Widgets.getSidebarWidgetControlContainingWidget( self.params.widget_id ), sidebarWidgetIds, i; if ( ! sidebarsWidgetsControl ) { return; } sidebarWidgetIds = sidebarsWidgetsControl.setting().slice(); i = _.indexOf( sidebarWidgetIds, self.params.widget_id ); if ( -1 === i ) { return; } sidebarWidgetIds.splice( i, 1 ); sidebarsWidgetsControl.setting( sidebarWidgetIds ); $adjacentFocusTarget.focus(); // Keyboard accessibility. } ); } ); replaceDeleteWithRemove = function() { $removeBtn.text( l10n.removeBtnLabel ); // wp_widget_control() outputs the button as "Delete". $removeBtn.attr( 'title', l10n.removeBtnTooltip ); }; if ( this.params.is_new ) { api.bind( 'saved', replaceDeleteWithRemove ); } else { replaceDeleteWithRemove(); } }, /** * Find all inputs in a widget container that should be considered when * comparing the loaded form with the sanitized form, whose fields will * be aligned to copy the sanitized over. The elements returned by this * are passed into this._getInputsSignature(), and they are iterated * over when copying sanitized values over to the form loaded. * * @param {jQuery} container element in which to look for inputs * @return {jQuery} inputs * @private */ _getInputs: function( container ) { return $( container ).find( ':input[name]' ); }, /** * Iterate over supplied inputs and create a signature string for all of them together. * This string can be used to compare whether or not the form has all of the same fields. * * @param {jQuery} inputs * @return {string} * @private */ _getInputsSignature: function( inputs ) { var inputsSignatures = _( inputs ).map( function( input ) { var $input = $( input ), signatureParts; if ( $input.is( ':checkbox, :radio' ) ) { signatureParts = [ $input.attr( 'id' ), $input.attr( 'name' ), $input.prop( 'value' ) ]; } else { signatureParts = [ $input.attr( 'id' ), $input.attr( 'name' ) ]; } return signatureParts.join( ',' ); } ); return inputsSignatures.join( ';' ); }, /** * Get the state for an input depending on its type. * * @param {jQuery|Element} input * @return {string|boolean|Array|*} * @private */ _getInputState: function( input ) { input = $( input ); if ( input.is( ':radio, :checkbox' ) ) { return input.prop( 'checked' ); } else if ( input.is( 'select[multiple]' ) ) { return input.find( 'option:selected' ).map( function () { return $( this ).val(); } ).get(); } else { return input.val(); } }, /** * Update an input's state based on its type. * * @param {jQuery|Element} input * @param {string|boolean|Array|*} state * @private */ _setInputState: function ( input, state ) { input = $( input ); if ( input.is( ':radio, :checkbox' ) ) { input.prop( 'checked', state ); } else if ( input.is( 'select[multiple]' ) ) { if ( ! Array.isArray( state ) ) { state = []; } else { // Make sure all state items are strings since the DOM value is a string. state = _.map( state, function ( value ) { return String( value ); } ); } input.find( 'option' ).each( function () { $( this ).prop( 'selected', -1 !== _.indexOf( state, String( this.value ) ) ); } ); } else { input.val( state ); } }, /*********************************************************************** * Begin public API methods **********************************************************************/ /** * @return {wp.customize.controlConstructor.sidebar_widgets[]} */ getSidebarWidgetsControl: function() { var settingId, sidebarWidgetsControl; settingId = 'sidebars_widgets[' + this.params.sidebar_id + ']'; sidebarWidgetsControl = api.control( settingId ); if ( ! sidebarWidgetsControl ) { return; } return sidebarWidgetsControl; }, /** * Submit the widget form via Ajax and get back the updated instance, * along with the new widget control form to render. * * @param {Object} [args] * @param {Object|null} [args.instance=null] When the model changes, the instance is sent here; otherwise, the inputs from the form are used * @param {Function|null} [args.complete=null] Function which is called when the request finishes. Context is bound to the control. First argument is any error. Following arguments are for success. * @param {boolean} [args.ignoreActiveElement=false] Whether or not updating a field will be deferred if focus is still on the element. */ updateWidget: function( args ) { var self = this, instanceOverride, completeCallback, $widgetRoot, $widgetContent, updateNumber, params, data, $inputs, processing, jqxhr, isChanged; // The updateWidget logic requires that the form fields to be fully present. self.embedWidgetContent(); args = $.extend( { instance: null, complete: null, ignoreActiveElement: false }, args ); instanceOverride = args.instance; completeCallback = args.complete; this._updateCount += 1; updateNumber = this._updateCount; $widgetRoot = this.container.find( '.widget:first' ); $widgetContent = $widgetRoot.find( '.widget-content:first' ); // Remove a previous error message. $widgetContent.find( '.widget-error' ).remove(); this.container.addClass( 'widget-form-loading' ); this.container.addClass( 'previewer-loading' ); processing = api.state( 'processing' ); processing( processing() + 1 ); if ( ! this.liveUpdateMode ) { this.container.addClass( 'widget-form-disabled' ); } params = {}; params.action = 'update-widget'; params.wp_customize = 'on'; params.nonce = api.settings.nonce['update-widget']; params.customize_theme = api.settings.theme.stylesheet; params.customized = wp.customize.previewer.query().customized; data = $.param( params ); $inputs = this._getInputs( $widgetContent ); /* * Store the value we're submitting in data so that when the response comes back, * we know if it got sanitized; if there is no difference in the sanitized value, * then we do not need to touch the UI and mess up the user's ongoing editing. */ $inputs.each( function() { $( this ).data( 'state' + updateNumber, self._getInputState( this ) ); } ); if ( instanceOverride ) { data += '&' + $.param( { 'sanitized_widget_setting': JSON.stringify( instanceOverride ) } ); } else { data += '&' + $inputs.serialize(); } data += '&' + $widgetContent.find( '~ :input' ).serialize(); if ( this._previousUpdateRequest ) { this._previousUpdateRequest.abort(); } jqxhr = $.post( wp.ajax.settings.url, data ); this._previousUpdateRequest = jqxhr; jqxhr.done( function( r ) { var message, sanitizedForm, $sanitizedInputs, hasSameInputsInResponse, isLiveUpdateAborted = false; // Check if the user is logged out. if ( '0' === r ) { api.previewer.preview.iframe.hide(); api.previewer.login().done( function() { self.updateWidget( args ); api.previewer.preview.iframe.show(); } ); return; } // Check for cheaters. if ( '-1' === r ) { api.previewer.cheatin(); return; } if ( r.success ) { sanitizedForm = $( '
    ' + r.data.form + '
    ' ); $sanitizedInputs = self._getInputs( sanitizedForm ); hasSameInputsInResponse = self._getInputsSignature( $inputs ) === self._getInputsSignature( $sanitizedInputs ); // Restore live update mode if sanitized fields are now aligned with the existing fields. if ( hasSameInputsInResponse && ! self.liveUpdateMode ) { self.liveUpdateMode = true; self.container.removeClass( 'widget-form-disabled' ); self.container.find( 'input[name="savewidget"]' ).hide(); } // Sync sanitized field states to existing fields if they are aligned. if ( hasSameInputsInResponse && self.liveUpdateMode ) { $inputs.each( function( i ) { var $input = $( this ), $sanitizedInput = $( $sanitizedInputs[i] ), submittedState, sanitizedState, canUpdateState; submittedState = $input.data( 'state' + updateNumber ); sanitizedState = self._getInputState( $sanitizedInput ); $input.data( 'sanitized', sanitizedState ); canUpdateState = ( ! _.isEqual( submittedState, sanitizedState ) && ( args.ignoreActiveElement || ! $input.is( document.activeElement ) ) ); if ( canUpdateState ) { self._setInputState( $input, sanitizedState ); } } ); $( document ).trigger( 'widget-synced', [ $widgetRoot, r.data.form ] ); // Otherwise, if sanitized fields are not aligned with existing fields, disable live update mode if enabled. } else if ( self.liveUpdateMode ) { self.liveUpdateMode = false; self.container.find( 'input[name="savewidget"]' ).show(); isLiveUpdateAborted = true; // Otherwise, replace existing form with the sanitized form. } else { $widgetContent.html( r.data.form ); self.container.removeClass( 'widget-form-disabled' ); $( document ).trigger( 'widget-updated', [ $widgetRoot ] ); } /** * If the old instance is identical to the new one, there is nothing new * needing to be rendered, and so we can preempt the event for the * preview finishing loading. */ isChanged = ! isLiveUpdateAborted && ! _( self.setting() ).isEqual( r.data.instance ); if ( isChanged ) { self.isWidgetUpdating = true; // Suppress triggering another updateWidget. self.setting( r.data.instance ); self.isWidgetUpdating = false; } else { // No change was made, so stop the spinner now instead of when the preview would updates. self.container.removeClass( 'previewer-loading' ); } if ( completeCallback ) { completeCallback.call( self, null, { noChange: ! isChanged, ajaxFinished: true } ); } } else { // General error message. message = l10n.error; if ( r.data && r.data.message ) { message = r.data.message; } if ( completeCallback ) { completeCallback.call( self, message ); } else { $widgetContent.prepend( '

    ' + message + '

    ' ); } } } ); jqxhr.fail( function( jqXHR, textStatus ) { if ( completeCallback ) { completeCallback.call( self, textStatus ); } } ); jqxhr.always( function() { self.container.removeClass( 'widget-form-loading' ); $inputs.each( function() { $( this ).removeData( 'state' + updateNumber ); } ); processing( processing() - 1 ); } ); }, /** * Expand the accordion section containing a control */ expandControlSection: function() { api.Control.prototype.expand.call( this ); }, /** * @since 4.1.0 * * @param {Boolean} expanded * @param {Object} [params] * @return {Boolean} False if state already applied. */ _toggleExpanded: api.Section.prototype._toggleExpanded, /** * @since 4.1.0 * * @param {Object} [params] * @return {Boolean} False if already expanded. */ expand: api.Section.prototype.expand, /** * Expand the widget form control * * @deprecated 4.1.0 Use this.expand() instead. */ expandForm: function() { this.expand(); }, /** * @since 4.1.0 * * @param {Object} [params] * @return {Boolean} False if already collapsed. */ collapse: api.Section.prototype.collapse, /** * Collapse the widget form control * * @deprecated 4.1.0 Use this.collapse() instead. */ collapseForm: function() { this.collapse(); }, /** * Expand or collapse the widget control * * @deprecated this is poor naming, and it is better to directly set control.expanded( showOrHide ) * * @param {boolean|undefined} [showOrHide] If not supplied, will be inverse of current visibility */ toggleForm: function( showOrHide ) { if ( typeof showOrHide === 'undefined' ) { showOrHide = ! this.expanded(); } this.expanded( showOrHide ); }, /** * Respond to change in the expanded state. * * @param {boolean} expanded * @param {Object} args merged on top of this.defaultActiveArguments */ onChangeExpanded: function ( expanded, args ) { var self = this, $widget, $inside, complete, prevComplete, expandControl, $toggleBtn; self.embedWidgetControl(); // Make sure the outer form is embedded so that the expanded state can be set in the UI. if ( expanded ) { self.embedWidgetContent(); } // If the expanded state is unchanged only manipulate container expanded states. if ( args.unchanged ) { if ( expanded ) { api.Control.prototype.expand.call( self, { completeCallback: args.completeCallback }); } return; } $widget = this.container.find( 'div.widget:first' ); $inside = $widget.find( '.widget-inside:first' ); $toggleBtn = this.container.find( '.widget-top button.widget-action' ); expandControl = function() { // Close all other widget controls before expanding this one. api.control.each( function( otherControl ) { if ( self.params.type === otherControl.params.type && self !== otherControl ) { otherControl.collapse(); } } ); complete = function() { self.container.removeClass( 'expanding' ); self.container.addClass( 'expanded' ); $widget.addClass( 'open' ); $toggleBtn.attr( 'aria-expanded', 'true' ); self.container.trigger( 'expanded' ); }; if ( args.completeCallback ) { prevComplete = complete; complete = function () { prevComplete(); args.completeCallback(); }; } if ( self.params.is_wide ) { $inside.fadeIn( args.duration, complete ); } else { $inside.slideDown( args.duration, complete ); } self.container.trigger( 'expand' ); self.container.addClass( 'expanding' ); }; if ( $toggleBtn.attr( 'aria-expanded' ) === 'false' ) { if ( api.section.has( self.section() ) ) { api.section( self.section() ).expand( { completeCallback: expandControl } ); } else { expandControl(); } } else { complete = function() { self.container.removeClass( 'collapsing' ); self.container.removeClass( 'expanded' ); $widget.removeClass( 'open' ); $toggleBtn.attr( 'aria-expanded', 'false' ); self.container.trigger( 'collapsed' ); }; if ( args.completeCallback ) { prevComplete = complete; complete = function () { prevComplete(); args.completeCallback(); }; } self.container.trigger( 'collapse' ); self.container.addClass( 'collapsing' ); if ( self.params.is_wide ) { $inside.fadeOut( args.duration, complete ); } else { $inside.slideUp( args.duration, function() { $widget.css( { width:'', margin:'' } ); complete(); } ); } } }, /** * Get the position (index) of the widget in the containing sidebar * * @return {number} */ getWidgetSidebarPosition: function() { var sidebarWidgetIds, position; sidebarWidgetIds = this.getSidebarWidgetsControl().setting(); position = _.indexOf( sidebarWidgetIds, this.params.widget_id ); if ( position === -1 ) { return; } return position; }, /** * Move widget up one in the sidebar */ moveUp: function() { this._moveWidgetByOne( -1 ); }, /** * Move widget up one in the sidebar */ moveDown: function() { this._moveWidgetByOne( 1 ); }, /** * @private * * @param {number} offset 1|-1 */ _moveWidgetByOne: function( offset ) { var i, sidebarWidgetsSetting, sidebarWidgetIds, adjacentWidgetId; i = this.getWidgetSidebarPosition(); sidebarWidgetsSetting = this.getSidebarWidgetsControl().setting; sidebarWidgetIds = Array.prototype.slice.call( sidebarWidgetsSetting() ); // Clone. adjacentWidgetId = sidebarWidgetIds[i + offset]; sidebarWidgetIds[i + offset] = this.params.widget_id; sidebarWidgetIds[i] = adjacentWidgetId; sidebarWidgetsSetting( sidebarWidgetIds ); }, /** * Toggle visibility of the widget move area * * @param {boolean} [showOrHide] */ toggleWidgetMoveArea: function( showOrHide ) { var self = this, $moveWidgetArea; $moveWidgetArea = this.container.find( '.move-widget-area' ); if ( typeof showOrHide === 'undefined' ) { showOrHide = ! $moveWidgetArea.hasClass( 'active' ); } if ( showOrHide ) { // Reset the selected sidebar. $moveWidgetArea.find( '.selected' ).removeClass( 'selected' ); $moveWidgetArea.find( 'li' ).filter( function() { return $( this ).data( 'id' ) === self.params.sidebar_id; } ).addClass( 'selected' ); this.container.find( '.move-widget-btn' ).prop( 'disabled', true ); } $moveWidgetArea.toggleClass( 'active', showOrHide ); }, /** * Highlight the widget control and section */ highlightSectionAndControl: function() { var $target; if ( this.container.is( ':hidden' ) ) { $target = this.container.closest( '.control-section' ); } else { $target = this.container; } $( '.highlighted' ).removeClass( 'highlighted' ); $target.addClass( 'highlighted' ); setTimeout( function() { $target.removeClass( 'highlighted' ); }, 500 ); } } ); /** * wp.customize.Widgets.WidgetsPanel * * Customizer panel containing the widget area sections. * * @since 4.4.0 * * @class wp.customize.Widgets.WidgetsPanel * @augments wp.customize.Panel */ api.Widgets.WidgetsPanel = api.Panel.extend(/** @lends wp.customize.Widgets.WigetsPanel.prototype */{ /** * Add and manage the display of the no-rendered-areas notice. * * @since 4.4.0 */ ready: function () { var panel = this; api.Panel.prototype.ready.call( panel ); panel.deferred.embedded.done(function() { var panelMetaContainer, noticeContainer, updateNotice, getActiveSectionCount, shouldShowNotice; panelMetaContainer = panel.container.find( '.panel-meta' ); // @todo This should use the Notifications API introduced to panels. See . noticeContainer = $( '
    ', { 'class': 'no-widget-areas-rendered-notice', 'role': 'alert' }); panelMetaContainer.append( noticeContainer ); /** * Get the number of active sections in the panel. * * @return {number} Number of active sidebar sections. */ getActiveSectionCount = function() { return _.filter( panel.sections(), function( section ) { return 'sidebar' === section.params.type && section.active(); } ).length; }; /** * Determine whether or not the notice should be displayed. * * @return {boolean} */ shouldShowNotice = function() { var activeSectionCount = getActiveSectionCount(); if ( 0 === activeSectionCount ) { return true; } else { return activeSectionCount !== api.Widgets.data.registeredSidebars.length; } }; /** * Update the notice. * * @return {void} */ updateNotice = function() { var activeSectionCount = getActiveSectionCount(), someRenderedMessage, nonRenderedAreaCount, registeredAreaCount; noticeContainer.empty(); registeredAreaCount = api.Widgets.data.registeredSidebars.length; if ( activeSectionCount !== registeredAreaCount ) { if ( 0 !== activeSectionCount ) { nonRenderedAreaCount = registeredAreaCount - activeSectionCount; someRenderedMessage = l10n.someAreasShown[ nonRenderedAreaCount ]; } else { someRenderedMessage = l10n.noAreasShown; } if ( someRenderedMessage ) { noticeContainer.append( $( '

    ', { text: someRenderedMessage } ) ); } noticeContainer.append( $( '

    ', { text: l10n.navigatePreview } ) ); } }; updateNotice(); /* * Set the initial visibility state for rendered notice. * Update the visibility of the notice whenever a reflow happens. */ noticeContainer.toggle( shouldShowNotice() ); api.previewer.deferred.active.done( function () { noticeContainer.toggle( shouldShowNotice() ); }); api.bind( 'pane-contents-reflowed', function() { var duration = ( 'resolved' === api.previewer.deferred.active.state() ) ? 'fast' : 0; updateNotice(); if ( shouldShowNotice() ) { noticeContainer.slideDown( duration ); } else { noticeContainer.slideUp( duration ); } }); }); }, /** * Allow an active widgets panel to be contextually active even when it has no active sections (widget areas). * * This ensures that the widgets panel appears even when there are no * sidebars displayed on the URL currently being previewed. * * @since 4.4.0 * * @return {boolean} */ isContextuallyActive: function() { var panel = this; return panel.active(); } }); /** * wp.customize.Widgets.SidebarSection * * Customizer section representing a widget area widget * * @since 4.1.0 * * @class wp.customize.Widgets.SidebarSection * @augments wp.customize.Section */ api.Widgets.SidebarSection = api.Section.extend(/** @lends wp.customize.Widgets.SidebarSection.prototype */{ /** * Sync the section's active state back to the Backbone model's is_rendered attribute * * @since 4.1.0 */ ready: function () { var section = this, registeredSidebar; api.Section.prototype.ready.call( this ); registeredSidebar = api.Widgets.registeredSidebars.get( section.params.sidebarId ); section.active.bind( function ( active ) { registeredSidebar.set( 'is_rendered', active ); }); registeredSidebar.set( 'is_rendered', section.active() ); } }); /** * wp.customize.Widgets.SidebarControl * * Customizer control for widgets. * Note that 'sidebar_widgets' must match the WP_Widget_Area_Customize_Control::$type * * @since 3.9.0 * * @class wp.customize.Widgets.SidebarControl * @augments wp.customize.Control */ api.Widgets.SidebarControl = api.Control.extend(/** @lends wp.customize.Widgets.SidebarControl.prototype */{ /** * Set up the control */ ready: function() { this.$controlSection = this.container.closest( '.control-section' ); this.$sectionContent = this.container.closest( '.accordion-section-content' ); this._setupModel(); this._setupSortable(); this._setupAddition(); this._applyCardinalOrderClassNames(); }, /** * Update ordering of widget control forms when the setting is updated */ _setupModel: function() { var self = this; this.setting.bind( function( newWidgetIds, oldWidgetIds ) { var widgetFormControls, removedWidgetIds, priority; removedWidgetIds = _( oldWidgetIds ).difference( newWidgetIds ); // Filter out any persistent widget IDs for widgets which have been deactivated. newWidgetIds = _( newWidgetIds ).filter( function( newWidgetId ) { var parsedWidgetId = parseWidgetId( newWidgetId ); return !! api.Widgets.availableWidgets.findWhere( { id_base: parsedWidgetId.id_base } ); } ); widgetFormControls = _( newWidgetIds ).map( function( widgetId ) { var widgetFormControl = api.Widgets.getWidgetFormControlForWidget( widgetId ); if ( ! widgetFormControl ) { widgetFormControl = self.addWidget( widgetId ); } return widgetFormControl; } ); // Sort widget controls to their new positions. widgetFormControls.sort( function( a, b ) { var aIndex = _.indexOf( newWidgetIds, a.params.widget_id ), bIndex = _.indexOf( newWidgetIds, b.params.widget_id ); return aIndex - bIndex; }); priority = 0; _( widgetFormControls ).each( function ( control ) { control.priority( priority ); control.section( self.section() ); priority += 1; }); self.priority( priority ); // Make sure sidebar control remains at end. // Re-sort widget form controls (including widgets form other sidebars newly moved here). self._applyCardinalOrderClassNames(); // If the widget was dragged into the sidebar, make sure the sidebar_id param is updated. _( widgetFormControls ).each( function( widgetFormControl ) { widgetFormControl.params.sidebar_id = self.params.sidebar_id; } ); // Cleanup after widget removal. _( removedWidgetIds ).each( function( removedWidgetId ) { // Using setTimeout so that when moving a widget to another sidebar, // the other sidebars_widgets settings get a chance to update. setTimeout( function() { var removedControl, wasDraggedToAnotherSidebar, inactiveWidgets, removedIdBase, widget, isPresentInAnotherSidebar = false; // Check if the widget is in another sidebar. api.each( function( otherSetting ) { if ( otherSetting.id === self.setting.id || 0 !== otherSetting.id.indexOf( 'sidebars_widgets[' ) || otherSetting.id === 'sidebars_widgets[wp_inactive_widgets]' ) { return; } var otherSidebarWidgets = otherSetting(), i; i = _.indexOf( otherSidebarWidgets, removedWidgetId ); if ( -1 !== i ) { isPresentInAnotherSidebar = true; } } ); // If the widget is present in another sidebar, abort! if ( isPresentInAnotherSidebar ) { return; } removedControl = api.Widgets.getWidgetFormControlForWidget( removedWidgetId ); // Detect if widget control was dragged to another sidebar. wasDraggedToAnotherSidebar = removedControl && $.contains( document, removedControl.container[0] ) && ! $.contains( self.$sectionContent[0], removedControl.container[0] ); // Delete any widget form controls for removed widgets. if ( removedControl && ! wasDraggedToAnotherSidebar ) { api.control.remove( removedControl.id ); removedControl.container.remove(); } // Move widget to inactive widgets sidebar (move it to Trash) if has been previously saved. // This prevents the inactive widgets sidebar from overflowing with throwaway widgets. if ( api.Widgets.savedWidgetIds[removedWidgetId] ) { inactiveWidgets = api.value( 'sidebars_widgets[wp_inactive_widgets]' )().slice(); inactiveWidgets.push( removedWidgetId ); api.value( 'sidebars_widgets[wp_inactive_widgets]' )( _( inactiveWidgets ).unique() ); } // Make old single widget available for adding again. removedIdBase = parseWidgetId( removedWidgetId ).id_base; widget = api.Widgets.availableWidgets.findWhere( { id_base: removedIdBase } ); if ( widget && ! widget.get( 'is_multi' ) ) { widget.set( 'is_disabled', false ); } } ); } ); } ); }, /** * Allow widgets in sidebar to be re-ordered, and for the order to be previewed */ _setupSortable: function() { var self = this; this.isReordering = false; /** * Update widget order setting when controls are re-ordered */ this.$sectionContent.sortable( { items: '> .customize-control-widget_form', handle: '.widget-top', axis: 'y', tolerance: 'pointer', connectWith: '.accordion-section-content:has(.customize-control-sidebar_widgets)', update: function() { var widgetContainerIds = self.$sectionContent.sortable( 'toArray' ), widgetIds; widgetIds = $.map( widgetContainerIds, function( widgetContainerId ) { return $( '#' + widgetContainerId ).find( ':input[name=widget-id]' ).val(); } ); self.setting( widgetIds ); } } ); /** * Expand other Customizer sidebar section when dragging a control widget over it, * allowing the control to be dropped into another section */ this.$controlSection.find( '.accordion-section-title' ).droppable({ accept: '.customize-control-widget_form', over: function() { var section = api.section( self.section.get() ); section.expand({ allowMultiple: true, // Prevent the section being dragged from to be collapsed. completeCallback: function () { // @todo It is not clear when refreshPositions should be called on which sections, or if it is even needed. api.section.each( function ( otherSection ) { if ( otherSection.container.find( '.customize-control-sidebar_widgets' ).length ) { otherSection.container.find( '.accordion-section-content:first' ).sortable( 'refreshPositions' ); } } ); } }); } }); /** * Keyboard-accessible reordering */ this.container.find( '.reorder-toggle' ).on( 'click', function() { self.toggleReordering( ! self.isReordering ); } ); }, /** * Set up UI for adding a new widget */ _setupAddition: function() { var self = this; this.container.find( '.add-new-widget' ).on( 'click', function() { var addNewWidgetBtn = $( this ); if ( self.$sectionContent.hasClass( 'reordering' ) ) { return; } if ( ! $( 'body' ).hasClass( 'adding-widget' ) ) { addNewWidgetBtn.attr( 'aria-expanded', 'true' ); api.Widgets.availableWidgetsPanel.open( self ); } else { addNewWidgetBtn.attr( 'aria-expanded', 'false' ); api.Widgets.availableWidgetsPanel.close(); } } ); }, /** * Add classes to the widget_form controls to assist with styling */ _applyCardinalOrderClassNames: function() { var widgetControls = []; _.each( this.setting(), function ( widgetId ) { var widgetControl = api.Widgets.getWidgetFormControlForWidget( widgetId ); if ( widgetControl ) { widgetControls.push( widgetControl ); } }); if ( 0 === widgetControls.length || ( 1 === api.Widgets.registeredSidebars.length && widgetControls.length <= 1 ) ) { this.container.find( '.reorder-toggle' ).hide(); return; } else { this.container.find( '.reorder-toggle' ).show(); } $( widgetControls ).each( function () { $( this.container ) .removeClass( 'first-widget' ) .removeClass( 'last-widget' ) .find( '.move-widget-down, .move-widget-up' ).prop( 'tabIndex', 0 ); }); _.first( widgetControls ).container .addClass( 'first-widget' ) .find( '.move-widget-up' ).prop( 'tabIndex', -1 ); _.last( widgetControls ).container .addClass( 'last-widget' ) .find( '.move-widget-down' ).prop( 'tabIndex', -1 ); }, /*********************************************************************** * Begin public API methods **********************************************************************/ /** * Enable/disable the reordering UI * * @param {boolean} showOrHide to enable/disable reordering * * @todo We should have a reordering state instead and rename this to onChangeReordering */ toggleReordering: function( showOrHide ) { var addNewWidgetBtn = this.$sectionContent.find( '.add-new-widget' ), reorderBtn = this.container.find( '.reorder-toggle' ), widgetsTitle = this.$sectionContent.find( '.widget-title' ); showOrHide = Boolean( showOrHide ); if ( showOrHide === this.$sectionContent.hasClass( 'reordering' ) ) { return; } this.isReordering = showOrHide; this.$sectionContent.toggleClass( 'reordering', showOrHide ); if ( showOrHide ) { _( this.getWidgetFormControls() ).each( function( formControl ) { formControl.collapse(); } ); addNewWidgetBtn.attr({ 'tabindex': '-1', 'aria-hidden': 'true' }); reorderBtn.attr( 'aria-label', l10n.reorderLabelOff ); wp.a11y.speak( l10n.reorderModeOn ); // Hide widget titles while reordering: title is already in the reorder controls. widgetsTitle.attr( 'aria-hidden', 'true' ); } else { addNewWidgetBtn.removeAttr( 'tabindex aria-hidden' ); reorderBtn.attr( 'aria-label', l10n.reorderLabelOn ); wp.a11y.speak( l10n.reorderModeOff ); widgetsTitle.attr( 'aria-hidden', 'false' ); } }, /** * Get the widget_form Customize controls associated with the current sidebar. * * @since 3.9.0 * @return {wp.customize.controlConstructor.widget_form[]} */ getWidgetFormControls: function() { var formControls = []; _( this.setting() ).each( function( widgetId ) { var settingId = widgetIdToSettingId( widgetId ), formControl = api.control( settingId ); if ( formControl ) { formControls.push( formControl ); } } ); return formControls; }, /** * @param {string} widgetId or an id_base for adding a previously non-existing widget. * @return {Object|false} widget_form control instance, or false on error. */ addWidget: function( widgetId ) { var self = this, controlHtml, $widget, controlType = 'widget_form', controlContainer, controlConstructor, parsedWidgetId = parseWidgetId( widgetId ), widgetNumber = parsedWidgetId.number, widgetIdBase = parsedWidgetId.id_base, widget = api.Widgets.availableWidgets.findWhere( {id_base: widgetIdBase} ), settingId, isExistingWidget, widgetFormControl, sidebarWidgets, settingArgs, setting; if ( ! widget ) { return false; } if ( widgetNumber && ! widget.get( 'is_multi' ) ) { return false; } // Set up new multi widget. if ( widget.get( 'is_multi' ) && ! widgetNumber ) { widget.set( 'multi_number', widget.get( 'multi_number' ) + 1 ); widgetNumber = widget.get( 'multi_number' ); } controlHtml = $( '#widget-tpl-' + widget.get( 'id' ) ).html().trim(); if ( widget.get( 'is_multi' ) ) { controlHtml = controlHtml.replace( /<[^<>]+>/g, function( m ) { return m.replace( /__i__|%i%/g, widgetNumber ); } ); } else { widget.set( 'is_disabled', true ); // Prevent single widget from being added again now. } $widget = $( controlHtml ); controlContainer = $( '
  • ' ) .addClass( 'customize-control' ) .addClass( 'customize-control-' + controlType ) .append( $widget ); // Remove icon which is visible inside the panel. controlContainer.find( '> .widget-icon' ).remove(); if ( widget.get( 'is_multi' ) ) { controlContainer.find( 'input[name="widget_number"]' ).val( widgetNumber ); controlContainer.find( 'input[name="multi_number"]' ).val( widgetNumber ); } widgetId = controlContainer.find( '[name="widget-id"]' ).val(); controlContainer.hide(); // To be slid-down below. settingId = 'widget_' + widget.get( 'id_base' ); if ( widget.get( 'is_multi' ) ) { settingId += '[' + widgetNumber + ']'; } controlContainer.attr( 'id', 'customize-control-' + settingId.replace( /\]/g, '' ).replace( /\[/g, '-' ) ); // Only create setting if it doesn't already exist (if we're adding a pre-existing inactive widget). isExistingWidget = api.has( settingId ); if ( ! isExistingWidget ) { settingArgs = { transport: api.Widgets.data.selectiveRefreshableWidgets[ widget.get( 'id_base' ) ] ? 'postMessage' : 'refresh', previewer: this.setting.previewer }; setting = api.create( settingId, settingId, '', settingArgs ); setting.set( {} ); // Mark dirty, changing from '' to {}. } controlConstructor = api.controlConstructor[controlType]; widgetFormControl = new controlConstructor( settingId, { settings: { 'default': settingId }, content: controlContainer, sidebar_id: self.params.sidebar_id, widget_id: widgetId, widget_id_base: widget.get( 'id_base' ), type: controlType, is_new: ! isExistingWidget, width: widget.get( 'width' ), height: widget.get( 'height' ), is_wide: widget.get( 'is_wide' ) } ); api.control.add( widgetFormControl ); // Make sure widget is removed from the other sidebars. api.each( function( otherSetting ) { if ( otherSetting.id === self.setting.id ) { return; } if ( 0 !== otherSetting.id.indexOf( 'sidebars_widgets[' ) ) { return; } var otherSidebarWidgets = otherSetting().slice(), i = _.indexOf( otherSidebarWidgets, widgetId ); if ( -1 !== i ) { otherSidebarWidgets.splice( i ); otherSetting( otherSidebarWidgets ); } } ); // Add widget to this sidebar. sidebarWidgets = this.setting().slice(); if ( -1 === _.indexOf( sidebarWidgets, widgetId ) ) { sidebarWidgets.push( widgetId ); this.setting( sidebarWidgets ); } controlContainer.slideDown( function() { if ( isExistingWidget ) { widgetFormControl.updateWidget( { instance: widgetFormControl.setting() } ); } } ); return widgetFormControl; } } ); // Register models for custom panel, section, and control types. $.extend( api.panelConstructor, { widgets: api.Widgets.WidgetsPanel }); $.extend( api.sectionConstructor, { sidebar: api.Widgets.SidebarSection }); $.extend( api.controlConstructor, { widget_form: api.Widgets.WidgetControl, sidebar_widgets: api.Widgets.SidebarControl }); /** * Init Customizer for widgets. */ api.bind( 'ready', function() { // Set up the widgets panel. api.Widgets.availableWidgetsPanel = new api.Widgets.AvailableWidgetsPanelView({ collection: api.Widgets.availableWidgets }); // Highlight widget control. api.previewer.bind( 'highlight-widget-control', api.Widgets.highlightWidgetFormControl ); // Open and focus widget control. api.previewer.bind( 'focus-widget-control', api.Widgets.focusWidgetFormControl ); } ); /** * Highlight a widget control. * * @param {string} widgetId */ api.Widgets.highlightWidgetFormControl = function( widgetId ) { var control = api.Widgets.getWidgetFormControlForWidget( widgetId ); if ( control ) { control.highlightSectionAndControl(); } }, /** * Focus a widget control. * * @param {string} widgetId */ api.Widgets.focusWidgetFormControl = function( widgetId ) { var control = api.Widgets.getWidgetFormControlForWidget( widgetId ); if ( control ) { control.focus(); } }, /** * Given a widget control, find the sidebar widgets control that contains it. * @param {string} widgetId * @return {Object|null} */ api.Widgets.getSidebarWidgetControlContainingWidget = function( widgetId ) { var foundControl = null; // @todo This can use widgetIdToSettingId(), then pass into wp.customize.control( x ).getSidebarWidgetsControl(). api.control.each( function( control ) { if ( control.params.type === 'sidebar_widgets' && -1 !== _.indexOf( control.setting(), widgetId ) ) { foundControl = control; } } ); return foundControl; }; /** * Given a widget ID for a widget appearing in the preview, get the widget form control associated with it. * * @param {string} widgetId * @return {Object|null} */ api.Widgets.getWidgetFormControlForWidget = function( widgetId ) { var foundControl = null; // @todo We can just use widgetIdToSettingId() here. api.control.each( function( control ) { if ( control.params.type === 'widget_form' && control.params.widget_id === widgetId ) { foundControl = control; } } ); return foundControl; }; /** * Initialize Edit Menu button in Nav Menu widget. */ $( document ).on( 'widget-added', function( event, widgetContainer ) { var parsedWidgetId, widgetControl, navMenuSelect, editMenuButton; parsedWidgetId = parseWidgetId( widgetContainer.find( '> .widget-inside > .form > .widget-id' ).val() ); if ( 'nav_menu' !== parsedWidgetId.id_base ) { return; } widgetControl = api.control( 'widget_nav_menu[' + String( parsedWidgetId.number ) + ']' ); if ( ! widgetControl ) { return; } navMenuSelect = widgetContainer.find( 'select[name*="nav_menu"]' ); editMenuButton = widgetContainer.find( '.edit-selected-nav-menu > button' ); if ( 0 === navMenuSelect.length || 0 === editMenuButton.length ) { return; } navMenuSelect.on( 'change', function() { if ( api.section.has( 'nav_menu[' + navMenuSelect.val() + ']' ) ) { editMenuButton.parent().show(); } else { editMenuButton.parent().hide(); } }); editMenuButton.on( 'click', function() { var section = api.section( 'nav_menu[' + navMenuSelect.val() + ']' ); if ( section ) { focusConstructWithBreadcrumb( section, widgetControl ); } } ); } ); /** * Focus (expand) one construct and then focus on another construct after the first is collapsed. * * This overrides the back button to serve the purpose of breadcrumb navigation. * * @param {wp.customize.Section|wp.customize.Panel|wp.customize.Control} focusConstruct - The object to initially focus. * @param {wp.customize.Section|wp.customize.Panel|wp.customize.Control} returnConstruct - The object to return focus. */ function focusConstructWithBreadcrumb( focusConstruct, returnConstruct ) { focusConstruct.focus(); function onceCollapsed( isExpanded ) { if ( ! isExpanded ) { focusConstruct.expanded.unbind( onceCollapsed ); returnConstruct.focus(); } } focusConstruct.expanded.bind( onceCollapsed ); } /** * @param {string} widgetId * @return {Object} */ function parseWidgetId( widgetId ) { var matches, parsed = { number: null, id_base: null }; matches = widgetId.match( /^(.+)-(\d+)$/ ); if ( matches ) { parsed.id_base = matches[1]; parsed.number = parseInt( matches[2], 10 ); } else { // Likely an old single widget. parsed.id_base = widgetId; } return parsed; } /** * @param {string} widgetId * @return {string} settingId */ function widgetIdToSettingId( widgetId ) { var parsed = parseWidgetId( widgetId ), settingId; settingId = 'widget_' + parsed.id_base; if ( parsed.number ) { settingId += '[' + parsed.number + ']'; } return settingId; } })( window.wp, jQuery ); code-editor.js000064400000026504147573140730007322 0ustar00/** * @output wp-admin/js/code-editor.js */ if ( 'undefined' === typeof window.wp ) { /** * @namespace wp */ window.wp = {}; } if ( 'undefined' === typeof window.wp.codeEditor ) { /** * @namespace wp.codeEditor */ window.wp.codeEditor = {}; } ( function( $, wp ) { 'use strict'; /** * Default settings for code editor. * * @since 4.9.0 * @type {object} */ wp.codeEditor.defaultSettings = { codemirror: {}, csslint: {}, htmlhint: {}, jshint: {}, onTabNext: function() {}, onTabPrevious: function() {}, onChangeLintingErrors: function() {}, onUpdateErrorNotice: function() {} }; /** * Configure linting. * * @param {CodeMirror} editor - Editor. * @param {Object} settings - Code editor settings. * @param {Object} settings.codeMirror - Settings for CodeMirror. * @param {Function} settings.onChangeLintingErrors - Callback for when there are changes to linting errors. * @param {Function} settings.onUpdateErrorNotice - Callback to update error notice. * * @return {void} */ function configureLinting( editor, settings ) { // eslint-disable-line complexity var currentErrorAnnotations = [], previouslyShownErrorAnnotations = []; /** * Call the onUpdateErrorNotice if there are new errors to show. * * @return {void} */ function updateErrorNotice() { if ( settings.onUpdateErrorNotice && ! _.isEqual( currentErrorAnnotations, previouslyShownErrorAnnotations ) ) { settings.onUpdateErrorNotice( currentErrorAnnotations, editor ); previouslyShownErrorAnnotations = currentErrorAnnotations; } } /** * Get lint options. * * @return {Object} Lint options. */ function getLintOptions() { // eslint-disable-line complexity var options = editor.getOption( 'lint' ); if ( ! options ) { return false; } if ( true === options ) { options = {}; } else if ( _.isObject( options ) ) { options = $.extend( {}, options ); } /* * Note that rules must be sent in the "deprecated" lint.options property * to prevent linter from complaining about unrecognized options. * See . */ if ( ! options.options ) { options.options = {}; } // Configure JSHint. if ( 'javascript' === settings.codemirror.mode && settings.jshint ) { $.extend( options.options, settings.jshint ); } // Configure CSSLint. if ( 'css' === settings.codemirror.mode && settings.csslint ) { $.extend( options.options, settings.csslint ); } // Configure HTMLHint. if ( 'htmlmixed' === settings.codemirror.mode && settings.htmlhint ) { options.options.rules = $.extend( {}, settings.htmlhint ); if ( settings.jshint ) { options.options.rules.jshint = settings.jshint; } if ( settings.csslint ) { options.options.rules.csslint = settings.csslint; } } // Wrap the onUpdateLinting CodeMirror event to route to onChangeLintingErrors and onUpdateErrorNotice. options.onUpdateLinting = (function( onUpdateLintingOverridden ) { return function( annotations, annotationsSorted, cm ) { var errorAnnotations = _.filter( annotations, function( annotation ) { return 'error' === annotation.severity; } ); if ( onUpdateLintingOverridden ) { onUpdateLintingOverridden.apply( annotations, annotationsSorted, cm ); } // Skip if there are no changes to the errors. if ( _.isEqual( errorAnnotations, currentErrorAnnotations ) ) { return; } currentErrorAnnotations = errorAnnotations; if ( settings.onChangeLintingErrors ) { settings.onChangeLintingErrors( errorAnnotations, annotations, annotationsSorted, cm ); } /* * Update notifications when the editor is not focused to prevent error message * from overwhelming the user during input, unless there are now no errors or there * were previously errors shown. In these cases, update immediately so they can know * that they fixed the errors. */ if ( ! editor.state.focused || 0 === currentErrorAnnotations.length || previouslyShownErrorAnnotations.length > 0 ) { updateErrorNotice(); } }; })( options.onUpdateLinting ); return options; } editor.setOption( 'lint', getLintOptions() ); // Keep lint options populated. editor.on( 'optionChange', function( cm, option ) { var options, gutters, gutterName = 'CodeMirror-lint-markers'; if ( 'lint' !== option ) { return; } gutters = editor.getOption( 'gutters' ) || []; options = editor.getOption( 'lint' ); if ( true === options ) { if ( ! _.contains( gutters, gutterName ) ) { editor.setOption( 'gutters', [ gutterName ].concat( gutters ) ); } editor.setOption( 'lint', getLintOptions() ); // Expand to include linting options. } else if ( ! options ) { editor.setOption( 'gutters', _.without( gutters, gutterName ) ); } // Force update on error notice to show or hide. if ( editor.getOption( 'lint' ) ) { editor.performLint(); } else { currentErrorAnnotations = []; updateErrorNotice(); } } ); // Update error notice when leaving the editor. editor.on( 'blur', updateErrorNotice ); // Work around hint selection with mouse causing focus to leave editor. editor.on( 'startCompletion', function() { editor.off( 'blur', updateErrorNotice ); } ); editor.on( 'endCompletion', function() { var editorRefocusWait = 500; editor.on( 'blur', updateErrorNotice ); // Wait for editor to possibly get re-focused after selection. _.delay( function() { if ( ! editor.state.focused ) { updateErrorNotice(); } }, editorRefocusWait ); }); /* * Make sure setting validities are set if the user tries to click Publish * while an autocomplete dropdown is still open. The Customizer will block * saving when a setting has an error notifications on it. This is only * necessary for mouse interactions because keyboards will have already * blurred the field and cause onUpdateErrorNotice to have already been * called. */ $( document.body ).on( 'mousedown', function( event ) { if ( editor.state.focused && ! $.contains( editor.display.wrapper, event.target ) && ! $( event.target ).hasClass( 'CodeMirror-hint' ) ) { updateErrorNotice(); } }); } /** * Configure tabbing. * * @param {CodeMirror} codemirror - Editor. * @param {Object} settings - Code editor settings. * @param {Object} settings.codeMirror - Settings for CodeMirror. * @param {Function} settings.onTabNext - Callback to handle tabbing to the next tabbable element. * @param {Function} settings.onTabPrevious - Callback to handle tabbing to the previous tabbable element. * * @return {void} */ function configureTabbing( codemirror, settings ) { var $textarea = $( codemirror.getTextArea() ); codemirror.on( 'blur', function() { $textarea.data( 'next-tab-blurs', false ); }); codemirror.on( 'keydown', function onKeydown( editor, event ) { var tabKeyCode = 9, escKeyCode = 27; // Take note of the ESC keypress so that the next TAB can focus outside the editor. if ( escKeyCode === event.keyCode ) { $textarea.data( 'next-tab-blurs', true ); return; } // Short-circuit if tab key is not being pressed or the tab key press should move focus. if ( tabKeyCode !== event.keyCode || ! $textarea.data( 'next-tab-blurs' ) ) { return; } // Focus on previous or next focusable item. if ( event.shiftKey ) { settings.onTabPrevious( codemirror, event ); } else { settings.onTabNext( codemirror, event ); } // Reset tab state. $textarea.data( 'next-tab-blurs', false ); // Prevent tab character from being added. event.preventDefault(); }); } /** * @typedef {object} wp.codeEditor~CodeEditorInstance * @property {object} settings - The code editor settings. * @property {CodeMirror} codemirror - The CodeMirror instance. */ /** * Initialize Code Editor (CodeMirror) for an existing textarea. * * @since 4.9.0 * * @param {string|jQuery|Element} textarea - The HTML id, jQuery object, or DOM Element for the textarea that is used for the editor. * @param {Object} [settings] - Settings to override defaults. * @param {Function} [settings.onChangeLintingErrors] - Callback for when the linting errors have changed. * @param {Function} [settings.onUpdateErrorNotice] - Callback for when error notice should be displayed. * @param {Function} [settings.onTabPrevious] - Callback to handle tabbing to the previous tabbable element. * @param {Function} [settings.onTabNext] - Callback to handle tabbing to the next tabbable element. * @param {Object} [settings.codemirror] - Options for CodeMirror. * @param {Object} [settings.csslint] - Rules for CSSLint. * @param {Object} [settings.htmlhint] - Rules for HTMLHint. * @param {Object} [settings.jshint] - Rules for JSHint. * * @return {CodeEditorInstance} Instance. */ wp.codeEditor.initialize = function initialize( textarea, settings ) { var $textarea, codemirror, instanceSettings, instance; if ( 'string' === typeof textarea ) { $textarea = $( '#' + textarea ); } else { $textarea = $( textarea ); } instanceSettings = $.extend( {}, wp.codeEditor.defaultSettings, settings ); instanceSettings.codemirror = $.extend( {}, instanceSettings.codemirror ); codemirror = wp.CodeMirror.fromTextArea( $textarea[0], instanceSettings.codemirror ); configureLinting( codemirror, instanceSettings ); instance = { settings: instanceSettings, codemirror: codemirror }; if ( codemirror.showHint ) { codemirror.on( 'keyup', function( editor, event ) { // eslint-disable-line complexity var shouldAutocomplete, isAlphaKey = /^[a-zA-Z]$/.test( event.key ), lineBeforeCursor, innerMode, token; if ( codemirror.state.completionActive && isAlphaKey ) { return; } // Prevent autocompletion in string literals or comments. token = codemirror.getTokenAt( codemirror.getCursor() ); if ( 'string' === token.type || 'comment' === token.type ) { return; } innerMode = wp.CodeMirror.innerMode( codemirror.getMode(), token.state ).mode.name; lineBeforeCursor = codemirror.doc.getLine( codemirror.doc.getCursor().line ).substr( 0, codemirror.doc.getCursor().ch ); if ( 'html' === innerMode || 'xml' === innerMode ) { shouldAutocomplete = '<' === event.key || '/' === event.key && 'tag' === token.type || isAlphaKey && 'tag' === token.type || isAlphaKey && 'attribute' === token.type || '=' === token.string && token.state.htmlState && token.state.htmlState.tagName; } else if ( 'css' === innerMode ) { shouldAutocomplete = isAlphaKey || ':' === event.key || ' ' === event.key && /:\s+$/.test( lineBeforeCursor ); } else if ( 'javascript' === innerMode ) { shouldAutocomplete = isAlphaKey || '.' === event.key; } else if ( 'clike' === innerMode && 'php' === codemirror.options.mode ) { shouldAutocomplete = 'keyword' === token.type || 'variable' === token.type; } if ( shouldAutocomplete ) { codemirror.showHint( { completeSingle: false } ); } }); } // Facilitate tabbing out of the editor. configureTabbing( codemirror, settings ); return instance; }; })( window.jQuery, window.wp ); image-edit.min.js000064400000036233147573140730007713 0ustar00/*! This file is auto-generated */ !function(c){var s=wp.i18n.__,d=window.imageEdit={iasapi:{},hold:{},postid:"",_view:!1,toggleCropTool:function(t,i,e){var a,o,r,n=c("#image-preview-"+t),s=this.iasapi.getSelection();d.toggleControls(e),"false"==("true"===c(e).attr("aria-expanded")?"true":"false")?(this.iasapi.cancelSelection(),d.setDisabled(c(".imgedit-crop-clear"),0)):(d.setDisabled(c(".imgedit-crop-clear"),1),e=c("#imgedit-start-x-"+t).val()?c("#imgedit-start-x-"+t).val():0,a=c("#imgedit-start-y-"+t).val()?c("#imgedit-start-y-"+t).val():0,o=c("#imgedit-sel-width-"+t).val()?c("#imgedit-sel-width-"+t).val():n.innerWidth(),r=c("#imgedit-sel-height-"+t).val()?c("#imgedit-sel-height-"+t).val():n.innerHeight(),isNaN(s.x1)&&(this.setCropSelection(t,{x1:e,y1:a,x2:o,y2:r,width:o,height:r}),s=this.iasapi.getSelection()),0===s.x1&&0===s.y1&&0===s.x2&&0===s.y2?this.iasapi.setSelection(0,0,n.innerWidth(),n.innerHeight(),!0):this.iasapi.setSelection(e,a,o,r,!0),this.iasapi.setOptions({show:!0}),this.iasapi.update())},handleCropToolClick:function(t,i,e){e.classList.contains("imgedit-crop-clear")?(this.iasapi.cancelSelection(),d.setDisabled(c(".imgedit-crop-apply"),0),c("#imgedit-sel-width-"+t).val(""),c("#imgedit-sel-height-"+t).val(""),c("#imgedit-start-x-"+t).val("0"),c("#imgedit-start-y-"+t).val("0"),c("#imgedit-selection-"+t).val("")):d.crop(t,i,e)},intval:function(t){return 0|t},setDisabled:function(t,i){i?t.removeClass("disabled").prop("disabled",!1):t.addClass("disabled").prop("disabled",!0)},init:function(e){var t=this,i=c("#image-editor-"+t.postid);t.postid!==e&&i.length&&t.close(t.postid),t.hold.sizer=parseFloat(c("#imgedit-sizer-"+e).val()),t.postid=e,c("#imgedit-response-"+e).empty(),c("#imgedit-panel-"+e).on("keypress",function(t){var i=c("#imgedit-nonce-"+e).val();26===t.which&&t.ctrlKey&&d.undo(e,i),25===t.which&&t.ctrlKey&&d.redo(e,i)}),c("#imgedit-panel-"+e).on("keypress",'input[type="text"]',function(t){var i=t.keyCode;if(36this.hold.oh||r&&r>this.hold.ow?(t.css("visibility","visible"),s.prop("disabled",!0)):(t.css("visibility","hidden"),s.prop("disabled",!1)))},getSelRatio:function(t){var i=this.hold.w,e=this.hold.h,a=this.intval(c("#imgedit-crop-width-"+t).val()),t=this.intval(c("#imgedit-crop-height-"+t).val());return a&&t?a+":"+t:i&&e?i+":"+e:"1:1"},filterHistory:function(t,i){var e,a,o,r=c("#imgedit-history-"+t).val(),n=[];if(""===r)return"";if(r=JSON.parse(r),0<(e=this.intval(c("#imgedit-undone-"+t).val())))for(;0').on("load",{history:t.history},function(t){var i=c("#imgedit-crop-"+o),e=d,a=(""!==t.data.history&&(t=JSON.parse(t.data.history))[t.length-1].hasOwnProperty("c")&&(e.setDisabled(c("#image-undo-"+o),!0),c("#image-undo-"+o).trigger("focus")),i.empty().append(n),t=Math.max(e.hold.w,e.hold.h),a=Math.max(c(n).width(),c(n).height()),e.hold.sizer=a

    '+t+"

  • "),i.toggleEditor(o,0,!0),wp.a11y.speak(t,"assertive")}).attr("src",ajaxurl+"?"+c.param(t))},action:function(i,t,e){var a,o,r,n,s=this;if(s.notsaved(i))return!1;if(t={action:"image-editor",_ajax_nonce:t,postid:i},"scale"===e){if(a=c("#imgedit-scale-width-"+i),o=c("#imgedit-scale-height-"+i),r=s.intval(a.val()),n=s.intval(o.val()),r<1)return a.trigger("focus"),!1;if(n<1)return o.trigger("focus"),!1;if(r===s.hold.ow||n===s.hold.oh)return!1;t.do="scale",t.fwidth=r,t.fheight=n}else{if("restore"!==e)return!1;t.do="restore"}s.toggleEditor(i,1),c.post(ajaxurl,t,function(t){c("#image-editor-"+i).empty().append(t.data.html),s.toggleEditor(i,0,!0),s._view&&s._view.refresh()}).done(function(t){t&&t.data.message.msg?wp.a11y.speak(t.data.message.msg):t&&t.data.message.error&&wp.a11y.speak(t.data.message.error)})},save:function(i,t){var e=this.getTarget(i),a=this.filterHistory(i,0),o=this;if(""===a)return!1;this.toggleEditor(i,1),t={action:"image-editor",_ajax_nonce:t,postid:i,history:a,target:e,context:c("#image-edit-context").length?c("#image-edit-context").val():null,do:"save"},c.post(ajaxurl,t,function(t){t.data.error?(c("#imgedit-response-"+i).html('"),d.close(i),wp.a11y.speak(t.data.error)):(t.data.fw&&t.data.fh&&c("#media-dims-"+i).html(t.data.fw+" × "+t.data.fh),t.data.thumbnail&&c(".thumbnail","#thumbnail-head-"+i).attr("src",""+t.data.thumbnail),t.data.msg&&(c("#imgedit-response-"+i).html('"),wp.a11y.speak(t.data.msg)),o._view?o._view.save():d.close(i))})},open:function(e,t,i){this._view=i;var a=c("#image-editor-"+e),o=c("#media-head-"+e),r=c("#imgedit-open-btn-"+e),n=r.siblings(".spinner");if(!r.hasClass("button-activated"))return n.addClass("is-active"),c.ajax({url:ajaxurl,type:"post",data:{action:"image-editor",_ajax_nonce:t,postid:e,do:"open"},beforeSend:function(){r.addClass("button-activated")}}).done(function(t){var i;"-1"===t&&(i=s("Could not load the preview image."),a.html('")),t.data&&t.data.html&&a.html(t.data.html),o.fadeOut("fast",function(){a.fadeIn("fast",function(){i&&c(document).trigger("image-editor-ui-ready")}),r.removeClass("button-activated"),n.removeClass("is-active")}),d.init(e)})},imgLoaded:function(t){var i=c("#image-preview-"+t),e=c("#imgedit-crop-"+t);void 0===this.hold.sizer&&this.init(t),this.calculateImgSize(t),this.initCrop(t,i,e),this.setCropSelection(t,{x1:0,y1:0,x2:0,y2:0,width:i.innerWidth(),height:i.innerHeight()}),this.toggleEditor(t,0,!0)},focusManager:function(){setTimeout(function(){var t=c('.notice[role="alert"]');(t=t.length?t:c(".imgedit-wrap").find(":tabbable:first")).attr("tabindex","-1").trigger("focus")},100)},initCrop:function(r,t,i){var n=this,o=c("#imgedit-sel-width-"+r),s=c("#imgedit-sel-height-"+r),t=c(t);t.data("imgAreaSelect")||(n.iasapi=t.imgAreaSelect({parent:i,instance:!0,handles:!0,keys:!0,minWidth:3,minHeight:3,onInit:function(t){c(t).next().css("position","absolute").nextAll(".imgareaselect-outer").css("position","absolute"),i.children().on("mousedown touchstart",function(t){var i=!1,e=n.iasapi.getSelection(),a=n.intval(c("#imgedit-crop-width-"+r).val()),o=n.intval(c("#imgedit-crop-height-"+r).val());a&&o?i=n.getSelRatio(r):t.shiftKey&&e&&e.width&&e.height&&(i=e.width+":"+e.height),n.iasapi.setOptions({aspectRatio:i})})},onSelectStart:function(){d.setDisabled(c("#imgedit-crop-sel-"+r),1),d.setDisabled(c(".imgedit-crop-clear"),1),d.setDisabled(c(".imgedit-crop-apply"),1)},onSelectEnd:function(t,i){d.setCropSelection(r,i),c("#imgedit-crop > *").is(":visible")||d.toggleControls(c(".imgedit-crop.button"))},onSelectChange:function(t,i){var e=d.hold.sizer,a=d.currentCropSelection;null!=a&&a.width==i.width&&a.height==i.height||(o.val(Math.min(d.hold.w,d.round(i.width/e))),s.val(Math.min(d.hold.h,d.round(i.height/e))),n.currentCropSelection=i)}}))},setCropSelection:function(t,i){var e=c("#imgedit-sel-width-"+t),a=c("#imgedit-sel-height-"+t),o=this.hold.sizer,r=this.hold;if(!(i=i||0)||i.width<3&&i.height<3)return this.setDisabled(c(".imgedit-crop","#imgedit-panel-"+t),1),this.setDisabled(c("#imgedit-crop-sel-"+t),1),c("#imgedit-sel-width-"+t).val(""),c("#imgedit-sel-height-"+t).val(""),c("#imgedit-start-x-"+t).val("0"),c("#imgedit-start-y-"+t).val("0"),c("#imgedit-selection-"+t).val(""),!1;var n=r.w-(Math.round(i.x1/o)+parseInt(e.val())),r=r.h-(Math.round(i.y1/o)+parseInt(a.val())),n={r:1,x:Math.round(i.x1/o)+Math.min(0,n),y:Math.round(i.y1/o)+Math.min(0,r),w:e.val(),h:a.val()};this.setDisabled(c(".imgedit-crop","#imgedit-panel-"+t),1),c("#imgedit-selection-"+t).val(JSON.stringify(n))},close:function(t,i){if((i=i||!1)&&this.notsaved(t))return!1;this.iasapi={},this.hold={},this._view?this._view.back():c("#image-editor-"+t).fadeOut("fast",function(){c("#media-head-"+t).fadeIn("fast",function(){c("#imgedit-open-btn-"+t).trigger("focus")}),c(this).empty()})},notsaved:function(t){var i=c("#imgedit-history-"+t).val(),i=""!==i?JSON.parse(i):[];return this.intval(c("#imgedit-undone-"+t).val())

    '+o+"

    "),wp.a11y.speak(o,"assertive"),c(i?"#imgedit-crop-height-"+t:"#imgedit-crop-width-"+t).val("")):void 0!==(r=c("#imgedit-crop-"+t).find(".notice-error"))&&r.remove(),this.iasapi.setSelection(e.x1,e.y1,e.x2,a),this.iasapi.update())},validateNumeric:function(t){if(!1===this.intval(c(t).val()))return c(t).val(""),!1}}}(jQuery);image-edit.js000064400000117750147573140730007135 0ustar00/** * The functions necessary for editing images. * * @since 2.9.0 * @output wp-admin/js/image-edit.js */ /* global ajaxurl, confirm */ (function($) { var __ = wp.i18n.__; /** * Contains all the methods to initialize and control the image editor. * * @namespace imageEdit */ var imageEdit = window.imageEdit = { iasapi : {}, hold : {}, postid : '', _view : false, /** * Enable crop tool. */ toggleCropTool: function( postid, nonce, cropButton ) { var img = $( '#image-preview-' + postid ), selection = this.iasapi.getSelection(); imageEdit.toggleControls( cropButton ); var $el = $( cropButton ); var state = ( $el.attr( 'aria-expanded' ) === 'true' ) ? 'true' : 'false'; // Crop tools have been closed. if ( 'false' === state ) { // Cancel selection, but do not unset inputs. this.iasapi.cancelSelection(); imageEdit.setDisabled($('.imgedit-crop-clear'), 0); } else { imageEdit.setDisabled($('.imgedit-crop-clear'), 1); // Get values from inputs to restore previous selection. var startX = ( $( '#imgedit-start-x-' + postid ).val() ) ? $('#imgedit-start-x-' + postid).val() : 0; var startY = ( $( '#imgedit-start-y-' + postid ).val() ) ? $('#imgedit-start-y-' + postid).val() : 0; var width = ( $( '#imgedit-sel-width-' + postid ).val() ) ? $('#imgedit-sel-width-' + postid).val() : img.innerWidth(); var height = ( $( '#imgedit-sel-height-' + postid ).val() ) ? $('#imgedit-sel-height-' + postid).val() : img.innerHeight(); // Ensure selection is available, otherwise reset to full image. if ( isNaN( selection.x1 ) ) { this.setCropSelection( postid, { 'x1': startX, 'y1': startY, 'x2': width, 'y2': height, 'width': width, 'height': height } ); selection = this.iasapi.getSelection(); } // If we don't already have a selection, select the entire image. if ( 0 === selection.x1 && 0 === selection.y1 && 0 === selection.x2 && 0 === selection.y2 ) { this.iasapi.setSelection( 0, 0, img.innerWidth(), img.innerHeight(), true ); this.iasapi.setOptions( { show: true } ); this.iasapi.update(); } else { this.iasapi.setSelection( startX, startY, width, height, true ); this.iasapi.setOptions( { show: true } ); this.iasapi.update(); } } }, /** * Handle crop tool clicks. */ handleCropToolClick: function( postid, nonce, cropButton ) { if ( cropButton.classList.contains( 'imgedit-crop-clear' ) ) { this.iasapi.cancelSelection(); imageEdit.setDisabled($('.imgedit-crop-apply'), 0); $('#imgedit-sel-width-' + postid).val(''); $('#imgedit-sel-height-' + postid).val(''); $('#imgedit-start-x-' + postid).val('0'); $('#imgedit-start-y-' + postid).val('0'); $('#imgedit-selection-' + postid).val(''); } else { // Otherwise, perform the crop. imageEdit.crop( postid, nonce , cropButton ); } }, /** * Converts a value to an integer. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} f The float value that should be converted. * * @return {number} The integer representation from the float value. */ intval : function(f) { /* * Bitwise OR operator: one of the obscure ways to truncate floating point figures, * worth reminding JavaScript doesn't have a distinct "integer" type. */ return f | 0; }, /** * Adds the disabled attribute and class to a single form element or a field set. * * @since 2.9.0 * * @memberof imageEdit * * @param {jQuery} el The element that should be modified. * @param {boolean|number} s The state for the element. If set to true * the element is disabled, * otherwise the element is enabled. * The function is sometimes called with a 0 or 1 * instead of true or false. * * @return {void} */ setDisabled : function( el, s ) { /* * `el` can be a single form element or a fieldset. Before #28864, the disabled state on * some text fields was handled targeting $('input', el). Now we need to handle the * disabled state on buttons too so we can just target `el` regardless if it's a single * element or a fieldset because when a fieldset is disabled, its descendants are disabled too. */ if ( s ) { el.removeClass( 'disabled' ).prop( 'disabled', false ); } else { el.addClass( 'disabled' ).prop( 'disabled', true ); } }, /** * Initializes the image editor. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} postid The post ID. * * @return {void} */ init : function(postid) { var t = this, old = $('#image-editor-' + t.postid); if ( t.postid !== postid && old.length ) { t.close(t.postid); } t.hold.sizer = parseFloat( $('#imgedit-sizer-' + postid).val() ); t.postid = postid; $('#imgedit-response-' + postid).empty(); $('#imgedit-panel-' + postid).on( 'keypress', function(e) { var nonce = $( '#imgedit-nonce-' + postid ).val(); if ( e.which === 26 && e.ctrlKey ) { imageEdit.undo( postid, nonce ); } if ( e.which === 25 && e.ctrlKey ) { imageEdit.redo( postid, nonce ); } }); $('#imgedit-panel-' + postid).on( 'keypress', 'input[type="text"]', function(e) { var k = e.keyCode; // Key codes 37 through 40 are the arrow keys. if ( 36 < k && k < 41 ) { $(this).trigger( 'blur' ); } // The key code 13 is the Enter key. if ( 13 === k ) { e.preventDefault(); e.stopPropagation(); return false; } }); $( document ).on( 'image-editor-ui-ready', this.focusManager ); }, /** * Calculate the image size and save it to memory. * * @since 6.7.0 * * @memberof imageEdit * * @param {number} postid The post ID. * * @return {void} */ calculateImgSize: function( postid ) { var t = this, x = t.intval( $( '#imgedit-x-' + postid ).val() ), y = t.intval( $( '#imgedit-y-' + postid ).val() ); t.hold.w = t.hold.ow = x; t.hold.h = t.hold.oh = y; t.hold.xy_ratio = x / y; t.hold.sizer = parseFloat( $( '#imgedit-sizer-' + postid ).val() ); t.currentCropSelection = null; }, /** * Toggles the wait/load icon in the editor. * * @since 2.9.0 * @since 5.5.0 Added the triggerUIReady parameter. * * @memberof imageEdit * * @param {number} postid The post ID. * @param {number} toggle Is 0 or 1, fades the icon in when 1 and out when 0. * @param {boolean} triggerUIReady Whether to trigger a custom event when the UI is ready. Default false. * * @return {void} */ toggleEditor: function( postid, toggle, triggerUIReady ) { var wait = $('#imgedit-wait-' + postid); if ( toggle ) { wait.fadeIn( 'fast' ); } else { wait.fadeOut( 'fast', function() { if ( triggerUIReady ) { $( document ).trigger( 'image-editor-ui-ready' ); } } ); } }, /** * Shows or hides image menu popup. * * @since 6.3.0 * * @memberof imageEdit * * @param {HTMLElement} el The activated control element. * * @return {boolean} Always returns false. */ togglePopup : function(el) { var $el = $( el ); var $targetEl = $( el ).attr( 'aria-controls' ); var $target = $( '#' + $targetEl ); $el .attr( 'aria-expanded', 'false' === $el.attr( 'aria-expanded' ) ? 'true' : 'false' ); // Open menu and set z-index to appear above image crop area if it is enabled. $target .toggleClass( 'imgedit-popup-menu-open' ).slideToggle( 'fast' ).css( { 'z-index' : 200000 } ); // Move focus to first item in menu when opening menu. if ( 'true' === $el.attr( 'aria-expanded' ) ) { $target.find( 'button' ).first().trigger( 'focus' ); } return false; }, /** * Observes whether the popup should remain open based on focus position. * * @since 6.4.0 * * @memberof imageEdit * * @param {HTMLElement} el The activated control element. * * @return {boolean} Always returns false. */ monitorPopup : function() { var $parent = document.querySelector( '.imgedit-rotate-menu-container' ); var $toggle = document.querySelector( '.imgedit-rotate-menu-container .imgedit-rotate' ); setTimeout( function() { var $focused = document.activeElement; var $contains = $parent.contains( $focused ); // If $focused is defined and not inside the menu container, close the popup. if ( $focused && ! $contains ) { if ( 'true' === $toggle.getAttribute( 'aria-expanded' ) ) { imageEdit.togglePopup( $toggle ); } } }, 100 ); return false; }, /** * Navigate popup menu by arrow keys. * * @since 6.3.0 * @since 6.7.0 Added the event parameter. * * @memberof imageEdit * * @param {Event} event The key or click event. * @param {HTMLElement} el The current element. * * @return {boolean} Always returns false. */ browsePopup : function(event, el) { var $el = $( el ); var $collection = $( el ).parent( '.imgedit-popup-menu' ).find( 'button' ); var $index = $collection.index( $el ); var $prev = $index - 1; var $next = $index + 1; var $last = $collection.length; if ( $prev < 0 ) { $prev = $last - 1; } if ( $next === $last ) { $next = 0; } var target = false; if ( event.keyCode === 40 ) { target = $collection.get( $next ); } else if ( event.keyCode === 38 ) { target = $collection.get( $prev ); } if ( target ) { target.focus(); event.preventDefault(); } return false; }, /** * Close popup menu and reset focus on feature activation. * * @since 6.3.0 * * @memberof imageEdit * * @param {HTMLElement} el The current element. * * @return {boolean} Always returns false. */ closePopup : function(el) { var $parent = $(el).parent( '.imgedit-popup-menu' ); var $controlledID = $parent.attr( 'id' ); var $target = $( 'button[aria-controls="' + $controlledID + '"]' ); $target .attr( 'aria-expanded', 'false' ).trigger( 'focus' ); $parent .toggleClass( 'imgedit-popup-menu-open' ).slideToggle( 'fast' ); return false; }, /** * Shows or hides the image edit help box. * * @since 2.9.0 * * @memberof imageEdit * * @param {HTMLElement} el The element to create the help window in. * * @return {boolean} Always returns false. */ toggleHelp : function(el) { var $el = $( el ); $el .attr( 'aria-expanded', 'false' === $el.attr( 'aria-expanded' ) ? 'true' : 'false' ) .parents( '.imgedit-group-top' ).toggleClass( 'imgedit-help-toggled' ).find( '.imgedit-help' ).slideToggle( 'fast' ); return false; }, /** * Shows or hides image edit input fields when enabled. * * @since 6.3.0 * * @memberof imageEdit * * @param {HTMLElement} el The element to trigger the edit panel. * * @return {boolean} Always returns false. */ toggleControls : function(el) { var $el = $( el ); var $target = $( '#' + $el.attr( 'aria-controls' ) ); $el .attr( 'aria-expanded', 'false' === $el.attr( 'aria-expanded' ) ? 'true' : 'false' ); $target .parent( '.imgedit-group' ).toggleClass( 'imgedit-panel-active' ); return false; }, /** * Gets the value from the image edit target. * * The image edit target contains the image sizes where the (possible) changes * have to be applied to. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} postid The post ID. * * @return {string} The value from the imagedit-save-target input field when available, * 'full' when not selected, or 'all' if it doesn't exist. */ getTarget : function( postid ) { var element = $( '#imgedit-save-target-' + postid ); if ( element.length ) { return element.find( 'input[name="imgedit-target-' + postid + '"]:checked' ).val() || 'full'; } return 'all'; }, /** * Recalculates the height or width and keeps the original aspect ratio. * * If the original image size is exceeded a red exclamation mark is shown. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} postid The current post ID. * @param {number} x Is 0 when it applies the y-axis * and 1 when applicable for the x-axis. * @param {jQuery} el Element. * * @return {void} */ scaleChanged : function( postid, x, el ) { var w = $('#imgedit-scale-width-' + postid), h = $('#imgedit-scale-height-' + postid), warn = $('#imgedit-scale-warn-' + postid), w1 = '', h1 = '', scaleBtn = $('#imgedit-scale-button'); if ( false === this.validateNumeric( el ) ) { return; } if ( x ) { h1 = ( w.val() !== '' ) ? Math.round( w.val() / this.hold.xy_ratio ) : ''; h.val( h1 ); } else { w1 = ( h.val() !== '' ) ? Math.round( h.val() * this.hold.xy_ratio ) : ''; w.val( w1 ); } if ( ( h1 && h1 > this.hold.oh ) || ( w1 && w1 > this.hold.ow ) ) { warn.css('visibility', 'visible'); scaleBtn.prop('disabled', true); } else { warn.css('visibility', 'hidden'); scaleBtn.prop('disabled', false); } }, /** * Gets the selected aspect ratio. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} postid The post ID. * * @return {string} The aspect ratio. */ getSelRatio : function(postid) { var x = this.hold.w, y = this.hold.h, X = this.intval( $('#imgedit-crop-width-' + postid).val() ), Y = this.intval( $('#imgedit-crop-height-' + postid).val() ); if ( X && Y ) { return X + ':' + Y; } if ( x && y ) { return x + ':' + y; } return '1:1'; }, /** * Removes the last action from the image edit history. * The history consist of (edit) actions performed on the image. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} postid The post ID. * @param {number} setSize 0 or 1, when 1 the image resets to its original size. * * @return {string} JSON string containing the history or an empty string if no history exists. */ filterHistory : function(postid, setSize) { // Apply undo state to history. var history = $('#imgedit-history-' + postid).val(), pop, n, o, i, op = []; if ( history !== '' ) { // Read the JSON string with the image edit history. history = JSON.parse(history); pop = this.intval( $('#imgedit-undone-' + postid).val() ); if ( pop > 0 ) { while ( pop > 0 ) { history.pop(); pop--; } } // Reset size to its original state. if ( setSize ) { if ( !history.length ) { this.hold.w = this.hold.ow; this.hold.h = this.hold.oh; return ''; } // Restore original 'o'. o = history[history.length - 1]; // c = 'crop', r = 'rotate', f = 'flip'. o = o.c || o.r || o.f || false; if ( o ) { // fw = Full image width. this.hold.w = o.fw; // fh = Full image height. this.hold.h = o.fh; } } // Filter the last step/action from the history. for ( n in history ) { i = history[n]; if ( i.hasOwnProperty('c') ) { op[n] = { 'c': { 'x': i.c.x, 'y': i.c.y, 'w': i.c.w, 'h': i.c.h, 'r': i.c.r } }; } else if ( i.hasOwnProperty('r') ) { op[n] = { 'r': i.r.r }; } else if ( i.hasOwnProperty('f') ) { op[n] = { 'f': i.f.f }; } } return JSON.stringify(op); } return ''; }, /** * Binds the necessary events to the image. * * When the image source is reloaded the image will be reloaded. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} postid The post ID. * @param {string} nonce The nonce to verify the request. * @param {function} callback Function to execute when the image is loaded. * * @return {void} */ refreshEditor : function(postid, nonce, callback) { var t = this, data, img; t.toggleEditor(postid, 1); data = { 'action': 'imgedit-preview', '_ajax_nonce': nonce, 'postid': postid, 'history': t.filterHistory(postid, 1), 'rand': t.intval(Math.random() * 1000000) }; img = $( '' ) .on( 'load', { history: data.history }, function( event ) { var max1, max2, parent = $( '#imgedit-crop-' + postid ), t = imageEdit, historyObj; // Checks if there already is some image-edit history. if ( '' !== event.data.history ) { historyObj = JSON.parse( event.data.history ); // If last executed action in history is a crop action. if ( historyObj[historyObj.length - 1].hasOwnProperty( 'c' ) ) { /* * A crop action has completed and the crop button gets disabled * ensure the undo button is enabled. */ t.setDisabled( $( '#image-undo-' + postid) , true ); // Move focus to the undo button to avoid a focus loss. $( '#image-undo-' + postid ).trigger( 'focus' ); } } parent.empty().append(img); // w, h are the new full size dimensions. max1 = Math.max( t.hold.w, t.hold.h ); max2 = Math.max( $(img).width(), $(img).height() ); t.hold.sizer = max1 > max2 ? max2 / max1 : 1; t.initCrop(postid, img, parent); if ( (typeof callback !== 'undefined') && callback !== null ) { callback(); } if ( $('#imgedit-history-' + postid).val() && $('#imgedit-undone-' + postid).val() === '0' ) { $('button.imgedit-submit-btn', '#imgedit-panel-' + postid).prop('disabled', false); } else { $('button.imgedit-submit-btn', '#imgedit-panel-' + postid).prop('disabled', true); } var successMessage = __( 'Image updated.' ); t.toggleEditor(postid, 0); wp.a11y.speak( successMessage, 'assertive' ); }) .on( 'error', function() { var errorMessage = __( 'Could not load the preview image. Please reload the page and try again.' ); $( '#imgedit-crop-' + postid ) .empty() .append( '' ); t.toggleEditor( postid, 0, true ); wp.a11y.speak( errorMessage, 'assertive' ); } ) .attr('src', ajaxurl + '?' + $.param(data)); }, /** * Performs an image edit action. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} postid The post ID. * @param {string} nonce The nonce to verify the request. * @param {string} action The action to perform on the image. * The possible actions are: "scale" and "restore". * * @return {boolean|void} Executes a post request that refreshes the page * when the action is performed. * Returns false if an invalid action is given, * or when the action cannot be performed. */ action : function(postid, nonce, action) { var t = this, data, w, h, fw, fh; if ( t.notsaved(postid) ) { return false; } data = { 'action': 'image-editor', '_ajax_nonce': nonce, 'postid': postid }; if ( 'scale' === action ) { w = $('#imgedit-scale-width-' + postid), h = $('#imgedit-scale-height-' + postid), fw = t.intval(w.val()), fh = t.intval(h.val()); if ( fw < 1 ) { w.trigger( 'focus' ); return false; } else if ( fh < 1 ) { h.trigger( 'focus' ); return false; } if ( fw === t.hold.ow || fh === t.hold.oh ) { return false; } data['do'] = 'scale'; data.fwidth = fw; data.fheight = fh; } else if ( 'restore' === action ) { data['do'] = 'restore'; } else { return false; } t.toggleEditor(postid, 1); $.post( ajaxurl, data, function( response ) { $( '#image-editor-' + postid ).empty().append( response.data.html ); t.toggleEditor( postid, 0, true ); // Refresh the attachment model so that changes propagate. if ( t._view ) { t._view.refresh(); } } ).done( function( response ) { // Whether the executed action was `scale` or `restore`, the response does have a message. if ( response && response.data.message.msg ) { wp.a11y.speak( response.data.message.msg ); return; } if ( response && response.data.message.error ) { wp.a11y.speak( response.data.message.error ); } } ); }, /** * Stores the changes that are made to the image. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} postid The post ID to get the image from the database. * @param {string} nonce The nonce to verify the request. * * @return {boolean|void} If the actions are successfully saved a response message is shown. * Returns false if there is no image editing history, * thus there are not edit-actions performed on the image. */ save : function(postid, nonce) { var data, target = this.getTarget(postid), history = this.filterHistory(postid, 0), self = this; if ( '' === history ) { return false; } this.toggleEditor(postid, 1); data = { 'action': 'image-editor', '_ajax_nonce': nonce, 'postid': postid, 'history': history, 'target': target, 'context': $('#image-edit-context').length ? $('#image-edit-context').val() : null, 'do': 'save' }; // Post the image edit data to the backend. $.post( ajaxurl, data, function( response ) { // If a response is returned, close the editor and show an error. if ( response.data.error ) { $( '#imgedit-response-' + postid ) .html( '' ); imageEdit.close(postid); wp.a11y.speak( response.data.error ); return; } if ( response.data.fw && response.data.fh ) { $( '#media-dims-' + postid ).html( response.data.fw + ' × ' + response.data.fh ); } if ( response.data.thumbnail ) { $( '.thumbnail', '#thumbnail-head-' + postid ).attr( 'src', '' + response.data.thumbnail ); } if ( response.data.msg ) { $( '#imgedit-response-' + postid ) .html( '' ); wp.a11y.speak( response.data.msg ); } if ( self._view ) { self._view.save(); } else { imageEdit.close(postid); } }); }, /** * Creates the image edit window. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} postid The post ID for the image. * @param {string} nonce The nonce to verify the request. * @param {Object} view The image editor view to be used for the editing. * * @return {void|promise} Either returns void if the button was already activated * or returns an instance of the image editor, wrapped in a promise. */ open : function( postid, nonce, view ) { this._view = view; var dfd, data, elem = $( '#image-editor-' + postid ), head = $( '#media-head-' + postid ), btn = $( '#imgedit-open-btn-' + postid ), spin = btn.siblings( '.spinner' ); /* * Instead of disabling the button, which causes a focus loss and makes screen * readers announce "unavailable", return if the button was already clicked. */ if ( btn.hasClass( 'button-activated' ) ) { return; } spin.addClass( 'is-active' ); data = { 'action': 'image-editor', '_ajax_nonce': nonce, 'postid': postid, 'do': 'open' }; dfd = $.ajax( { url: ajaxurl, type: 'post', data: data, beforeSend: function() { btn.addClass( 'button-activated' ); } } ).done( function( response ) { var errorMessage; if ( '-1' === response ) { errorMessage = __( 'Could not load the preview image.' ); elem.html( '' ); } if ( response.data && response.data.html ) { elem.html( response.data.html ); } head.fadeOut( 'fast', function() { elem.fadeIn( 'fast', function() { if ( errorMessage ) { $( document ).trigger( 'image-editor-ui-ready' ); } } ); btn.removeClass( 'button-activated' ); spin.removeClass( 'is-active' ); } ); // Initialize the Image Editor now that everything is ready. imageEdit.init( postid ); } ); return dfd; }, /** * Initializes the cropping tool and sets a default cropping selection. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} postid The post ID. * * @return {void} */ imgLoaded : function(postid) { var img = $('#image-preview-' + postid), parent = $('#imgedit-crop-' + postid); // Ensure init has run even when directly loaded. if ( 'undefined' === typeof this.hold.sizer ) { this.init( postid ); } this.calculateImgSize( postid ); this.initCrop(postid, img, parent); this.setCropSelection( postid, { 'x1': 0, 'y1': 0, 'x2': 0, 'y2': 0, 'width': img.innerWidth(), 'height': img.innerHeight() } ); this.toggleEditor( postid, 0, true ); }, /** * Manages keyboard focus in the Image Editor user interface. * * @since 5.5.0 * * @return {void} */ focusManager: function() { /* * Editor is ready. Move focus to one of the admin alert notices displayed * after a user action or to the first focusable element. Since the DOM * update is pretty large, the timeout helps browsers update their * accessibility tree to better support assistive technologies. */ setTimeout( function() { var elementToSetFocusTo = $( '.notice[role="alert"]' ); if ( ! elementToSetFocusTo.length ) { elementToSetFocusTo = $( '.imgedit-wrap' ).find( ':tabbable:first' ); } elementToSetFocusTo.attr( 'tabindex', '-1' ).trigger( 'focus' ); }, 100 ); }, /** * Initializes the cropping tool. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} postid The post ID. * @param {HTMLElement} image The preview image. * @param {HTMLElement} parent The preview image container. * * @return {void} */ initCrop : function(postid, image, parent) { var t = this, selW = $('#imgedit-sel-width-' + postid), selH = $('#imgedit-sel-height-' + postid), $image = $( image ), $img; // Already initialized? if ( $image.data( 'imgAreaSelect' ) ) { return; } t.iasapi = $image.imgAreaSelect({ parent: parent, instance: true, handles: true, keys: true, minWidth: 3, minHeight: 3, /** * Sets the CSS styles and binds events for locking the aspect ratio. * * @ignore * * @param {jQuery} img The preview image. */ onInit: function( img ) { // Ensure that the imgAreaSelect wrapper elements are position:absolute // (even if we're in a position:fixed modal). $img = $( img ); $img.next().css( 'position', 'absolute' ) .nextAll( '.imgareaselect-outer' ).css( 'position', 'absolute' ); /** * Binds mouse down event to the cropping container. * * @return {void} */ parent.children().on( 'mousedown touchstart', function(e) { var ratio = false, sel = t.iasapi.getSelection(), cx = t.intval( $( '#imgedit-crop-width-' + postid ).val() ), cy = t.intval( $( '#imgedit-crop-height-' + postid ).val() ); if ( cx && cy ) { ratio = t.getSelRatio( postid ); } else if ( e.shiftKey && sel && sel.width && sel.height ) { ratio = sel.width + ':' + sel.height; } t.iasapi.setOptions({ aspectRatio: ratio }); }); }, /** * Event triggered when starting a selection. * * @ignore * * @return {void} */ onSelectStart: function() { imageEdit.setDisabled($('#imgedit-crop-sel-' + postid), 1); imageEdit.setDisabled($('.imgedit-crop-clear'), 1); imageEdit.setDisabled($('.imgedit-crop-apply'), 1); }, /** * Event triggered when the selection is ended. * * @ignore * * @param {Object} img jQuery object representing the image. * @param {Object} c The selection. * * @return {Object} */ onSelectEnd: function(img, c) { imageEdit.setCropSelection(postid, c); if ( ! $('#imgedit-crop > *').is(':visible') ) { imageEdit.toggleControls($('.imgedit-crop.button')); } }, /** * Event triggered when the selection changes. * * @ignore * * @param {Object} img jQuery object representing the image. * @param {Object} c The selection. * * @return {void} */ onSelectChange: function(img, c) { var sizer = imageEdit.hold.sizer, oldSel = imageEdit.currentCropSelection; if ( oldSel != null && oldSel.width == c.width && oldSel.height == c.height ) { return; } selW.val( Math.min( imageEdit.hold.w, imageEdit.round( c.width / sizer ) ) ); selH.val( Math.min( imageEdit.hold.h, imageEdit.round( c.height / sizer ) ) ); t.currentCropSelection = c; } }); }, /** * Stores the current crop selection. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} postid The post ID. * @param {Object} c The selection. * * @return {boolean} */ setCropSelection : function(postid, c) { var sel, selW = $( '#imgedit-sel-width-' + postid ), selH = $( '#imgedit-sel-height-' + postid ), sizer = this.hold.sizer, hold = this.hold; c = c || 0; if ( !c || ( c.width < 3 && c.height < 3 ) ) { this.setDisabled( $( '.imgedit-crop', '#imgedit-panel-' + postid ), 1 ); this.setDisabled( $( '#imgedit-crop-sel-' + postid ), 1 ); $('#imgedit-sel-width-' + postid).val(''); $('#imgedit-sel-height-' + postid).val(''); $('#imgedit-start-x-' + postid).val('0'); $('#imgedit-start-y-' + postid).val('0'); $('#imgedit-selection-' + postid).val(''); return false; } // adjust the selection within the bounds of the image on 100% scale var excessW = hold.w - ( Math.round( c.x1 / sizer ) + parseInt( selW.val() ) ); var excessH = hold.h - ( Math.round( c.y1 / sizer ) + parseInt( selH.val() ) ); var x = Math.round( c.x1 / sizer ) + Math.min( 0, excessW ); var y = Math.round( c.y1 / sizer ) + Math.min( 0, excessH ); // use 100% scaling to prevent rounding errors sel = { 'r': 1, 'x': x, 'y': y, 'w': selW.val(), 'h': selH.val() }; this.setDisabled($('.imgedit-crop', '#imgedit-panel-' + postid), 1); $('#imgedit-selection-' + postid).val( JSON.stringify(sel) ); }, /** * Closes the image editor. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} postid The post ID. * @param {boolean} warn Warning message. * * @return {void|boolean} Returns false if there is a warning. */ close : function(postid, warn) { warn = warn || false; if ( warn && this.notsaved(postid) ) { return false; } this.iasapi = {}; this.hold = {}; // If we've loaded the editor in the context of a Media Modal, // then switch to the previous view, whatever that might have been. if ( this._view ){ this._view.back(); } // In case we are not accessing the image editor in the context of a View, // close the editor the old-school way. else { $('#image-editor-' + postid).fadeOut('fast', function() { $( '#media-head-' + postid ).fadeIn( 'fast', function() { // Move focus back to the Edit Image button. Runs also when saving. $( '#imgedit-open-btn-' + postid ).trigger( 'focus' ); }); $(this).empty(); }); } }, /** * Checks if the image edit history is saved. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} postid The post ID. * * @return {boolean} Returns true if the history is not saved. */ notsaved : function(postid) { var h = $('#imgedit-history-' + postid).val(), history = ( h !== '' ) ? JSON.parse(h) : [], pop = this.intval( $('#imgedit-undone-' + postid).val() ); if ( pop < history.length ) { if ( confirm( $('#imgedit-leaving-' + postid).text() ) ) { return false; } return true; } return false; }, /** * Adds an image edit action to the history. * * @since 2.9.0 * * @memberof imageEdit * * @param {Object} op The original position. * @param {number} postid The post ID. * @param {string} nonce The nonce. * * @return {void} */ addStep : function(op, postid, nonce) { var t = this, elem = $('#imgedit-history-' + postid), history = ( elem.val() !== '' ) ? JSON.parse( elem.val() ) : [], undone = $( '#imgedit-undone-' + postid ), pop = t.intval( undone.val() ); while ( pop > 0 ) { history.pop(); pop--; } undone.val(0); // Reset. history.push(op); elem.val( JSON.stringify(history) ); t.refreshEditor(postid, nonce, function() { t.setDisabled($('#image-undo-' + postid), true); t.setDisabled($('#image-redo-' + postid), false); }); }, /** * Rotates the image. * * @since 2.9.0 * * @memberof imageEdit * * @param {string} angle The angle the image is rotated with. * @param {number} postid The post ID. * @param {string} nonce The nonce. * @param {Object} t The target element. * * @return {boolean} */ rotate : function(angle, postid, nonce, t) { if ( $(t).hasClass('disabled') ) { return false; } this.closePopup(t); this.addStep({ 'r': { 'r': angle, 'fw': this.hold.h, 'fh': this.hold.w }}, postid, nonce); // Clear the selection fields after rotating. $( '#imgedit-sel-width-' + postid ).val( '' ); $( '#imgedit-sel-height-' + postid ).val( '' ); this.currentCropSelection = null; }, /** * Flips the image. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} axis The axle the image is flipped on. * @param {number} postid The post ID. * @param {string} nonce The nonce. * @param {Object} t The target element. * * @return {boolean} */ flip : function (axis, postid, nonce, t) { if ( $(t).hasClass('disabled') ) { return false; } this.closePopup(t); this.addStep({ 'f': { 'f': axis, 'fw': this.hold.w, 'fh': this.hold.h }}, postid, nonce); // Clear the selection fields after flipping. $( '#imgedit-sel-width-' + postid ).val( '' ); $( '#imgedit-sel-height-' + postid ).val( '' ); this.currentCropSelection = null; }, /** * Crops the image. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} postid The post ID. * @param {string} nonce The nonce. * @param {Object} t The target object. * * @return {void|boolean} Returns false if the crop button is disabled. */ crop : function (postid, nonce, t) { var sel = $('#imgedit-selection-' + postid).val(), w = this.intval( $('#imgedit-sel-width-' + postid).val() ), h = this.intval( $('#imgedit-sel-height-' + postid).val() ); if ( $(t).hasClass('disabled') || sel === '' ) { return false; } sel = JSON.parse(sel); if ( sel.w > 0 && sel.h > 0 && w > 0 && h > 0 ) { sel.fw = w; sel.fh = h; this.addStep({ 'c': sel }, postid, nonce); } // Clear the selection fields after cropping. $( '#imgedit-sel-width-' + postid ).val( '' ); $( '#imgedit-sel-height-' + postid ).val( '' ); $( '#imgedit-start-x-' + postid ).val( '0' ); $( '#imgedit-start-y-' + postid ).val( '0' ); this.currentCropSelection = null; }, /** * Undoes an image edit action. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} postid The post ID. * @param {string} nonce The nonce. * * @return {void|false} Returns false if the undo button is disabled. */ undo : function (postid, nonce) { var t = this, button = $('#image-undo-' + postid), elem = $('#imgedit-undone-' + postid), pop = t.intval( elem.val() ) + 1; if ( button.hasClass('disabled') ) { return; } elem.val(pop); t.refreshEditor(postid, nonce, function() { var elem = $('#imgedit-history-' + postid), history = ( elem.val() !== '' ) ? JSON.parse( elem.val() ) : []; t.setDisabled($('#image-redo-' + postid), true); t.setDisabled(button, pop < history.length); // When undo gets disabled, move focus to the redo button to avoid a focus loss. if ( history.length === pop ) { $( '#image-redo-' + postid ).trigger( 'focus' ); } }); }, /** * Reverts a undo action. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} postid The post ID. * @param {string} nonce The nonce. * * @return {void} */ redo : function(postid, nonce) { var t = this, button = $('#image-redo-' + postid), elem = $('#imgedit-undone-' + postid), pop = t.intval( elem.val() ) - 1; if ( button.hasClass('disabled') ) { return; } elem.val(pop); t.refreshEditor(postid, nonce, function() { t.setDisabled($('#image-undo-' + postid), true); t.setDisabled(button, pop > 0); // When redo gets disabled, move focus to the undo button to avoid a focus loss. if ( 0 === pop ) { $( '#image-undo-' + postid ).trigger( 'focus' ); } }); }, /** * Sets the selection for the height and width in pixels. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} postid The post ID. * @param {jQuery} el The element containing the values. * * @return {void|boolean} Returns false when the x or y value is lower than 1, * void when the value is not numeric or when the operation * is successful. */ setNumSelection : function( postid, el ) { var sel, elX = $('#imgedit-sel-width-' + postid), elY = $('#imgedit-sel-height-' + postid), elX1 = $('#imgedit-start-x-' + postid), elY1 = $('#imgedit-start-y-' + postid), xS = this.intval( elX1.val() ), yS = this.intval( elY1.val() ), x = this.intval( elX.val() ), y = this.intval( elY.val() ), img = $('#image-preview-' + postid), imgh = img.height(), imgw = img.width(), sizer = this.hold.sizer, x1, y1, x2, y2, ias = this.iasapi; this.currentCropSelection = null; if ( false === this.validateNumeric( el ) ) { return; } if ( x < 1 ) { elX.val(''); return false; } if ( y < 1 ) { elY.val(''); return false; } if ( ( ( x && y ) || ( xS && yS ) ) && ( sel = ias.getSelection() ) ) { x2 = sel.x1 + Math.round( x * sizer ); y2 = sel.y1 + Math.round( y * sizer ); x1 = ( xS === sel.x1 ) ? sel.x1 : Math.round( xS * sizer ); y1 = ( yS === sel.y1 ) ? sel.y1 : Math.round( yS * sizer ); if ( x2 > imgw ) { x1 = 0; x2 = imgw; elX.val( Math.min( this.hold.w, Math.round( x2 / sizer ) ) ); } if ( y2 > imgh ) { y1 = 0; y2 = imgh; elY.val( Math.min( this.hold.h, Math.round( y2 / sizer ) ) ); } ias.setSelection( x1, y1, x2, y2 ); ias.update(); this.setCropSelection(postid, ias.getSelection()); this.currentCropSelection = ias.getSelection(); } }, /** * Rounds a number to a whole. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} num The number. * * @return {number} The number rounded to a whole number. */ round : function(num) { var s; num = Math.round(num); if ( this.hold.sizer > 0.6 ) { return num; } s = num.toString().slice(-1); if ( '1' === s ) { return num - 1; } else if ( '9' === s ) { return num + 1; } return num; }, /** * Sets a locked aspect ratio for the selection. * * @since 2.9.0 * * @memberof imageEdit * * @param {number} postid The post ID. * @param {number} n The ratio to set. * @param {jQuery} el The element containing the values. * * @return {void} */ setRatioSelection : function(postid, n, el) { var sel, r, x = this.intval( $('#imgedit-crop-width-' + postid).val() ), y = this.intval( $('#imgedit-crop-height-' + postid).val() ), h = $('#image-preview-' + postid).height(); if ( false === this.validateNumeric( el ) ) { this.iasapi.setOptions({ aspectRatio: null }); return; } if ( x && y ) { this.iasapi.setOptions({ aspectRatio: x + ':' + y }); if ( sel = this.iasapi.getSelection(true) ) { r = Math.ceil( sel.y1 + ( ( sel.x2 - sel.x1 ) / ( x / y ) ) ); if ( r > h ) { r = h; var errorMessage = __( 'Selected crop ratio exceeds the boundaries of the image. Try a different ratio.' ); $( '#imgedit-crop-' + postid ) .prepend( '' ); wp.a11y.speak( errorMessage, 'assertive' ); if ( n ) { $('#imgedit-crop-height-' + postid).val( '' ); } else { $('#imgedit-crop-width-' + postid).val( ''); } } else { var error = $( '#imgedit-crop-' + postid ).find( '.notice-error' ); if ( 'undefined' !== typeof( error ) ) { error.remove(); } } this.iasapi.setSelection( sel.x1, sel.y1, sel.x2, r ); this.iasapi.update(); } } }, /** * Validates if a value in a jQuery.HTMLElement is numeric. * * @since 4.6.0 * * @memberof imageEdit * * @param {jQuery} el The html element. * * @return {void|boolean} Returns false if the value is not numeric, * void when it is. */ validateNumeric: function( el ) { if ( false === this.intval( $( el ).val() ) ) { $( el ).val( '' ); return false; } } }; })(jQuery); customize-nav-menus.js000064400000333311147573140730011052 0ustar00/** * @output wp-admin/js/customize-nav-menus.js */ /* global menus, _wpCustomizeNavMenusSettings, wpNavMenu, console */ ( function( api, wp, $ ) { 'use strict'; /** * Set up wpNavMenu for drag and drop. */ wpNavMenu.originalInit = wpNavMenu.init; wpNavMenu.options.menuItemDepthPerLevel = 20; wpNavMenu.options.sortableItems = '> .customize-control-nav_menu_item'; wpNavMenu.options.targetTolerance = 10; wpNavMenu.init = function() { this.jQueryExtensions(); }; /** * @namespace wp.customize.Menus */ api.Menus = api.Menus || {}; // Link settings. api.Menus.data = { itemTypes: [], l10n: {}, settingTransport: 'refresh', phpIntMax: 0, defaultSettingValues: { nav_menu: {}, nav_menu_item: {} }, locationSlugMappedToName: {} }; if ( 'undefined' !== typeof _wpCustomizeNavMenusSettings ) { $.extend( api.Menus.data, _wpCustomizeNavMenusSettings ); } /** * Newly-created Nav Menus and Nav Menu Items have negative integer IDs which * serve as placeholders until Save & Publish happens. * * @alias wp.customize.Menus.generatePlaceholderAutoIncrementId * * @return {number} */ api.Menus.generatePlaceholderAutoIncrementId = function() { return -Math.ceil( api.Menus.data.phpIntMax * Math.random() ); }; /** * wp.customize.Menus.AvailableItemModel * * A single available menu item model. See PHP's WP_Customize_Nav_Menu_Item_Setting class. * * @class wp.customize.Menus.AvailableItemModel * @augments Backbone.Model */ api.Menus.AvailableItemModel = Backbone.Model.extend( $.extend( { id: null // This is only used by Backbone. }, api.Menus.data.defaultSettingValues.nav_menu_item ) ); /** * wp.customize.Menus.AvailableItemCollection * * Collection for available menu item models. * * @class wp.customize.Menus.AvailableItemCollection * @augments Backbone.Collection */ api.Menus.AvailableItemCollection = Backbone.Collection.extend(/** @lends wp.customize.Menus.AvailableItemCollection.prototype */{ model: api.Menus.AvailableItemModel, sort_key: 'order', comparator: function( item ) { return -item.get( this.sort_key ); }, sortByField: function( fieldName ) { this.sort_key = fieldName; this.sort(); } }); api.Menus.availableMenuItems = new api.Menus.AvailableItemCollection( api.Menus.data.availableMenuItems ); /** * Insert a new `auto-draft` post. * * @since 4.7.0 * @alias wp.customize.Menus.insertAutoDraftPost * * @param {Object} params - Parameters for the draft post to create. * @param {string} params.post_type - Post type to add. * @param {string} params.post_title - Post title to use. * @return {jQuery.promise} Promise resolved with the added post. */ api.Menus.insertAutoDraftPost = function insertAutoDraftPost( params ) { var request, deferred = $.Deferred(); request = wp.ajax.post( 'customize-nav-menus-insert-auto-draft', { 'customize-menus-nonce': api.settings.nonce['customize-menus'], 'wp_customize': 'on', 'customize_changeset_uuid': api.settings.changeset.uuid, 'params': params } ); request.done( function( response ) { if ( response.post_id ) { api( 'nav_menus_created_posts' ).set( api( 'nav_menus_created_posts' ).get().concat( [ response.post_id ] ) ); if ( 'page' === params.post_type ) { // Activate static front page controls as this could be the first page created. if ( api.section.has( 'static_front_page' ) ) { api.section( 'static_front_page' ).activate(); } // Add new page to dropdown-pages controls. api.control.each( function( control ) { var select; if ( 'dropdown-pages' === control.params.type ) { select = control.container.find( 'select[name^="_customize-dropdown-pages-"]' ); select.append( new Option( params.post_title, response.post_id ) ); } } ); } deferred.resolve( response ); } } ); request.fail( function( response ) { var error = response || ''; if ( 'undefined' !== typeof response.message ) { error = response.message; } console.error( error ); deferred.rejectWith( error ); } ); return deferred.promise(); }; api.Menus.AvailableMenuItemsPanelView = wp.Backbone.View.extend(/** @lends wp.customize.Menus.AvailableMenuItemsPanelView.prototype */{ el: '#available-menu-items', events: { 'input #menu-items-search': 'debounceSearch', 'focus .menu-item-tpl': 'focus', 'click .menu-item-tpl': '_submit', 'click #custom-menu-item-submit': '_submitLink', 'keypress #custom-menu-item-name': '_submitLink', 'click .new-content-item .add-content': '_submitNew', 'keypress .create-item-input': '_submitNew', 'keydown': 'keyboardAccessible' }, // Cache current selected menu item. selected: null, // Cache menu control that opened the panel. currentMenuControl: null, debounceSearch: null, $search: null, $clearResults: null, searchTerm: '', rendered: false, pages: {}, sectionContent: '', loading: false, addingNew: false, /** * wp.customize.Menus.AvailableMenuItemsPanelView * * View class for the available menu items panel. * * @constructs wp.customize.Menus.AvailableMenuItemsPanelView * @augments wp.Backbone.View */ initialize: function() { var self = this; if ( ! api.panel.has( 'nav_menus' ) ) { return; } this.$search = $( '#menu-items-search' ); this.$clearResults = this.$el.find( '.clear-results' ); this.sectionContent = this.$el.find( '.available-menu-items-list' ); this.debounceSearch = _.debounce( self.search, 500 ); _.bindAll( this, 'close' ); /* * If the available menu items panel is open and the customize controls * are interacted with (other than an item being deleted), then close * the available menu items panel. Also close on back button click. */ $( '#customize-controls, .customize-section-back' ).on( 'click keydown', function( e ) { var isDeleteBtn = $( e.target ).is( '.item-delete, .item-delete *' ), isAddNewBtn = $( e.target ).is( '.add-new-menu-item, .add-new-menu-item *' ); if ( $( 'body' ).hasClass( 'adding-menu-items' ) && ! isDeleteBtn && ! isAddNewBtn ) { self.close(); } } ); // Clear the search results and trigger an `input` event to fire a new search. this.$clearResults.on( 'click', function() { self.$search.val( '' ).trigger( 'focus' ).trigger( 'input' ); } ); this.$el.on( 'input', '#custom-menu-item-name.invalid, #custom-menu-item-url.invalid', function() { $( this ).removeClass( 'invalid' ); }); // Load available items if it looks like we'll need them. api.panel( 'nav_menus' ).container.on( 'expanded', function() { if ( ! self.rendered ) { self.initList(); self.rendered = true; } }); // Load more items. this.sectionContent.on( 'scroll', function() { var totalHeight = self.$el.find( '.accordion-section.open .available-menu-items-list' ).prop( 'scrollHeight' ), visibleHeight = self.$el.find( '.accordion-section.open' ).height(); if ( ! self.loading && $( this ).scrollTop() > 3 / 4 * totalHeight - visibleHeight ) { var type = $( this ).data( 'type' ), object = $( this ).data( 'object' ); if ( 'search' === type ) { if ( self.searchTerm ) { self.doSearch( self.pages.search ); } } else { self.loadItems( [ { type: type, object: object } ] ); } } }); // Close the panel if the URL in the preview changes. api.previewer.bind( 'url', this.close ); self.delegateEvents(); }, // Search input change handler. search: function( event ) { var $searchSection = $( '#available-menu-items-search' ), $otherSections = $( '#available-menu-items .accordion-section' ).not( $searchSection ); if ( ! event ) { return; } if ( this.searchTerm === event.target.value ) { return; } if ( '' !== event.target.value && ! $searchSection.hasClass( 'open' ) ) { $otherSections.fadeOut( 100 ); $searchSection.find( '.accordion-section-content' ).slideDown( 'fast' ); $searchSection.addClass( 'open' ); this.$clearResults.addClass( 'is-visible' ); } else if ( '' === event.target.value ) { $searchSection.removeClass( 'open' ); $otherSections.show(); this.$clearResults.removeClass( 'is-visible' ); } this.searchTerm = event.target.value; this.pages.search = 1; this.doSearch( 1 ); }, // Get search results. doSearch: function( page ) { var self = this, params, $section = $( '#available-menu-items-search' ), $content = $section.find( '.accordion-section-content' ), itemTemplate = wp.template( 'available-menu-item' ); if ( self.currentRequest ) { self.currentRequest.abort(); } if ( page < 0 ) { return; } else if ( page > 1 ) { $section.addClass( 'loading-more' ); $content.attr( 'aria-busy', 'true' ); wp.a11y.speak( api.Menus.data.l10n.itemsLoadingMore ); } else if ( '' === self.searchTerm ) { $content.html( '' ); wp.a11y.speak( '' ); return; } $section.addClass( 'loading' ); self.loading = true; params = api.previewer.query( { excludeCustomizedSaved: true } ); _.extend( params, { 'customize-menus-nonce': api.settings.nonce['customize-menus'], 'wp_customize': 'on', 'search': self.searchTerm, 'page': page } ); self.currentRequest = wp.ajax.post( 'search-available-menu-items-customizer', params ); self.currentRequest.done(function( data ) { var items; if ( 1 === page ) { // Clear previous results as it's a new search. $content.empty(); } $section.removeClass( 'loading loading-more' ); $content.attr( 'aria-busy', 'false' ); $section.addClass( 'open' ); self.loading = false; items = new api.Menus.AvailableItemCollection( data.items ); self.collection.add( items.models ); items.each( function( menuItem ) { $content.append( itemTemplate( menuItem.attributes ) ); } ); if ( 20 > items.length ) { self.pages.search = -1; // Up to 20 posts and 20 terms in results, if <20, no more results for either. } else { self.pages.search = self.pages.search + 1; } if ( items && page > 1 ) { wp.a11y.speak( api.Menus.data.l10n.itemsFoundMore.replace( '%d', items.length ) ); } else if ( items && page === 1 ) { wp.a11y.speak( api.Menus.data.l10n.itemsFound.replace( '%d', items.length ) ); } }); self.currentRequest.fail(function( data ) { // data.message may be undefined, for example when typing slow and the request is aborted. if ( data.message ) { $content.empty().append( $( '
  • ' ).text( data.message ) ); wp.a11y.speak( data.message ); } self.pages.search = -1; }); self.currentRequest.always(function() { $section.removeClass( 'loading loading-more' ); $content.attr( 'aria-busy', 'false' ); self.loading = false; self.currentRequest = null; }); }, // Render the individual items. initList: function() { var self = this; // Render the template for each item by type. _.each( api.Menus.data.itemTypes, function( itemType ) { self.pages[ itemType.type + ':' + itemType.object ] = 0; } ); self.loadItems( api.Menus.data.itemTypes ); }, /** * Load available nav menu items. * * @since 4.3.0 * @since 4.7.0 Changed function signature to take list of item types instead of single type/object. * @access private * * @param {Array.} itemTypes List of objects containing type and key. * @param {string} deprecated Formerly the object parameter. * @return {void} */ loadItems: function( itemTypes, deprecated ) { var self = this, _itemTypes, requestItemTypes = [], params, request, itemTemplate, availableMenuItemContainers = {}; itemTemplate = wp.template( 'available-menu-item' ); if ( _.isString( itemTypes ) && _.isString( deprecated ) ) { _itemTypes = [ { type: itemTypes, object: deprecated } ]; } else { _itemTypes = itemTypes; } _.each( _itemTypes, function( itemType ) { var container, name = itemType.type + ':' + itemType.object; if ( -1 === self.pages[ name ] ) { return; // Skip types for which there are no more results. } container = $( '#available-menu-items-' + itemType.type + '-' + itemType.object ); container.find( '.accordion-section-title' ).addClass( 'loading' ); availableMenuItemContainers[ name ] = container; requestItemTypes.push( { object: itemType.object, type: itemType.type, page: self.pages[ name ] } ); } ); if ( 0 === requestItemTypes.length ) { return; } self.loading = true; params = api.previewer.query( { excludeCustomizedSaved: true } ); _.extend( params, { 'customize-menus-nonce': api.settings.nonce['customize-menus'], 'wp_customize': 'on', 'item_types': requestItemTypes } ); request = wp.ajax.post( 'load-available-menu-items-customizer', params ); request.done(function( data ) { var typeInner; _.each( data.items, function( typeItems, name ) { if ( 0 === typeItems.length ) { if ( 0 === self.pages[ name ] ) { availableMenuItemContainers[ name ].find( '.accordion-section-title' ) .addClass( 'cannot-expand' ) .removeClass( 'loading' ) .find( '.accordion-section-title > button' ) .prop( 'tabIndex', -1 ); } self.pages[ name ] = -1; return; } else if ( ( 'post_type:page' === name ) && ( ! availableMenuItemContainers[ name ].hasClass( 'open' ) ) ) { availableMenuItemContainers[ name ].find( '.accordion-section-title > button' ).trigger( 'click' ); } typeItems = new api.Menus.AvailableItemCollection( typeItems ); // @todo Why is this collection created and then thrown away? self.collection.add( typeItems.models ); typeInner = availableMenuItemContainers[ name ].find( '.available-menu-items-list' ); typeItems.each( function( menuItem ) { typeInner.append( itemTemplate( menuItem.attributes ) ); } ); self.pages[ name ] += 1; }); }); request.fail(function( data ) { if ( typeof console !== 'undefined' && console.error ) { console.error( data ); } }); request.always(function() { _.each( availableMenuItemContainers, function( container ) { container.find( '.accordion-section-title' ).removeClass( 'loading' ); } ); self.loading = false; }); }, // Adjust the height of each section of items to fit the screen. itemSectionHeight: function() { var sections, lists, totalHeight, accordionHeight, diff; totalHeight = window.innerHeight; sections = this.$el.find( '.accordion-section:not( #available-menu-items-search ) .accordion-section-content' ); lists = this.$el.find( '.accordion-section:not( #available-menu-items-search ) .available-menu-items-list:not(":only-child")' ); accordionHeight = 46 * ( 1 + sections.length ) + 14; // Magic numbers. diff = totalHeight - accordionHeight; if ( 120 < diff && 290 > diff ) { sections.css( 'max-height', diff ); lists.css( 'max-height', ( diff - 60 ) ); } }, // Highlights a menu item. select: function( menuitemTpl ) { this.selected = $( menuitemTpl ); this.selected.siblings( '.menu-item-tpl' ).removeClass( 'selected' ); this.selected.addClass( 'selected' ); }, // Highlights a menu item on focus. focus: function( event ) { this.select( $( event.currentTarget ) ); }, // Submit handler for keypress and click on menu item. _submit: function( event ) { // Only proceed with keypress if it is Enter or Spacebar. if ( 'keypress' === event.type && ( 13 !== event.which && 32 !== event.which ) ) { return; } this.submit( $( event.currentTarget ) ); }, // Adds a selected menu item to the menu. submit: function( menuitemTpl ) { var menuitemId, menu_item; if ( ! menuitemTpl ) { menuitemTpl = this.selected; } if ( ! menuitemTpl || ! this.currentMenuControl ) { return; } this.select( menuitemTpl ); menuitemId = $( this.selected ).data( 'menu-item-id' ); menu_item = this.collection.findWhere( { id: menuitemId } ); if ( ! menu_item ) { return; } this.currentMenuControl.addItemToMenu( menu_item.attributes ); $( menuitemTpl ).find( '.menu-item-handle' ).addClass( 'item-added' ); }, // Submit handler for keypress and click on custom menu item. _submitLink: function( event ) { // Only proceed with keypress if it is Enter. if ( 'keypress' === event.type && 13 !== event.which ) { return; } this.submitLink(); }, // Adds the custom menu item to the menu. submitLink: function() { var menuItem, itemName = $( '#custom-menu-item-name' ), itemUrl = $( '#custom-menu-item-url' ), url = itemUrl.val().trim(), urlRegex; if ( ! this.currentMenuControl ) { return; } /* * Allow URLs including: * - http://example.com/ * - //example.com * - /directory/ * - ?query-param * - #target * - mailto:foo@example.com * * Any further validation will be handled on the server when the setting is attempted to be saved, * so this pattern does not need to be complete. */ urlRegex = /^((\w+:)?\/\/\w.*|\w+:(?!\/\/$)|\/|\?|#)/; if ( '' === itemName.val() ) { itemName.addClass( 'invalid' ); return; } else if ( ! urlRegex.test( url ) ) { itemUrl.addClass( 'invalid' ); return; } menuItem = { 'title': itemName.val(), 'url': url, 'type': 'custom', 'type_label': api.Menus.data.l10n.custom_label, 'object': 'custom' }; this.currentMenuControl.addItemToMenu( menuItem ); // Reset the custom link form. itemUrl.val( '' ).attr( 'placeholder', 'https://' ); itemName.val( '' ); }, /** * Submit handler for keypress (enter) on field and click on button. * * @since 4.7.0 * @private * * @param {jQuery.Event} event Event. * @return {void} */ _submitNew: function( event ) { var container; // Only proceed with keypress if it is Enter. if ( 'keypress' === event.type && 13 !== event.which ) { return; } if ( this.addingNew ) { return; } container = $( event.target ).closest( '.accordion-section' ); this.submitNew( container ); }, /** * Creates a new object and adds an associated menu item to the menu. * * @since 4.7.0 * @private * * @param {jQuery} container * @return {void} */ submitNew: function( container ) { var panel = this, itemName = container.find( '.create-item-input' ), title = itemName.val(), dataContainer = container.find( '.available-menu-items-list' ), itemType = dataContainer.data( 'type' ), itemObject = dataContainer.data( 'object' ), itemTypeLabel = dataContainer.data( 'type_label' ), promise; if ( ! this.currentMenuControl ) { return; } // Only posts are supported currently. if ( 'post_type' !== itemType ) { return; } if ( '' === itemName.val().trim() ) { itemName.addClass( 'invalid' ); itemName.focus(); return; } else { itemName.removeClass( 'invalid' ); container.find( '.accordion-section-title' ).addClass( 'loading' ); } panel.addingNew = true; itemName.attr( 'disabled', 'disabled' ); promise = api.Menus.insertAutoDraftPost( { post_title: title, post_type: itemObject } ); promise.done( function( data ) { var availableItem, $content, itemElement; availableItem = new api.Menus.AvailableItemModel( { 'id': 'post-' + data.post_id, // Used for available menu item Backbone models. 'title': itemName.val(), 'type': itemType, 'type_label': itemTypeLabel, 'object': itemObject, 'object_id': data.post_id, 'url': data.url } ); // Add new item to menu. panel.currentMenuControl.addItemToMenu( availableItem.attributes ); // Add the new item to the list of available items. api.Menus.availableMenuItemsPanel.collection.add( availableItem ); $content = container.find( '.available-menu-items-list' ); itemElement = $( wp.template( 'available-menu-item' )( availableItem.attributes ) ); itemElement.find( '.menu-item-handle:first' ).addClass( 'item-added' ); $content.prepend( itemElement ); $content.scrollTop(); // Reset the create content form. itemName.val( '' ).removeAttr( 'disabled' ); panel.addingNew = false; container.find( '.accordion-section-title' ).removeClass( 'loading' ); } ); }, // Opens the panel. open: function( menuControl ) { var panel = this, close; this.currentMenuControl = menuControl; this.itemSectionHeight(); if ( api.section.has( 'publish_settings' ) ) { api.section( 'publish_settings' ).collapse(); } $( 'body' ).addClass( 'adding-menu-items' ); close = function() { panel.close(); $( this ).off( 'click', close ); }; $( '#customize-preview' ).on( 'click', close ); // Collapse all controls. _( this.currentMenuControl.getMenuItemControls() ).each( function( control ) { control.collapseForm(); } ); this.$el.find( '.selected' ).removeClass( 'selected' ); this.$search.trigger( 'focus' ); }, // Closes the panel. close: function( options ) { options = options || {}; if ( options.returnFocus && this.currentMenuControl ) { this.currentMenuControl.container.find( '.add-new-menu-item' ).focus(); } this.currentMenuControl = null; this.selected = null; $( 'body' ).removeClass( 'adding-menu-items' ); $( '#available-menu-items .menu-item-handle.item-added' ).removeClass( 'item-added' ); this.$search.val( '' ).trigger( 'input' ); }, // Add a few keyboard enhancements to the panel. keyboardAccessible: function( event ) { var isEnter = ( 13 === event.which ), isEsc = ( 27 === event.which ), isBackTab = ( 9 === event.which && event.shiftKey ), isSearchFocused = $( event.target ).is( this.$search ); // If enter pressed but nothing entered, don't do anything. if ( isEnter && ! this.$search.val() ) { return; } if ( isSearchFocused && isBackTab ) { this.currentMenuControl.container.find( '.add-new-menu-item' ).focus(); event.preventDefault(); // Avoid additional back-tab. } else if ( isEsc ) { this.close( { returnFocus: true } ); } } }); /** * wp.customize.Menus.MenusPanel * * Customizer panel for menus. This is used only for screen options management. * Note that 'menus' must match the WP_Customize_Menu_Panel::$type. * * @class wp.customize.Menus.MenusPanel * @augments wp.customize.Panel */ api.Menus.MenusPanel = api.Panel.extend(/** @lends wp.customize.Menus.MenusPanel.prototype */{ attachEvents: function() { api.Panel.prototype.attachEvents.call( this ); var panel = this, panelMeta = panel.container.find( '.panel-meta' ), help = panelMeta.find( '.customize-help-toggle' ), content = panelMeta.find( '.customize-panel-description' ), options = $( '#screen-options-wrap' ), button = panelMeta.find( '.customize-screen-options-toggle' ); button.on( 'click keydown', function( event ) { if ( api.utils.isKeydownButNotEnterEvent( event ) ) { return; } event.preventDefault(); // Hide description. if ( content.not( ':hidden' ) ) { content.slideUp( 'fast' ); help.attr( 'aria-expanded', 'false' ); } if ( 'true' === button.attr( 'aria-expanded' ) ) { button.attr( 'aria-expanded', 'false' ); panelMeta.removeClass( 'open' ); panelMeta.removeClass( 'active-menu-screen-options' ); options.slideUp( 'fast' ); } else { button.attr( 'aria-expanded', 'true' ); panelMeta.addClass( 'open' ); panelMeta.addClass( 'active-menu-screen-options' ); options.slideDown( 'fast' ); } return false; } ); // Help toggle. help.on( 'click keydown', function( event ) { if ( api.utils.isKeydownButNotEnterEvent( event ) ) { return; } event.preventDefault(); if ( 'true' === button.attr( 'aria-expanded' ) ) { button.attr( 'aria-expanded', 'false' ); help.attr( 'aria-expanded', 'true' ); panelMeta.addClass( 'open' ); panelMeta.removeClass( 'active-menu-screen-options' ); options.slideUp( 'fast' ); content.slideDown( 'fast' ); } } ); }, /** * Update field visibility when clicking on the field toggles. */ ready: function() { var panel = this; panel.container.find( '.hide-column-tog' ).on( 'click', function() { panel.saveManageColumnsState(); }); // Inject additional heading into the menu locations section's head container. api.section( 'menu_locations', function( section ) { section.headContainer.prepend( wp.template( 'nav-menu-locations-header' )( api.Menus.data ) ); } ); }, /** * Save hidden column states. * * @since 4.3.0 * @private * * @return {void} */ saveManageColumnsState: _.debounce( function() { var panel = this; if ( panel._updateHiddenColumnsRequest ) { panel._updateHiddenColumnsRequest.abort(); } panel._updateHiddenColumnsRequest = wp.ajax.post( 'hidden-columns', { hidden: panel.hidden(), screenoptionnonce: $( '#screenoptionnonce' ).val(), page: 'nav-menus' } ); panel._updateHiddenColumnsRequest.always( function() { panel._updateHiddenColumnsRequest = null; } ); }, 2000 ), /** * @deprecated Since 4.7.0 now that the nav_menu sections are responsible for toggling the classes on their own containers. */ checked: function() {}, /** * @deprecated Since 4.7.0 now that the nav_menu sections are responsible for toggling the classes on their own containers. */ unchecked: function() {}, /** * Get hidden fields. * * @since 4.3.0 * @private * * @return {Array} Fields (columns) that are hidden. */ hidden: function() { return $( '.hide-column-tog' ).not( ':checked' ).map( function() { var id = this.id; return id.substring( 0, id.length - 5 ); }).get().join( ',' ); } } ); /** * wp.customize.Menus.MenuSection * * Customizer section for menus. This is used only for lazy-loading child controls. * Note that 'nav_menu' must match the WP_Customize_Menu_Section::$type. * * @class wp.customize.Menus.MenuSection * @augments wp.customize.Section */ api.Menus.MenuSection = api.Section.extend(/** @lends wp.customize.Menus.MenuSection.prototype */{ /** * Initialize. * * @since 4.3.0 * * @param {string} id * @param {Object} options */ initialize: function( id, options ) { var section = this; api.Section.prototype.initialize.call( section, id, options ); section.deferred.initSortables = $.Deferred(); }, /** * Ready. */ ready: function() { var section = this, fieldActiveToggles, handleFieldActiveToggle; if ( 'undefined' === typeof section.params.menu_id ) { throw new Error( 'params.menu_id was not defined' ); } /* * Since newly created sections won't be registered in PHP, we need to prevent the * preview's sending of the activeSections to result in this control * being deactivated when the preview refreshes. So we can hook onto * the setting that has the same ID and its presence can dictate * whether the section is active. */ section.active.validate = function() { if ( ! api.has( section.id ) ) { return false; } return !! api( section.id ).get(); }; section.populateControls(); section.navMenuLocationSettings = {}; section.assignedLocations = new api.Value( [] ); api.each(function( setting, id ) { var matches = id.match( /^nav_menu_locations\[(.+?)]/ ); if ( matches ) { section.navMenuLocationSettings[ matches[1] ] = setting; setting.bind( function() { section.refreshAssignedLocations(); }); } }); section.assignedLocations.bind(function( to ) { section.updateAssignedLocationsInSectionTitle( to ); }); section.refreshAssignedLocations(); api.bind( 'pane-contents-reflowed', function() { // Skip menus that have been removed. if ( ! section.contentContainer.parent().length ) { return; } section.container.find( '.menu-item .menu-item-reorder-nav button' ).attr({ 'tabindex': '0', 'aria-hidden': 'false' }); section.container.find( '.menu-item.move-up-disabled .menus-move-up' ).attr({ 'tabindex': '-1', 'aria-hidden': 'true' }); section.container.find( '.menu-item.move-down-disabled .menus-move-down' ).attr({ 'tabindex': '-1', 'aria-hidden': 'true' }); section.container.find( '.menu-item.move-left-disabled .menus-move-left' ).attr({ 'tabindex': '-1', 'aria-hidden': 'true' }); section.container.find( '.menu-item.move-right-disabled .menus-move-right' ).attr({ 'tabindex': '-1', 'aria-hidden': 'true' }); } ); /** * Update the active field class for the content container for a given checkbox toggle. * * @this {jQuery} * @return {void} */ handleFieldActiveToggle = function() { var className = 'field-' + $( this ).val() + '-active'; section.contentContainer.toggleClass( className, $( this ).prop( 'checked' ) ); }; fieldActiveToggles = api.panel( 'nav_menus' ).contentContainer.find( '.metabox-prefs:first' ).find( '.hide-column-tog' ); fieldActiveToggles.each( handleFieldActiveToggle ); fieldActiveToggles.on( 'click', handleFieldActiveToggle ); }, populateControls: function() { var section = this, menuNameControlId, menuLocationsControlId, menuAutoAddControlId, menuDeleteControlId, menuControl, menuNameControl, menuLocationsControl, menuAutoAddControl, menuDeleteControl; // Add the control for managing the menu name. menuNameControlId = section.id + '[name]'; menuNameControl = api.control( menuNameControlId ); if ( ! menuNameControl ) { menuNameControl = new api.controlConstructor.nav_menu_name( menuNameControlId, { type: 'nav_menu_name', label: api.Menus.data.l10n.menuNameLabel, section: section.id, priority: 0, settings: { 'default': section.id } } ); api.control.add( menuNameControl ); menuNameControl.active.set( true ); } // Add the menu control. menuControl = api.control( section.id ); if ( ! menuControl ) { menuControl = new api.controlConstructor.nav_menu( section.id, { type: 'nav_menu', section: section.id, priority: 998, settings: { 'default': section.id }, menu_id: section.params.menu_id } ); api.control.add( menuControl ); menuControl.active.set( true ); } // Add the menu locations control. menuLocationsControlId = section.id + '[locations]'; menuLocationsControl = api.control( menuLocationsControlId ); if ( ! menuLocationsControl ) { menuLocationsControl = new api.controlConstructor.nav_menu_locations( menuLocationsControlId, { section: section.id, priority: 999, settings: { 'default': section.id }, menu_id: section.params.menu_id } ); api.control.add( menuLocationsControl.id, menuLocationsControl ); menuControl.active.set( true ); } // Add the control for managing the menu auto_add. menuAutoAddControlId = section.id + '[auto_add]'; menuAutoAddControl = api.control( menuAutoAddControlId ); if ( ! menuAutoAddControl ) { menuAutoAddControl = new api.controlConstructor.nav_menu_auto_add( menuAutoAddControlId, { type: 'nav_menu_auto_add', label: '', section: section.id, priority: 1000, settings: { 'default': section.id } } ); api.control.add( menuAutoAddControl ); menuAutoAddControl.active.set( true ); } // Add the control for deleting the menu. menuDeleteControlId = section.id + '[delete]'; menuDeleteControl = api.control( menuDeleteControlId ); if ( ! menuDeleteControl ) { menuDeleteControl = new api.Control( menuDeleteControlId, { section: section.id, priority: 1001, templateId: 'nav-menu-delete-button' } ); api.control.add( menuDeleteControl.id, menuDeleteControl ); menuDeleteControl.active.set( true ); menuDeleteControl.deferred.embedded.done( function () { menuDeleteControl.container.find( 'button' ).on( 'click', function() { var menuId = section.params.menu_id; var menuControl = api.Menus.getMenuControl( menuId ); menuControl.setting.set( false ); }); } ); } }, /** * */ refreshAssignedLocations: function() { var section = this, menuTermId = section.params.menu_id, currentAssignedLocations = []; _.each( section.navMenuLocationSettings, function( setting, themeLocation ) { if ( setting() === menuTermId ) { currentAssignedLocations.push( themeLocation ); } }); section.assignedLocations.set( currentAssignedLocations ); }, /** * @param {Array} themeLocationSlugs Theme location slugs. */ updateAssignedLocationsInSectionTitle: function( themeLocationSlugs ) { var section = this, $title; $title = section.container.find( '.accordion-section-title button:first' ); $title.find( '.menu-in-location' ).remove(); _.each( themeLocationSlugs, function( themeLocationSlug ) { var $label, locationName; $label = $( '' ); locationName = api.Menus.data.locationSlugMappedToName[ themeLocationSlug ]; $label.text( api.Menus.data.l10n.menuLocation.replace( '%s', locationName ) ); $title.append( $label ); }); section.container.toggleClass( 'assigned-to-menu-location', 0 !== themeLocationSlugs.length ); }, onChangeExpanded: function( expanded, args ) { var section = this, completeCallback; if ( expanded ) { wpNavMenu.menuList = section.contentContainer; wpNavMenu.targetList = wpNavMenu.menuList; // Add attributes needed by wpNavMenu. $( '#menu-to-edit' ).removeAttr( 'id' ); wpNavMenu.menuList.attr( 'id', 'menu-to-edit' ).addClass( 'menu' ); api.Menus.MenuItemControl.prototype.initAccessibility(); _.each( api.section( section.id ).controls(), function( control ) { if ( 'nav_menu_item' === control.params.type ) { control.actuallyEmbed(); } } ); // Make sure Sortables is initialized after the section has been expanded to prevent `offset` issues. if ( args.completeCallback ) { completeCallback = args.completeCallback; } args.completeCallback = function() { if ( 'resolved' !== section.deferred.initSortables.state() ) { wpNavMenu.initSortables(); // Depends on menu-to-edit ID being set above. section.deferred.initSortables.resolve( wpNavMenu.menuList ); // Now MenuControl can extend the sortable. // @todo Note that wp.customize.reflowPaneContents() is debounced, // so this immediate change will show a slight flicker while priorities get updated. api.control( 'nav_menu[' + String( section.params.menu_id ) + ']' ).reflowMenuItems(); } if ( _.isFunction( completeCallback ) ) { completeCallback(); } }; } api.Section.prototype.onChangeExpanded.call( section, expanded, args ); }, /** * Highlight how a user may create new menu items. * * This method reminds the user to create new menu items and how. * It's exposed this way because this class knows best which UI needs * highlighted but those expanding this section know more about why and * when the affordance should be highlighted. * * @since 4.9.0 * * @return {void} */ highlightNewItemButton: function() { api.utils.highlightButton( this.contentContainer.find( '.add-new-menu-item' ), { delay: 2000 } ); } }); /** * Create a nav menu setting and section. * * @since 4.9.0 * * @param {string} [name=''] Nav menu name. * @return {wp.customize.Menus.MenuSection} Added nav menu. */ api.Menus.createNavMenu = function createNavMenu( name ) { var customizeId, placeholderId, setting; placeholderId = api.Menus.generatePlaceholderAutoIncrementId(); customizeId = 'nav_menu[' + String( placeholderId ) + ']'; // Register the menu control setting. setting = api.create( customizeId, customizeId, {}, { type: 'nav_menu', transport: api.Menus.data.settingTransport, previewer: api.previewer } ); setting.set( $.extend( {}, api.Menus.data.defaultSettingValues.nav_menu, { name: name || '' } ) ); /* * Add the menu section (and its controls). * Note that this will automatically create the required controls * inside via the Section's ready method. */ return api.section.add( new api.Menus.MenuSection( customizeId, { panel: 'nav_menus', title: displayNavMenuName( name ), customizeAction: api.Menus.data.l10n.customizingMenus, priority: 10, menu_id: placeholderId } ) ); }; /** * wp.customize.Menus.NewMenuSection * * Customizer section for new menus. * * @class wp.customize.Menus.NewMenuSection * @augments wp.customize.Section */ api.Menus.NewMenuSection = api.Section.extend(/** @lends wp.customize.Menus.NewMenuSection.prototype */{ /** * Add behaviors for the accordion section. * * @since 4.3.0 */ attachEvents: function() { var section = this, container = section.container, contentContainer = section.contentContainer, navMenuSettingPattern = /^nav_menu\[/; section.headContainer.find( '.accordion-section-title' ).replaceWith( wp.template( 'nav-menu-create-menu-section-title' ) ); /* * We have to manually handle section expanded because we do not * apply the `accordion-section-title` class to this button-driven section. */ container.on( 'click', '.customize-add-menu-button', function() { section.expand(); }); contentContainer.on( 'keydown', '.menu-name-field', function( event ) { if ( 13 === event.which ) { // Enter. section.submit(); } } ); contentContainer.on( 'click', '#customize-new-menu-submit', function( event ) { section.submit(); event.stopPropagation(); event.preventDefault(); } ); /** * Get number of non-deleted nav menus. * * @since 4.9.0 * @return {number} Count. */ function getNavMenuCount() { var count = 0; api.each( function( setting ) { if ( navMenuSettingPattern.test( setting.id ) && false !== setting.get() ) { count += 1; } } ); return count; } /** * Update visibility of notice to prompt users to create menus. * * @since 4.9.0 * @return {void} */ function updateNoticeVisibility() { container.find( '.add-new-menu-notice' ).prop( 'hidden', getNavMenuCount() > 0 ); } /** * Handle setting addition. * * @since 4.9.0 * @param {wp.customize.Setting} setting - Added setting. * @return {void} */ function addChangeEventListener( setting ) { if ( navMenuSettingPattern.test( setting.id ) ) { setting.bind( updateNoticeVisibility ); updateNoticeVisibility(); } } /** * Handle setting removal. * * @since 4.9.0 * @param {wp.customize.Setting} setting - Removed setting. * @return {void} */ function removeChangeEventListener( setting ) { if ( navMenuSettingPattern.test( setting.id ) ) { setting.unbind( updateNoticeVisibility ); updateNoticeVisibility(); } } api.each( addChangeEventListener ); api.bind( 'add', addChangeEventListener ); api.bind( 'removed', removeChangeEventListener ); updateNoticeVisibility(); api.Section.prototype.attachEvents.apply( section, arguments ); }, /** * Set up the control. * * @since 4.9.0 */ ready: function() { this.populateControls(); }, /** * Create the controls for this section. * * @since 4.9.0 */ populateControls: function() { var section = this, menuNameControlId, menuLocationsControlId, newMenuSubmitControlId, menuNameControl, menuLocationsControl, newMenuSubmitControl; menuNameControlId = section.id + '[name]'; menuNameControl = api.control( menuNameControlId ); if ( ! menuNameControl ) { menuNameControl = new api.controlConstructor.nav_menu_name( menuNameControlId, { label: api.Menus.data.l10n.menuNameLabel, description: api.Menus.data.l10n.newMenuNameDescription, section: section.id, priority: 0 } ); api.control.add( menuNameControl.id, menuNameControl ); menuNameControl.active.set( true ); } menuLocationsControlId = section.id + '[locations]'; menuLocationsControl = api.control( menuLocationsControlId ); if ( ! menuLocationsControl ) { menuLocationsControl = new api.controlConstructor.nav_menu_locations( menuLocationsControlId, { section: section.id, priority: 1, menu_id: '', isCreating: true } ); api.control.add( menuLocationsControlId, menuLocationsControl ); menuLocationsControl.active.set( true ); } newMenuSubmitControlId = section.id + '[submit]'; newMenuSubmitControl = api.control( newMenuSubmitControlId ); if ( !newMenuSubmitControl ) { newMenuSubmitControl = new api.Control( newMenuSubmitControlId, { section: section.id, priority: 1, templateId: 'nav-menu-submit-new-button' } ); api.control.add( newMenuSubmitControlId, newMenuSubmitControl ); newMenuSubmitControl.active.set( true ); } }, /** * Create the new menu with name and location supplied by the user. * * @since 4.9.0 */ submit: function() { var section = this, contentContainer = section.contentContainer, nameInput = contentContainer.find( '.menu-name-field' ).first(), name = nameInput.val(), menuSection; if ( ! name ) { nameInput.addClass( 'invalid' ); nameInput.focus(); return; } menuSection = api.Menus.createNavMenu( name ); // Clear name field. nameInput.val( '' ); nameInput.removeClass( 'invalid' ); contentContainer.find( '.assigned-menu-location input[type=checkbox]' ).each( function() { var checkbox = $( this ), navMenuLocationSetting; if ( checkbox.prop( 'checked' ) ) { navMenuLocationSetting = api( 'nav_menu_locations[' + checkbox.data( 'location-id' ) + ']' ); navMenuLocationSetting.set( menuSection.params.menu_id ); // Reset state for next new menu. checkbox.prop( 'checked', false ); } } ); wp.a11y.speak( api.Menus.data.l10n.menuAdded ); // Focus on the new menu section. menuSection.focus( { completeCallback: function() { menuSection.highlightNewItemButton(); } } ); }, /** * Select a default location. * * This method selects a single location by default so we can support * creating a menu for a specific menu location. * * @since 4.9.0 * * @param {string|null} locationId - The ID of the location to select. `null` clears all selections. * @return {void} */ selectDefaultLocation: function( locationId ) { var locationControl = api.control( this.id + '[locations]' ), locationSelections = {}; if ( locationId !== null ) { locationSelections[ locationId ] = true; } locationControl.setSelections( locationSelections ); } }); /** * wp.customize.Menus.MenuLocationControl * * Customizer control for menu locations (rendered as a ').children("input").on("keydown",function(t){var e=t.which;13===e&&(t.preventDefault(),p.children(".save").trigger("click")),27===e&&p.children(".cancel").trigger("click")}).on("keyup",function(){s.val(this.value)}).trigger("focus")}),window.wptitlehint=function(t){var e=h("#"+(t=t||"title")),i=h("#"+t+"-prompt-text");""===e.val()&&i.removeClass("screen-reader-text"),e.on("input",function(){""===this.value?i.removeClass("screen-reader-text"):i.addClass("screen-reader-text")})},wptitlehint(),t=h("#post-status-info"),c=h("#postdivrich"),!u.length||"ontouchstart"in window?h("#content-resize-handle").hide():t.on("mousedown.wp-editor-resize",function(t){(o="undefined"!=typeof tinymce?tinymce.get("content"):o)&&!o.isHidden()?(r=!0,l=h("#content_ifr").height()-t.pageY):(r=!1,l=u.height()-t.pageY,u.trigger("blur")),v.on("mousemove.wp-editor-resize",D).on("mouseup.wp-editor-resize mouseleave.wp-editor-resize",j),t.preventDefault()}).on("mouseup.wp-editor-resize",j),"undefined"!=typeof tinymce&&(h("#post-formats-select input.post-format").on("change.set-editor-class",function(){var t,e,i=this.id;i&&h(this).prop("checked")&&(t=tinymce.get("content"))&&((e=t.getBody()).className=e.className.replace(/\bpost-format-[^ ]+/,""),t.dom.addClass(e,"post-format-0"==i?"post-format-standard":i),h(document).trigger("editor-classchange"))}),h("#page_template").on("change.set-editor-class",function(){var t,e,i=h(this).val()||"";(i=i.substr(i.lastIndexOf("/")+1,i.length).replace(/\.php$/,"").replace(/\./g,"-"))&&(t=tinymce.get("content"))&&((e=t.getBody()).className=e.className.replace(/\bpage-template-[^ ]+/,""),t.dom.addClass(e,"page-template-"+i),h(document).trigger("editor-classchange"))})),u.on("keydown.wp-autosave",function(t){83!==t.which||t.shiftKey||t.altKey||_&&(!t.metaKey||t.ctrlKey)||!_&&!t.ctrlKey||(wp.autosave&&wp.autosave.server.triggerSave(),t.preventDefault())}),"auto-draft"===h("#original_post_status").val()&&window.history.replaceState&&h("#publish").on("click",function(){p=(p=window.location.href)+(-1!==p.indexOf("?")?"&":"?")+"wp-post-new-reload=true",window.history.replaceState(null,null,p)}),y.on("success",function(t){var e=h(t.trigger),i=h(".success",e.closest(".copy-to-clipboard-container"));t.clearSelection(),clearTimeout(s),i.removeClass("hidden"),s=setTimeout(function(){i.addClass("hidden")},3e3),wp.a11y.speak(x("The file URL has been copied to your clipboard"))})}),function(t,o){t(function(){var i,e=t("#content"),a=t("#wp-word-count").find(".word-count"),n=0;function s(){var t=!i||i.isHidden()?e.val():i.getContent({format:"raw"}),t=o.count(t);t!==n&&a.text(t),n=t}t(document).on("tinymce-editor-init",function(t,e){"content"===e.id&&(i=e).on("nodechange keyup",_.debounce(s,1e3))}),e.on("input keyup",_.debounce(s,1e3)),s()})}(jQuery,new wp.utils.WordCounter);postbox.min.js000064400000015061147573140730007400 0ustar00/*! This file is auto-generated */ !function(l){var a=l(document),r=wp.i18n.__;window.postboxes={handle_click:function(){var e,o=l(this),s=o.closest(".postbox"),t=s.attr("id");"dashboard_browser_nag"!==t&&(s.toggleClass("closed"),e=!s.hasClass("closed"),(o.hasClass("handlediv")?o:o.closest(".postbox").find("button.handlediv")).attr("aria-expanded",e),"press-this"!==postboxes.page&&postboxes.save_state(postboxes.page),t&&(s.hasClass("closed")||"function"!=typeof postboxes.pbshow?s.hasClass("closed")&&"function"==typeof postboxes.pbhide&&postboxes.pbhide(t):postboxes.pbshow(t)),a.trigger("postbox-toggled",s))},handleOrder:function(){var e=l(this),o=e.closest(".postbox"),s=o.attr("id"),t=o.closest(".meta-box-sortables").find(".postbox:visible"),a=t.length,t=t.index(o);if("dashboard_browser_nag"!==s)if("true"===e.attr("aria-disabled"))s=e.hasClass("handle-order-higher")?r("The box is on the first position"):r("The box is on the last position"),wp.a11y.speak(s);else{if(e.hasClass("handle-order-higher")){if(0===t)return void postboxes.handleOrderBetweenSortables("previous",e,o);o.prevAll(".postbox:visible").eq(0).before(o),e.trigger("focus"),postboxes.updateOrderButtonsProperties(),postboxes.save_order(postboxes.page)}e.hasClass("handle-order-lower")&&(t+1===a?postboxes.handleOrderBetweenSortables("next",e,o):(o.nextAll(".postbox:visible").eq(0).after(o),e.trigger("focus"),postboxes.updateOrderButtonsProperties(),postboxes.save_order(postboxes.page)))}},handleOrderBetweenSortables:function(e,o,s){var t=o.closest(".meta-box-sortables").attr("id"),a=[];l(".meta-box-sortables:visible").each(function(){a.push(l(this).attr("id"))}),1!==a.length&&(t=l.inArray(t,a),s=s.detach(),"previous"===e&&l(s).appendTo("#"+a[t-1]),"next"===e&&l(s).prependTo("#"+a[t+1]),postboxes._mark_area(),o.focus(),postboxes.updateOrderButtonsProperties(),postboxes.save_order(postboxes.page))},updateOrderButtonsProperties:function(){var e=l(".meta-box-sortables:visible:first").attr("id"),o=l(".meta-box-sortables:visible:last").attr("id"),s=l(".postbox:visible:first"),t=l(".postbox:visible:last"),a=s.attr("id"),r=t.attr("id"),i=s.closest(".meta-box-sortables").attr("id"),t=t.closest(".meta-box-sortables").attr("id"),n=l(".handle-order-higher"),d=l(".handle-order-lower");n.attr("aria-disabled","false").removeClass("hidden"),d.attr("aria-disabled","false").removeClass("hidden"),e===o&&a===r&&(n.addClass("hidden"),d.addClass("hidden")),e===i&&l(s).find(".handle-order-higher").attr("aria-disabled","true"),o===t&&l(".postbox:visible .handle-order-lower").last().attr("aria-disabled","true")},add_postbox_toggles:function(t,e){var o=l(".postbox .hndle, .postbox .handlediv"),s=l(".postbox .handle-order-higher, .postbox .handle-order-lower");this.page=t,this.init(t,e),o.on("click.postboxes",this.handle_click),s.on("click.postboxes",this.handleOrder),l(".postbox .hndle a").on("click",function(e){e.stopPropagation()}),l(".postbox a.dismiss").on("click.postboxes",function(e){var o=l(this).parents(".postbox").attr("id")+"-hide";e.preventDefault(),l("#"+o).prop("checked",!1).triggerHandler("click")}),l(".hide-postbox-tog").on("click.postboxes",function(){var e=l(this),o=e.val(),s=l("#"+o);e.prop("checked")?(s.show(),"function"==typeof postboxes.pbshow&&postboxes.pbshow(o)):(s.hide(),"function"==typeof postboxes.pbhide&&postboxes.pbhide(o)),postboxes.save_state(t),postboxes._mark_area(),a.trigger("postbox-toggled",s)}),l('.columns-prefs input[type="radio"]').on("click.postboxes",function(){var e=parseInt(l(this).val(),10);e&&(postboxes._pb_edit(e),postboxes.save_order(t))})},init:function(o,e){var s=l(document.body).hasClass("mobile"),t=l(".postbox .handlediv");l.extend(this,e||{}),l(".meta-box-sortables").sortable({placeholder:"sortable-placeholder",connectWith:".meta-box-sortables",items:".postbox",handle:".hndle",cursor:"move",delay:s?200:0,distance:2,tolerance:"pointer",forcePlaceholderSize:!0,helper:function(e,o){return o.clone().find(":input").attr("name",function(e,o){return"sort_"+parseInt(1e5*Math.random(),10).toString()+"_"+o}).end()},opacity:.65,start:function(){l("body").addClass("is-dragging-metaboxes"),l(".meta-box-sortables").sortable("refreshPositions")},stop:function(){var e=l(this);l("body").removeClass("is-dragging-metaboxes"),e.find("#dashboard_browser_nag").is(":visible")&&"dashboard_browser_nag"!=this.firstChild.id?e.sortable("cancel"):(postboxes.updateOrderButtonsProperties(),postboxes.save_order(o))},receive:function(e,o){"dashboard_browser_nag"==o.item[0].id&&l(o.sender).sortable("cancel"),postboxes._mark_area(),a.trigger("postbox-moved",o.item)}}),s&&(l(document.body).on("orientationchange.postboxes",function(){postboxes._pb_change()}),this._pb_change()),this._mark_area(),this.updateOrderButtonsProperties(),a.on("postbox-toggled",this.updateOrderButtonsProperties),t.each(function(){var e=l(this);e.attr("aria-expanded",!e.closest(".postbox").hasClass("closed"))})},save_state:function(e){var o,s;"nav-menus"!==e&&(o=l(".postbox").filter(".closed").map(function(){return this.id}).get().join(","),s=l(".postbox").filter(":hidden").map(function(){return this.id}).get().join(","),l.post(ajaxurl,{action:"closed-postboxes",closed:o,hidden:s,closedpostboxesnonce:jQuery("#closedpostboxesnonce").val(),page:e}))},save_order:function(e){var o=l(".columns-prefs input:checked").val()||0,s={action:"meta-box-order",_ajax_nonce:l("#meta-box-order-nonce").val(),page_columns:o,page:e};l(".meta-box-sortables").each(function(){s["order["+this.id.split("-")[0]+"]"]=l(this).sortable("toArray").join(",")}),l.post(ajaxurl,s,function(e){e.success&&wp.a11y.speak(r("The boxes order has been saved."))})},_mark_area:function(){var o=l("div.postbox:visible").length,e=l("#dashboard-widgets .meta-box-sortables:visible, #post-body .meta-box-sortables:visible"),s=!0;e.each(function(){var e=l(this);1==o||e.children(".postbox:visible").length?(e.removeClass("empty-container"),s=!1):e.addClass("empty-container")}),postboxes.updateEmptySortablesText(e,s)},updateEmptySortablesText:function(e,o){var s=l("#dashboard-widgets").length,t=r(o?"Add boxes from the Screen Options menu":"Drag boxes here");s&&e.each(function(){l(this).hasClass("empty-container")&&l(this).attr("data-emptyString",t)})},_pb_edit:function(e){var o=l(".metabox-holder").get(0);o&&(o.className=o.className.replace(/columns-\d+/,"columns-"+e)),l(document).trigger("postboxes-columnchange")},_pb_change:function(){var e=l('label.columns-prefs-1 input[type="radio"]');switch(window.orientation){case 90:case-90:e.length&&e.is(":checked")||this._pb_edit(2);break;case 0:case 180:l("#poststuff").length?this._pb_edit(1):e.length&&e.is(":checked")||this._pb_edit(2)}},pbshow:!1,pbhide:!1}}(jQuery);password-strength-meter.min.js000064400000002143147573140730012507 0ustar00/*! This file is auto-generated */ window.wp=window.wp||{},function(a){var e=wp.i18n.__,n=wp.i18n.sprintf;wp.passwordStrength={meter:function(e,n,t){return Array.isArray(n)||(n=[n.toString()]),e!=t&&t&&0