From 7636d7ab12fda1acddc4bf8a4e341eb7ae105f7b Mon Sep 17 00:00:00 2001 From: Stefan Grunert Date: Fri, 22 Feb 2019 16:13:47 +0100 Subject: [PATCH] improve insert nested assets --- dist/bundle.js | 2 ++ dist/bundle.js.map | 1 + 2 files changed, 3 insertions(+) create mode 100644 dist/bundle.js create mode 100644 dist/bundle.js.map diff --git a/dist/bundle.js b/dist/bundle.js new file mode 100644 index 0000000..723312b --- /dev/null +++ b/dist/bundle.js @@ -0,0 +1,2 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.PluginAPI=t():e.PluginAPI=t()}(this,function(){return function(e){function t(r){if(o[r])return o[r].exports;var n=o[r]={exports:{},id:r,loaded:!1};return e[r].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var o={};return t.m=e,t.c=o,t.p="",t(0)}([function(e,exports,t){"use strict";var o=t(1),r=t(2),n=t(3),i=function(){var e=function(){function e(e){function o(e){for(var t in e)e.hasOwnProperty(t)&&("object"==typeof e[t]&&null!==e[t]&&"function"===e[t].type?e[t]=r(e[t].eventKey):"object"==typeof e[t]&&null!==e[t]&&"function"==typeof e[t].map?e[t]=e[t].map(o):"object"==typeof e[t]&&null!==e[t]&&(e[t]=o(e[t])));return e}function r(e){return function(t){i.request(e,t)}}var n=t.eventListeners.notify(e.type,o(e.data));return n!==!1||{abort:!0}}this.DEBUG=!1,this.Version="3.0",this.Editor=null,this.Article=null,this.errorListeners=new n,this.eventListeners=new n,this.appName="";var t=this;pm.bind("event",e,"*")};return e.prototype.request=function(e,t,o){var r=this;this.DEBUG&&console.info(this.getAppName()+": Requesting "+e+" from parent with data",t),t||(t={}),"undefined"==typeof o&&(o=null),"number"==typeof t.length&&(t={data:t}),t.src_app=this.getAppName();var n=function(e,t){return function(){return r.eventListeners.remove(t,t),e.apply(null,arguments)}},i=function(e,t){var o=Math.floor(1e3*Math.random()),i=e+o+"functioncallback"+(new Date).getTime(),s=n(t,i);return r.eventListeners.add(i,s),{type:"function",eventKey:i}},s=function(e){for(var t in e)if(e.hasOwnProperty(t)){var o=e[t];"function"==typeof o?e[t]=i(t,o):"object"==typeof o&&null!==o&&"function"==typeof o.map?e[t]=o.map(s):"object"==typeof o&&null!==o&&(e[t]=s(o))}return e};t=s(t),pm({target:parent,type:e,data:t,success:o,error:function(e){r.errorListeners.notify(e.type,e)},origin:"*",hash:!1})},e.prototype.openTagCreationDialog=function(e,t){this.request("create-tag",{tag:e},t)},e.prototype.reloadIframe=function(){this.request("app-reload",{app:this.getAppName()})},e.prototype.getAppName=function(){return this.appName},e.prototype.setAppName=function(e){this.appName=e},e.prototype.showInfoMsg=function(e){this.request("show-message-info",{message:e})},e.prototype.showWarningMsg=function(e){this.request("show-message-warning",{message:e})},e.prototype.showErrorMsg=function(e){this.request("show-message-error",{message:e})},e.prototype.showLoader=function(e){this.request("show-loader",{message:e})},e.prototype.hideLoader=function(){this.request("hide-loader")},e.prototype.__loadArticleRevision=function(e,t){this.request("load-revision",{revision:e},t)},e.prototype.createTag=function(e,t){this.request("tag-create",{tag:e},t)},e.prototype.searchDrLib=function(e,t){this.request("drlib-search",{query:e.query,access:e.access,secure:e.secure,success:e.success,error:e.error},t)},e.prototype.convertDomToHTML=function(e){return"object"==typeof e&&"function"==typeof e.wrap?e.wrap("
").parent().html():e.outerHTML},e.prototype.generateArticleUrl=function(e,t){this.request("generate-article-url",{id:e},t)},e.prototype.extendApi=function(e,t,o){var r=this;this.request("extend-api",{group:e,name:t,action:function(e){var t=o(e.data);r.request(e.eventKey,{data:t})}})},e.prototype.callExtendedApi=function(e,t,o,r){this.request("call-extended-api",{group:e,name:t,data:o,callback:r})},e.prototype.getCurrentUser=function(e){this.request("get-current-user",null,e)},e.prototype.getConfiguration=function(e){this.request("get-configuration",null,e)},e.prototype.getDrPublishConfiguration=function(e){this.request("get-drpublish-configuration",null,e)},e.prototype.setConfiguration=function(e,t,o){"boolean"==typeof t?t={onlyPublication:t}:"object"==typeof t&&null!==t||(t={});var r={config:e,onlyPublication:"boolean"==typeof t.onlyPublication&&t.onlyPublication,success:"function"==typeof t.success?t.success:null,error:"function"==typeof t.error?t.error:null};this.request("set-configuration",r,o)},e.prototype.emit=function(e,t){this.request("emit-api-event",{name:e,data:t})},e.prototype.on=function(e,t){var o=this;o.eventListeners.add(e,t),this.request("on-api-event",{name:e})},e.prototype.increaseRequiredActionCounter=function(e){this.request("increase-required-action-counter",{},e)},e.prototype.decreaseRequiredActionCounter=function(e){this.request("decrease-required-action-counter",{},e)},e.prototype.clearRequiredActionCounter=function(e){this.request("clear-required-action-counter",{},e)},e.prototype.setRequiredActionCounter=function(e,t){this.request("set-required-action-counter",{count:e},t)},e.prototype.create=function(){return new e},e.prototype.createEmbeddedObject=function(e,t){this.request("create-embedded-object",{typeId:e,callback:t})},e.prototype.getEmbeddedObjectTypes=function(e){this.request("get-embedded-object-types",null,e)},e.prototype.giveFocus=function(e,t,o){return"string"==typeof e&&""!==e&&("boolean"!=typeof o&&(o=!0),this.request("give-focus",{pluginName:e,start:o,argument:t}),!0)},e.prototype.hide=function(){return this.request("hide"),!0},e.prototype.createModal=function(e,t){return this.request("create-custom-modal",{content:e,options:t}),!0},e.prototype.updateModal=function(e){return this.request("update-custom-modal",{content:e}),!0},e.prototype.closeModal=function(e){return this.request("close-custom-modal",{destroy:e}),!0},e.prototype.getModalInputs=function(e){this.request("get-custom-modal-inputs",null,e)},e.prototype.confirmAuthenticated=function(){this.request("confirm-authenticated",{pluginName:this.appName})},new e}();i.Article=o(i),i.Editor=r(i),e.exports=i},function(e,exports){"use strict";e.exports=function(e){var t=function(){this.DEBUG=!1};return t.prototype.focusApp=function(t){e.request("app-focus",{},t)},t.prototype.startApp=function(t,o,r){e.request("app-start",{app:t,option:o},r)},t.prototype.stopApp=function(t){e.request("app-stop",{app:t})},t.prototype.getId=function(t){e.request("article-id-get",null,t)},t.prototype.getPackageId=function(t){e.request("package-id-get",null,t)},t.prototype.getPackageGuid=function(t){e.request("package-guid-get",null,t)},t.prototype.clearMetaInfo=function(t){e.request("article-metainfo-clear",null,t)},t.prototype.getTags=function(t){e.request("article-tags-get",null,t)},t.prototype.getCustomMeta=function(t,o){e.request("article-custom-meta-get",{name:t},o)},t.prototype.setCustomMeta=function(t,o,r){e.request("article-custom-meta-set",{name:t,value:o},r)},t.prototype.setTags=function(t,o,r){e.request("article-tags-set",{save:o,tags:t},r)},t.prototype.addTag=function(t,o,r){e.request("article-tags-add",{tag:t,onError:o},r)},t.prototype.addTags=function(t,o,r){e.request("article-tags-add",{tags:t,onError:o},r)},t.prototype.removeTag=function(t,o){e.request("article-tags-remove",{tag:t},o)},t.prototype.getSelectedCategories=function(t){e.request("article-categories-selected-get",null,t)},t.prototype.saveCategories=function(e){this.getSelectedCategories(function(t){this.setCategories(t,e)})},t.prototype.setCategories=function(t,o){e.request("article-categories-selected-set",{categories:t},o)},t.prototype.addCategories=function(t,o){e.request("article-categories-add",{categories:t},o)},t.prototype.removeCategories=function(t,o){e.request("article-categories-remove",{categories:t},o)},t.prototype.setMainCategory=function(t,o){e.request("article-categories-main-set",{category:t},o)},t.prototype.getSource=function(t){e.request("article-source-get",null,t)},t.prototype.setSource=function(t,o){e.request("article-source-set",{source:t},o)},t.prototype.getStatus=function(t){e.request("article-status-get",null,t)},t.prototype.setStatus=function(t,o){e.request("article-status-set",{status:t},o)},t.prototype.getPublishedDatetime=function(t){e.request("article-published-get",null,t)},t.prototype.setPublishedDatetime=function(t,o){e.request("article-published-set",{published:t},o)},t.prototype.getAuthors=function(t){e.request("article-authors-get",null,t)},t.prototype.setAuthors=function(t,o){e.request("article-authors-set",{authors:t},o)},t.prototype.addAuthors=function(t,o){e.request("article-authors-add",{authors:t},o)},t.prototype.removeAuthors=function(t,o){e.request("article-authors-remove",{authors:t},o)},t.prototype.setKeywords=function(t,o){e.request("article-keywords-set",{keywords:t},o)},t.prototype.getKeywords=function(t){e.request("article-keywords-get",null,t)},t.prototype.getCurrentContent=function(t){e.request("article-content-get",null,t)},t.prototype.setCurrentContent=function(t,o){e.request("article-content-set",{content:t},o)},t.prototype.getArticletypeId=function(t){e.request("article-type-get",null,t)},t.prototype.setArticletypeId=function(t,o){e.request("article-type-set",{articletype:t},o)},t.prototype.maximizeAppWindow=function(t,o){var r="editor-pane-close-"+(new Date).getTime();e.request("editor-pane-maximize",{title:t,event:r}),e.eventListeners.removeAll(r),e.eventListeners.add(r,o)},t.prototype.restoreAppWindow=function(t){e.request("restore-app-window",{},t)},t.prototype.getByline=function(t){e.request("article-byline-get",null,t)},t.prototype.setByline=function(t,o,r){e.request("article-byline-set",{save:o,byline:t},r)},t.prototype.setGeolocations=function(t,o){e.request("article-geolocations-set",{geolocations:t},o)},t.prototype.getGeolocations=function(t){e.request("article-geolocations-get",null,t)},t.prototype.getProperties=function(t){e.request("article-properties-get",null,t)},t.prototype.setProperties=function(t,o){e.request("article-properties-set",{properties:t},o)},t.prototype.setProperty=function(t,o,r){var n={};n[t]=o,e.request("article-properties-set",{properties:n},r)},t.prototype.getTopic=function(t){e.request("article-topic-get",null,t)},t.prototype.setTopic=function(t,o){e.request("article-topic-set",{topic:t},o)},new t}},function(e,exports){"use strict";e.exports=function(e){var t=null,o=function(){function o(e){t=e}function r(){t=null}this.DEBUG=!1,e.on("pluginElementClicked",o),e.on("pluginElementDeselected",r)};return o.prototype.getActiveEditor=function(t){e.request("get-active-editor",null,t)},o.prototype.registerMenuAction=function(t,o){e.request("register-menu-action",t,o)},o.prototype.registerHoverAction=function(t,o){e.request("register-hover-action",t,o)},o.prototype.directionalCastle=function(t,o){e.request("editor-directional-castle",t,o)},o.prototype.registerMenuActionGroup=function(t,o){e.request("register-menu-action-group",t,o)},o.prototype.getEditorType=function(t){e.request("editor-get-type",null,t)},o.prototype.replaceElementById=function(t,o,r){e.request("editor-element-replace-byid",{id:t,element:o},r)},o.prototype.replacePluginElementById=function(t,o,r){e.request("editor-element-replace-plugin-element-byid",{id:t,element:o},r)},o.prototype.deleteElementById=function(t,o){e.request("editor-element-replace-byid",{id:t},o)},o.prototype.getHTMLById=function(t,o){e.request("editor-element-get-byid",{id:t},o)},o.prototype.getHTMLBySelector=function(t,o){e.request("editor-elements-get-byselector",{selector:t},o)},o.prototype.getCategories=function(t){e.request("get-categories",null,t)},o.prototype.getParentCategories=function(t,o){e.request("get-parent-categories",t,o)},o.prototype.getParentIds=function(t,o,r){e.request("get-parent-ids",{id:t,selector:o},r)},o.prototype.getTagTypes=function(t){e.request("get-tag-types",null,t)},o.prototype.getTagType=function(t,o){e.request("get-tag-type",{id:t},o)},o.prototype.clear=function(t){e.request("editor-clear",null,t)},o.prototype.insertString=function(t,o){e.request("editor-insert-string",{string:t},o)},o.prototype.insertElement=function(t,o,r){var n=!1;"object"==typeof o?(o=o||{},n="boolean"==typeof o.select&&o.select):"undefined"==typeof r&&"function"==typeof o&&(r=o),e.request("editor-insert-element",{element:t.outerHTML,select:n},r)},o.prototype.removeClasses=function(t,o,r){e.request("editor-classes-remove",{id:t,classes:o},r)},o.prototype.addClasses=function(t,o,r){e.request("editor-classes-add",{id:t,classes:o},r)},o.prototype.markAsActive=function(t,o){e.request("editor-mark-as-active",{id:t},o)},o.prototype.setAttributeById=function(t,o,r,n){e.request("editor-element-attribute-set-byid",{id:t,attribute:o,value:r},n)},o.prototype.setStyleById=function(t,o,r,n){e.request("editor-element-style-set-byid",{id:t,attribute:o,value:r},n)},o.prototype.initMenu=function(t,o){e.request("editor-initialize-menu",{menus:t},o)},o.prototype.openPluginElementEditor=function(t){e.request("open-element-editor",{id:t})},o.prototype.getTotalWordCount=function(t){e.request("total-word-count",null,t)},o.prototype.getTotalCharCount=function(t){e.request("total-char-count",null,t)},o.prototype.updateAssetOption=function(t,o,r,n){e.request("update-asset-option",{dpArticleId:t,key:o,value:r},n)},o.prototype.updateAssetData=function(t,o){e.request("update-asset-media",t,o)},o.prototype.getAssetData=function(t,o){e.request("get-asset-data",{data:t},o)},o.prototype.insertNestedAsset=function(t,o,r,n){function i(t,n,i){r.internalId=t;var s="asset-"+t,a=$("
");a.attr("id",s),a.attr("data-internalId",t),r.externalId&&a.attr("data-externalId",r.externalId),r.assetClass&&a.addClass(r.assetClass),a.addClass("dp-plugin-element"),a.html(o),e.Editor.getHTMLById(n,function(e){var t=document.createElement("div");t.innerHTML=e,t.firstChild.setAttribute("id",n+"tmp"),u.replacePluginElementById(n,t.innerHTML,function(){t=document.createElement("div"),t.innerHTML=e;var o=t.querySelector(".dp-fact-box-image, .dp-nested-asset-container");r.isMultiple?$(o).append(a.get(0).outerHTML):o.innerHTML=a.get(0).outerHTML,u.replacePluginElementById(n+"tmp",t.innerHTML,i)})})}function s(t){e.request("update-embedded-asset",r,t)}var u=this;e.createEmbeddedObject(r.embeddedTypeId,function(e){i(e,t,function(e){return s(n)})})},o.prototype.insertEmbeddedAsset=function(o,r,n){function i(e,t){r.internalId=e;var n="asset-"+e,i=document.createElement("div");if(i.id=n,i.dataset.internalId=e,r.externalId&&(i.dataset.externalId=r.externalId),r.assetClass&&i.classList.add(r.assetClass),i.innerHTML=o,p?a.replaceElementById(n,i.outerHTML,null):a.insertElement(i,{select:!0}),"function"==typeof t)return t()}function s(t){e.request("add-embedded-asset",r,t)}function u(t){e.request("update-embedded-asset",r,t)}var a=this,p=!1;if(t){if(r.assetSource!==e.getAppName())return void e.showErrorMsg("Can't update selected plugin element since it doesn't belong to the '"+e.getAppName()+"' plugin");p=!0}if(t){var c=t.dpArticleId;if(!c)throw Error("Selected plugin element: expected dpArticleId not found (tried reading from attribute 'data-internal-id')");i(c,function(e){return u("function"==typeof n?n(e):null)})}else e.createEmbeddedObject(r.embeddedTypeId,function(e){i(e,function(e){return s("function"==typeof n?n(e):null)})})},o.prototype.getSelectedPluginElement=function(t){e.request("get-selected-plugin-element",{},t)},new o}},function(e,exports){"use strict";function t(){this._listeners={}}e.exports=t,t.prototype.add=function(e,t){if("function"!=typeof t)throw Error("Listener callback must be a function.");return void 0===this._listeners[e]&&(this._listeners[e]=[]),this._listeners[e].push(t),this._listeners[e].length-1},t.prototype.remove=function(e,t){void 0!==this._listeners[e]&&void 0!==this._listeners[e][t]&&(this._listeners[e][t]=!1)},t.prototype.removeAll=function(e){e?this._listeners[e]=[]:this._listeners=[]},t.prototype.notify=function(e,t){var o=!0;return void 0===this._listeners[e]?o:(this._listeners[e].forEach(function(e){if("function"==typeof e){var r=null;r=t&&t.params&&t.params===!0?e.apply(null,t.data):e("object"==typeof t&&null!==t&&"undefined"!=typeof t.data?t.data:t),r===!1&&(o=!1)}}),o)}}])}); +//# sourceMappingURL=bundle.js.map \ No newline at end of file diff --git a/dist/bundle.js.map b/dist/bundle.js.map new file mode 100644 index 0000000..da31986 --- /dev/null +++ b/dist/bundle.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///bundle.js","webpack:///webpack/bootstrap b7ce02d6d601da7cb8b9","webpack:///./js/PluginAPI.js","webpack:///./js/articleCommunicator.js","webpack:///./js/AH5Communicator.js","webpack:///./js/Listeners.js"],"names":["root","factory","exports","module","define","amd","this","modules","__webpack_require__","moduleId","installedModules","id","loaded","call","m","c","p","articleCommunicator","ah5Communicator","Listeners","PluginAPI","Api","eventListener","event","updateObjectWithEventFunctions","data","key","hasOwnProperty","type","createEventFunction","eventKey","map","eventName","request","continueProcessing","self","eventListeners","notify","abort","DEBUG","Version","Editor","Article","errorListeners","appName","pm","bind","prototype","callSpec","callback","console","info","getAppName","length","src_app","func","remove","apply","arguments","createCallbackObject","random","Math","floor","Date","getTime","eventFunction","add","updateObject","val","target","parent","success","error","origin","hash","openTagCreationDialog","tag","reloadIframe","app","setAppName","name","showInfoMsg","msg","message","showWarningMsg","showErrorMsg","showLoader","hideLoader","__loadArticleRevision","revision","createTag","searchDrLib","query","access","secure","convertDomToHTML","element","wrap","html","outerHTML","generateArticleUrl","extendApi","group","action","a","callExtendedApi","getCurrentUser","getConfiguration","getDrPublishConfiguration","setConfiguration","config","options","onlyPublication","emit","on","increaseRequiredActionCounter","decreaseRequiredActionCounter","clearRequiredActionCounter","setRequiredActionCounter","count","create","createEmbeddedObject","typeId","getEmbeddedObjectTypes","giveFocus","pluginName","argument","start","hide","createModal","content","updateModal","closeModal","destroy","getModalInputs","confirmAuthenticated","ArticleCommunicator","focusApp","startApp","option","stopApp","getId","getPackageId","getPackageGuid","clearMetaInfo","getTags","getCustomMeta","setCustomMeta","value","setTags","tags","save","addTag","errorFunction","onError","addTags","removeTag","getSelectedCategories","saveCategories","categories","setCategories","addCategories","removeCategories","setMainCategory","category","getSource","setSource","source","getStatus","setStatus","status","getPublishedDatetime","setPublishedDatetime","published","getAuthors","setAuthors","authors","addAuthors","removeAuthors","setKeywords","keywords","getKeywords","getCurrentContent","setCurrentContent","getArticletypeId","setArticletypeId","articletypeId","articletype","maximizeAppWindow","title","onClose","removeAll","restoreAppWindow","getByline","setByline","byline","setGeolocations","geolocations","getGeolocations","getProperties","setProperties","properties","setProperty","getTopic","setTopic","topic","selectedPluginElement","AH5Communicator","pluginElementSelected","elementData","pluginElementDeselected","getActiveEditor","registerMenuAction","registerHoverAction","directionalCastle","movement","registerMenuActionGroup","getEditorType","replaceElementById","replacePluginElementById","deleteElementById","getHTMLById","getHTMLBySelector","selector","getCategories","getParentCategories","getParentIds","getTagTypes","getTagType","clear","insertString","string","insertElement","select","removeClasses","classes","addClasses","markAsActive","setAttributeById","attribute","setStyleById","initMenu","menus","openPluginElementEditor","getTotalWordCount","getTotalCharCount","updateAssetOption","dpArticleId","updateAssetData","getAssetData","insertNestedAsset","parentElementId","markup","insert","internalId","elementId","$element","$","attr","externalId","assetClass","addClass","d","document","createElement","innerHTML","firstChild","setAttribute","assetContainer","querySelector","isMultiple","append","get","updateEmbeddedAssetRequest","embeddedTypeId","insertEmbeddedAsset","dataset","classList","replaceElement","addEmbeddedAssetRequest","assetSource","Error","getSelectedPluginElement","_listeners","undefined","push","index","payload","returnValue","forEach","listenerFn","res","params"],"mappings":"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","file":"bundle.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"PluginAPI\"] = factory();\n\telse\n\t\troot[\"PluginAPI\"] = factory();\n})(this, function() {\nreturn \n\n\n/** WEBPACK FOOTER **\n ** webpack/universalModuleDefinition\n **/","(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"PluginAPI\"] = factory();\n\telse\n\t\troot[\"PluginAPI\"] = factory();\n})(this, function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ function(module, exports, __webpack_require__) {\n\n\t/* global pm:false*/\n\t'use strict';\n\t\n\tvar articleCommunicator = __webpack_require__(1);\n\tvar ah5Communicator = __webpack_require__(2);\n\tvar Listeners = __webpack_require__(3);\n\t\n\t/**\n\t * @extends Api\n\t * @property {ArticleCommunicator} Article\n\t * @property {AH5Communicator} Editor\n\t */\n\t\n\t/* eslint max-statements: [\"error\", 50, { \"ignoreTopLevelFunctions\": true }]*/\n\tvar PluginAPI = (function () {\n\t\n\t\t/**\n\t\t *\n\t\t * Namespace for all public DrPublish methods available from apps.\n\t\t *\n\t\t * @class\n\t\t * @classdesc The basic API object\n\t\t * @exports PluginAPI\n\t\t *\n\t\t */\n\t\tvar Api = function () {\n\t\t\tthis.DEBUG = false;\n\t\n\t\t\tthis.Version = '3.0';\n\t\t\tthis.Editor = null;\n\t\t\tthis.Article = null;\n\t\t\tthis.errorListeners = new Listeners();\n\t\t\tthis.eventListeners = new Listeners();\n\t\t\tthis.appName = '';\n\t\n\t\t\tvar self = this;\n\t\n\t\t\tpm.bind('event', eventListener, '*');\n\t\n\t\t\t/**\n\t\t\t * @param {Object} event\n\t\t\t * @param {String} event.type\n\t\t\t * @param {*} event.data\n\t * @return {boolean|Object} True if none of listeners want to stop the processing\n\t */\n\t\t\tfunction eventListener(event) {\n\t\t\t\tvar continueProcessing = self.eventListeners.notify(\n\t\t\t\t\tevent.type,\n\t\t\t\t\tupdateObjectWithEventFunctions(event.data)\n\t\t\t\t);\n\t\n\t\t\t\tif (continueProcessing === false) {\n\t\t\t\t\treturn {abort: true};\n\t\t\t\t}\n\t\n\t\t\t\treturn true;\n\t\n\t\t\t\t/**\n\t\t\t\t * data can be be anything, but if it's an object, we'll iterate over the keys and look for any values\n\t\t\t\t * that should be treated as function calls.\n\t\t\t\t *\n\t\t\t\t * To be treated as a function call, the value must be an object where `type === 'function'`, and have a key\n\t\t\t\t * `eventKey` which is the event name that should be passed to `PluginAPI.request()`\n\t\t\t\t *\n\t\t\t\t * @param {*} data\n\t * @return {*}\n\t */\n\t\t\t\tfunction updateObjectWithEventFunctions(data) {\n\t\t\t\t\tfor (var key in data) {\n\t\t\t\t\t\tif (data.hasOwnProperty(key)) {\n\t\t\t\t\t\t\tif (typeof data[key] === 'object' && data[key] !== null && data[key].type === 'function') {\n\t\t\t\t\t\t\t\tdata[key] = createEventFunction(data[key].eventKey);\n\t\t\t\t\t\t\t} else if (typeof data[key] === 'object' && data[key] !== null && typeof data[key].map === 'function') {\n\t\t\t\t\t\t\t\tdata[key] = data[key].map(updateObjectWithEventFunctions);\n\t\t\t\t\t\t\t} else if (typeof data[key] === 'object' && data[key] !== null) {\n\t\t\t\t\t\t\t\tdata[key] = updateObjectWithEventFunctions(data[key]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\t\n\t\t\t\tfunction createEventFunction(eventName) {\n\t\t\t\t\treturn function (data) {\n\t\t\t\t\t\tPluginAPI.request(eventName, data);\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\n\t\t/**\n\t\t * Dispatches a request to DrPublish, and returns the reply to callback On error, notifies all error listeners based on the index .type of the thrown object\n\t\t *\n\t\t * @param {String} callSpec What do you want to call?\n\t\t * @param {Object} data The data attached to the request\n\t\t * @param {Function} [callback] The function to call upon return\n\t\t */\n\t\tApi.prototype.request = function (callSpec, data, callback) {\n\t\t\tvar self = this;\n\t\t\tif (this.DEBUG) {\n\t\t\t\tconsole.info(this.getAppName() + ': Requesting ' + callSpec + ' from parent with data', data);\n\t\t\t}\n\t\n\t\t\tif (!data) {\n\t\t\t\tdata = {};\n\t\t\t}\n\t\n\t\t\tif (typeof callback === 'undefined') {\n\t\t\t\tcallback = null;\n\t\t\t}\n\t\n\t\t\tif (typeof data.length === 'number') {\n\t\t\t\tdata = {data: data};\n\t\t\t}\n\t\n\t\t\t// eslint-disable-next-line camelcase\n\t\t\tdata.src_app = this.getAppName();\n\t\n\t\t\tvar createEventFunction = function (func, eventKey) {\n\t\t\t\treturn function () {\n\t\t\t\t\tself.eventListeners.remove(eventKey, eventKey);\n\t\t\t\t\treturn func.apply(null, arguments);\n\t\t\t\t};\n\t\t\t};\n\t\n\t\t\tvar createCallbackObject = function (key, callback) {\n\t\t\t\tvar random = Math.floor(Math.random() * 1000);\n\t\t\t\tvar eventKey = key + random + 'functioncallback' + (new Date()).getTime();\n\t\t\t\tvar eventFunction = createEventFunction(callback, eventKey);\n\t\t\t\tself.eventListeners.add(eventKey, eventFunction);\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'function',\n\t\t\t\t\teventKey: eventKey\n\t\t\t\t};\n\t\t\t};\n\t\n\t\t\tvar updateObject = function (data) {\n\t\t\t\tfor (var key in data) {\n\t\t\t\t\tif (data.hasOwnProperty(key)) {\n\t\t\t\t\t\tvar val = data[key];\n\t\t\t\t\t\tif (typeof val === 'function') {\n\t\t\t\t\t\t\tdata[key] = createCallbackObject(key, val);\n\t\t\t\t\t\t} else if (typeof val === 'object' && val !== null && typeof val.map === 'function') {\n\t\t\t\t\t\t\tdata[key] = val.map(updateObject);\n\t\t\t\t\t\t} else if (typeof val === 'object' && val !== null) {\n\t\t\t\t\t\t\tdata[key] = updateObject(val);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn data;\n\t\t\t};\n\t\t\tdata = updateObject(data);\n\t\n\t\t\tpm({\n\t\t\t\ttarget: parent,\n\t\t\t\ttype: callSpec,\n\t\t\t\tdata: data,\n\t\t\t\tsuccess: callback,\n\t\t\t\terror: function (data) {\n\t\t\t\t\tself.errorListeners.notify(data.type, data);\n\t\t\t\t},\n\t\t\t\torigin: '*', // TODO: Find a way of avoiding all-origins\n\t\t\t\thash: false\n\t\t\t});\n\t\t};\n\t\n\t\n\t\t/**\n\t\t * Creates a new tag\n\t\t *\n\t\t * @param {String} tag The tag to create\n\t\t * @param {Function} callback function(Boolean)\n\t\t */\n\t\tApi.prototype.openTagCreationDialog = function (tag, callback) {\n\t\t\tthis.request('create-tag', {\n\t\t\t\ttag: tag\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Reloads the app's iframe\n\t\t */\n\t\tApi.prototype.reloadIframe = function () {\n\t\n\t\t\tthis.request('app-reload', {\n\t\t\t\tapp: this.getAppName()\n\t\t\t});\n\t\t};\n\t\n\t\t/**\n\t\t * Get the name of the loaded app\n\t\t *\n\t\t * @return {String} The name of the app, or false if it couldn't be detected\n\t\t */\n\t\tApi.prototype.getAppName = function () {\n\t\t\treturn this.appName;\n\t\t};\n\t\n\t\t/**\n\t\t * Set the name of the app\n\t\t *\n\t\t * @param {String} name The name of the app\n\t\t */\n\t\tApi.prototype.setAppName = function (name) {\n\t\t\tthis.appName = name;\n\t\t};\n\t\n\t\t/**\n\t\t * Show info-message to the user\n\t\t *\n\t\t * @param {String} msg Message to be displayed\n\t\t */\n\t\tApi.prototype.showInfoMsg = function (msg) {\n\t\n\t\t\tthis.request('show-message-info', {\n\t\t\t\tmessage: msg\n\t\t\t});\n\t\t};\n\t\n\t\t/**\n\t\t * Show warning-message to the user\n\t\t *\n\t\t * @param {String} msg Message to be displayed\n\t\t */\n\t\tApi.prototype.showWarningMsg = function (msg) {\n\t\n\t\t\tthis.request('show-message-warning', {\n\t\t\t\tmessage: msg\n\t\t\t});\n\t\t};\n\t\n\t\t/**\n\t\t * Show error-message to the user\n\t\t *\n\t\t * @param {String} msg Message to be displayed\n\t\t */\n\t\tApi.prototype.showErrorMsg = function (msg) {\n\t\n\t\t\tthis.request('show-message-error', {\n\t\t\t\tmessage: msg\n\t\t\t});\n\t\t};\n\t\n\t\t/**\n\t\t * Show the loader\n\t\t *\n\t\t * @param {String} msg Message to display in progress loader\n\t\t */\n\t\tApi.prototype.showLoader = function (msg) {\n\t\t\tthis.request('show-loader', {\n\t\t\t\tmessage: msg\n\t\t\t});\n\t\t};\n\t\n\t\t/**\n\t\t * Hide the loader\n\t\t */\n\t\tApi.prototype.hideLoader = function () {\n\t\t\tthis.request('hide-loader');\n\t\t};\n\t\n\t\t/**\n\t\t * Loads an old revision of an article\n\t\t *\n\t\t * @param {Number} id The id of the revision to load\n\t\t * @param {Function} callback The function to call when the new revision has been loaded\n\t\t * @private\n\t\t */\n\t\tApi.prototype.__loadArticleRevision = function (id, callback) {\n\t\t\tthis.request('load-revision', {\n\t\t\t\trevision: id\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Creates a new tag\n\t\t *\n\t\t * @param {String} tag JSON object with the tag to create, must contain tagTypeId and name properties\n\t\t * @param {Function} callback function(Boolean)\n\t\t */\n\t\tApi.prototype.createTag = function (tag, callback) {\n\t\t\tthis.request('tag-create', {\n\t\t\t\ttag: tag\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Sends a query to DrLib\n\t\t *\n\t\t * @example\n\t\t * PluginAPI.searchDrLib({\n\t * query: 'articles.json?q=awesome',\n\t * secure: true,\n\t * success: function(data) {\n\t * data.items.forEach(doStuffWithArticle);\n\t * },\n\t * error: function(data) {\n\t * console.warn('something went wrong');\n\t * }\n\t * })\n\t\t *\n\t\t * @param {Object} data Object with three properties; 'query' which is the query to send to DrLib, 'success' which is the callback to execute on success, and 'secure' a boolean to add the internal API key to the query and thus allow searching on unpublished article. This callback's parameter is an object which is the query result as an object. See the json output of DrLib to learn more about this object\n\t\t * @param {Function} callback function(Boolean)\n\t\t *\n\t\t */\n\t\tApi.prototype.searchDrLib = function (data, callback) {\n\t\t\tthis.request('drlib-search', {\n\t\t\t\tquery: data.query,\n\t\t\t\taccess: data.access,\n\t\t\t\tsecure: data.secure,\n\t\t\t\tsuccess: data.success,\n\t\t\t\terror: data.error\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Generates proper html code to represent the dom element. This is NOT an asynchronous function\n\t\t *\n\t\t * @param {Object|Element} element The dom node to convert\n\t\t * @return {String} The html code\n\t\t */\n\t\tApi.prototype.convertDomToHTML = function (element) {\n\t\t\t// Support for passing in a jQuery element\n\t\t\tif (typeof element === 'object' && typeof element.wrap === 'function') {\n\t\t\t\treturn element.wrap('
').parent().html();\n\t\t\t}\n\t\t\treturn element.outerHTML;\n\t\t};\n\t\n\t\t/**\n\t\t * Generates an url to a published article\n\t\t *\n\t\t * @param {String} id The id of the article to generate url for\n\t\t * @param {Function} callback function(String), where the parameter is the generated url\n\t\t */\n\t\tApi.prototype.generateArticleUrl = function (id, callback) {\n\t\t\tthis.request('generate-article-url', {\n\t\t\t\tid: id\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Extends the PluginAPI with custom functionality that other apps can use\n\t\t *\n\t\t * @param {String} group Group name for functionality to add\n\t\t * @param {String} name Name of the specific function to add\n\t\t * @param {Function} action function(Object) Function to call when the API is invoked, recieves one parameter as given in PluginAPI.callExtendedApi and return value is passed back to the caller\n\t\t */\n\t\tApi.prototype.extendApi = function (group, name, action) {\n\t\t\tvar self = this;\n\t\t\tthis.request('extend-api', {\n\t\t\t\tgroup: group,\n\t\t\t\tname: name,\n\t\t\t\taction: function (data) {\n\t\t\t\t\tvar a = action(data.data);\n\t\t\t\t\tself.request(data.eventKey, {'data': a});\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\t\n\t\t/**\n\t\t * Call the extended PluginAPI\n\t\t *\n\t\t * @param {String} group Group name for functionality to call\n\t\t * @param {String} name Name of the specific function to call\n\t\t * @param {Object} data Data object to pass as parameter to the api call\n\t\t * @param {Function} callback function(Object) Function to recieve the API response, parameter is the response from the API call\n\t\t */\n\t\tApi.prototype.callExtendedApi = function (group, name, data, callback) {\n\t\t\tthis.request('call-extended-api', {\n\t\t\t\tgroup: group,\n\t\t\t\tname: name,\n\t\t\t\tdata: data,\n\t\t\t\tcallback: callback\n\t\t\t});\n\t\t};\n\t\n\t\t/**\n\t\t * Gets logged in user\n\t\t *\n\t\t * @param {Function} callback function(Object)\n\t\t */\n\t\tApi.prototype.getCurrentUser = function (callback) {\n\t\t\tthis.request('get-current-user', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Get configuration information about the app\n\t\t *\n\t\t * @param {Function} callback function(Object)\n\t\t */\n\t\tApi.prototype.getConfiguration = function (callback) {\n\t\t\tthis.request('get-configuration', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Get DrPublish configuratin\n\t\t *\n\t\t * @param {Function} callback function(Object)\n\t\t */\n\t\tApi.prototype.getDrPublishConfiguration = function (callback) {\n\t\t\tthis.request('get-drpublish-configuration', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Set configuration information about the app\n\t\t *\n\t\t * @param {Object} config The configuration object to save\n\t\t * @param {Object} options Object, can have three keys.\n\t\t * 'onlyPublication' (boolean) If true the configuration is set for the current publication only\n\t\t * 'success' (function) Called if the configuration was saved successfully\n\t\t * 'error' (function) Called if there was an error, recieves and error object as first parameter\n\t\t * @param {Function} callback function()\n\t\t */\n\t\tApi.prototype.setConfiguration = function (config, options, callback) {\n\t\t\t// support old function signature\n\t\t\tif (typeof options === 'boolean') {\n\t\t\t\toptions = {\n\t\t\t\t\tonlyPublication: options\n\t\t\t\t};\n\t\t\t} else if (typeof options !== 'object' || options === null) {\n\t\t\t\toptions = {};\n\t\t\t}\n\t\t\tvar data = {\n\t\t\t\tconfig: config,\n\t\t\t\tonlyPublication: typeof options.onlyPublication === 'boolean' ? options.onlyPublication : false,\n\t\t\t\tsuccess: typeof options.success === 'function' ? options.success : null,\n\t\t\t\terror: typeof options.error === 'function' ? options.error : null\n\t\t\t};\n\t\t\tthis.request('set-configuration', data, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Emits an event to DrPublish, and possibly other apps\n\t\t *\n\t\t * @param {String} name Name of the event\n\t\t * @param {String} data Data object to send with the event\n\t\t */\n\t\tApi.prototype.emit = function (name, data) {\n\t\t\tthis.request('emit-api-event', {\n\t\t\t\tname: name,\n\t\t\t\tdata: data\n\t\t\t});\n\t\t};\n\t\n\t\t/**\n\t\t * Listen for an event. If the callback returns false the event may cancel continued actions, e.g beforeSave can cancel article save. Look at documentation for Listeners to learn more.\n\t\t *\n\t\t * @param {String} name Name of the event\n\t\t * @param {Function} callback function(Object) Function to call when the event is triggered. Recieves one data object parameter of the form {source: , data: }\n\t\t */\n\t\tApi.prototype.on = function (name, callback) {\n\t\t\tvar self = this;\n\t\t\tself.eventListeners.add(name, callback);\n\t\t\tthis.request('on-api-event', {\n\t\t\t\tname: name\n\t\t\t});\n\t\t};\n\t\n\t\t/**\n\t\t * Increase the counter of actions required by the user, used to tell the user that the plugin requires input of some kind\n\t\t *\n\t\t * @param {Function} callback function(Object) function to call once the counter has been increased, returns the new counter value\n\t\t */\n\t\tApi.prototype.increaseRequiredActionCounter = function (callback) {\n\t\t\tthis.request('increase-required-action-counter', {}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Decrease the counter of actions required by the user, used to tell the user that the plugin requires input of some kind\n\t\t *\n\t\t * @param {Function} callback function(Object) function to call once the counter has been decrease, returns current counter value\n\t\t */\n\t\tApi.prototype.decreaseRequiredActionCounter = function (callback) {\n\t\t\tthis.request('decrease-required-action-counter', {}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Clear the counter of actions required by the user, used to tell the user that the plugin requires input of some kind\n\t\t *\n\t\t * @param {Function} callback function(Object) function to call once the counter has been cleared\n\t\t */\n\t\tApi.prototype.clearRequiredActionCounter = function (callback) {\n\t\t\tthis.request('clear-required-action-counter', {}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Set the counter of actions required by the user, used to tell the user that the plugin requires input of some kind\n\t\t *\n\t\t * @param {Number} count The value to set the counter to\n\t\t * @param {Function} callback function(Object) function to call once the counter has been cleared\n\t\t */\n\t\tApi.prototype.setRequiredActionCounter = function (count, callback) {\n\t\t\tthis.request('set-required-action-counter', {count: count}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Create a new instance of the Api class\n\t\t * @private\n\t\t * @return {Api}\n\t\t */\n\t\tApi.prototype.create = function () {\n\t\t\treturn new Api();\n\t\t};\n\t\n\t\t/**\n\t\t * Create an embedded object of the given type\n\t\t *\n\t\t * @param {Number} typeId Type Id of the embedded object to create\n\t\t * @param {Function} callback function(embeddedObjectId) called once the object has been created, first parameter is the new embedded object id\n\t\t */\n\t\tApi.prototype.createEmbeddedObject = function (typeId, callback) {\n\t\t\tthis.request('create-embedded-object', {typeId: typeId, callback: callback});\n\t\t};\n\t\n\t\t/**\n\t\t * Get information about the available embedded object types\n\t\t *\n\t\t * @param {Function} callback function([Object]) recieves an array with objects describing the available embedded object types in the form of `{typeId: 'embedded object type id', cssClass: 'css class used to style the objects'}`\n\t\t */\n\t\tApi.prototype.getEmbeddedObjectTypes = function (callback) {\n\t\t\tthis.request('get-embedded-object-types', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Gives focus to another plugin\n\t\t *\n\t\t * @param {String} pluginName The name of the plugin to recieve focus\n\t\t * @param {Object} argument Optional option argument to pass along to the plugin recieving focus\n\t\t * @param {Boolean} start Flag to decide if the plugin should be started if it has not been loaded previously, default true\n\t\t * @return {Boolean}\n\t\t */\n\t\tApi.prototype.giveFocus = function (pluginName, argument, start) {\n\t\t\tif (typeof pluginName !== 'string' || pluginName === '') {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (typeof start !== 'boolean') {\n\t\t\t\tstart = true;\n\t\t\t}\n\t\t\tthis.request('give-focus', {pluginName: pluginName, start: start, argument: argument});\n\t\t\treturn true;\n\t\t};\n\t\n\t\n\t\t/**\n\t\t * Hide the plugin, so it is no longer visible on the list of open plugins\n\t\t * @return {Boolean}\n\t\t */\n\t\tApi.prototype.hide = function () {\n\t\t\tthis.request('hide');\n\t\t\treturn true;\n\t\t};\n\t\n\t\t/**\n\t\t *

Creates a jQuery UI modal in the main editor window, detached from the plugin itself. Modals are unique on a\n\t\t * per-plugin basis, meaning that a plugin can only have a single modal at a time. Creating a new modal will\n\t\t * overwrite the previous.

\n\t\t *\n\t\t * See the official documentation for a list of available options.

\n\t\t *\n\t\t *

Note that you do not have direct access to the DOM of the modal. Use the provided helper methods to\n\t\t * manipulate or read from the modal:\n\t\t *

\n\t\t *

\n\t\t *\n\t\t * @example\n\t\t *\n\t\t * PluginAPI.createModal('

This is a modal

', {\n\t * buttons: {\n\t * Ok: function () {\n\t * alert('Ok!');\n\t * }\n\t * }\n\t * });\n\t\t *\n\t\t * PluginAPI.updateModal('

This is the same modal

');\n\t\t *\n\t\t * PluginAPI.createModal('

This is a brand new modal

', {\n\t * buttons: {\n\t * cancel: function() {\n\t * PluginAPI.closeModal(true);\n\t * }\n\t * }\n\t * });\n\t\t *\n\t\t * @param {String} content An HTML string\n\t\t * @param {Object} options A standard jQuery UI options object.\n\t\t * @return {Boolean}\n\t\t */\n\t\tApi.prototype.createModal = function (content, options) {\n\t\t\tthis.request('create-custom-modal', {content: content, options: options});\n\t\t\treturn true;\n\t\t};\n\t\n\t\t/**\n\t\t * Updates the HTML content of a live modal. Has no effect if the modal does not exist.\n\t\t *\n\t\t * @param {String} content An HTML string\n\t\t * @return {Boolean}\n\t\t */\n\t\tApi.prototype.updateModal = function (content) {\n\t\t\tthis.request('update-custom-modal', {content: content});\n\t\t\treturn true;\n\t\t};\n\t\n\t\t/**\n\t\t * Closes and optionally deletes the modal. Has no effect if the modal does not exists.\n\t\t *\n\t\t * @param {Boolean} destroy Whether or not to delete the modal\n\t\t * @return {Boolean}\n\t\t */\n\t\tApi.prototype.closeModal = function (destroy) {\n\t\t\tthis.request('close-custom-modal', {destroy: destroy});\n\t\t\treturn true;\n\t\t};\n\t\n\t\t/**\n\t\t * Returns the values of all input or select elements within a modal.\n\t\t *\n\t\t * The values are keyed by one of the following properties in order of priority: element ID, element name\n\t\t * or input type + index.\n\t\t *\n\t\t * @example\n\t\t * Given a modal with the following HTML content:\n\t\t *\n\t\t *
\n\t\t * \n\t\t * \n\t\t * \n\t\t *
\n\t\t *\n\t\t * getModalInputs would return:\n\t\t *\n\t\t * {\n\t * \"number-0\": {VALUE}\n\t * \"name\": {VALUE},\n\t * \"languages\": \"en\"\n\t * }\n\t\t *\n\t\t * @param {Function} callback\n\t\t */\n\t\tApi.prototype.getModalInputs = function (callback) {\n\t\t\tthis.request('get-custom-modal-inputs', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * unlocks the plugin after authentication. In order to use the plugin, calling this method is required\n\t\t * for all plugins having a secret defined within the publication config.\n\t\t *\n\t\t */\n\t\tApi.prototype.confirmAuthenticated = function () {\n\t\t\tthis.request('confirm-authenticated', {\n\t\t\t\tpluginName: this.appName\n\t\t\t});\n\t\t};\n\t\n\t\treturn new Api();\n\t})();\n\t\n\t\n\tPluginAPI.Article = articleCommunicator(PluginAPI);\n\tPluginAPI.Editor = ah5Communicator(PluginAPI);\n\t\n\tmodule.exports = PluginAPI;\n\n\n/***/ },\n/* 1 */\n/***/ function(module, exports) {\n\n\t'use strict';\n\t\n\t/**\n\t * @param {Api} PluginAPI\n\t * @return {ArticleCommunicator}\n\t */\n\tmodule.exports = function (PluginAPI) {\n\t\t/**\n\t\t * This class is used for communicating with the article, typically setting and getting values of metadata or in the article content itself.\n\t\t *\n\t\t * @class\n\t\t * @classdesc Functions for talking with the DrPublish article object. Accessed through PluginAPI.Article\n\t\t * @exports PluginAPI/Article\n\t\t */\n\t\n\t /* eslint max-statements: [\"error\", 50, { \"ignoreTopLevelFunctions\": true }]*/\n\t\tvar ArticleCommunicator = function () {\n\t\t\tthis.DEBUG = false;\n\t\t};\n\t\n\t\t/**\n\t\t * Give focus to yourself\n\t\t *\n\t\t * @param {Function} callback function(Boolean), called as the app gets focus\n\t\t */\n\t\tArticleCommunicator.prototype.focusApp = function (callback) {\n\t\t\tPluginAPI.request('app-focus', {}, callback);\n\t\t};\n\t\t/**\n\t\t * Start the given app\n\t\t *\n\t\t * @param {String} name Name of the app from settings.php\n\t\t * @param {Object} options Options for initializing the app\n\t\t * @param {Function} callback function(Boolean), called after app is started\n\t\t */\n\t\tArticleCommunicator.prototype.startApp = function (name, options, callback) {\n\t\t\tPluginAPI.request('app-start', {\n\t\t\t\tapp: name,\n\t\t\t\toption: options\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Stop the given app\n\t\t *\n\t\t * @param {String} name Name of the app from settings.php\n\t\t */\n\t\tArticleCommunicator.prototype.stopApp = function (name) {\n\t\t\tPluginAPI.request('app-stop', {\n\t\t\t\tapp: name\n\t\t\t});\n\t\t};\n\t\n\t\t/**\n\t\t * Get the id of the article currently edited\n\t\t *\n\t\t * @param {Function} callback function(Int), id of the current article\n\t\t */\n\t\tArticleCommunicator.prototype.getId = function (callback) {\n\t\t\tPluginAPI.request('article-id-get', null, callback);\n\t\t};\n\t\n\t\n\t\t/**\n\t\t * Get the guid of the article package currently edited\n\t\t *\n\t\t * @param {Function} callback function(Int), id of the current article\n\t\t */\n\t\tArticleCommunicator.prototype.getPackageId = function (callback) {\n\t\t\tPluginAPI.request('package-id-get', null, callback);\n\t\t};\n\t\n\t\n\t\t/**\n\t\t * Get the guid of the article package currently edited\n\t\t *\n\t\t * @param {Function} callback function(Int), id of the current article\n\t\t */\n\t\tArticleCommunicator.prototype.getPackageGuid = function (callback) {\n\t\t\tPluginAPI.request('package-guid-get', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Clear the meta information summary\n\t\t *\n\t\t * @param {Function} callback function(Boolean), called when meta data has been cleared\n\t\t */\n\t\tArticleCommunicator.prototype.clearMetaInfo = function (callback) {\n\t\t\tPluginAPI.request('article-metainfo-clear', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Get tags used in the article\n\t\t *\n\t\t * @param {Function} callback function([Object Tag]), array with tags connected to an article\n\t\t */\n\t\tArticleCommunicator.prototype.getTags = function (callback) {\n\t\t\tPluginAPI.request('article-tags-get', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Retrieve custom meta value for the article\n\t\t *\n\t\t * @param {String} name Name of the custom meta value\n\t\t * @param {Function} callback function(Object), the parameter is an object containing the given custom meta value\n\t\t */\n\t\tArticleCommunicator.prototype.getCustomMeta = function (name, callback) {\n\t\t\tPluginAPI.request('article-custom-meta-get', {\n\t\t\t\tname: name\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Set custom meta value for the article\n\t\t *\n\t\t * @param {String} name Name of the meta value\n\t\t * @param {Object} value Value to set\n\t\t * @param {Function} callback function()\n\t\t */\n\t\tArticleCommunicator.prototype.setCustomMeta = function (name, value, callback) {\n\t\t\tPluginAPI.request('article-custom-meta-set', {\n\t\t\t\tname: name,\n\t\t\t\tvalue: value\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Set tags for the article\n\t\t *\n\t\t * @param {Array} tags List of tags that should be set\n\t\t * @param {Boolean} save Set to true to force save once the tags are updated\n\t\t * @param {Function} callback function(Boolean), called when tags have been set\n\t\t */\n\t\tArticleCommunicator.prototype.setTags = function (tags, save, callback) {\n\t\t\tPluginAPI.request('article-tags-set', {\n\t\t\t\tsave: save,\n\t\t\t\ttags: tags\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Add tag for the article\n\t\t *\n\t\t * @param {String} tag Tag to be added\n\t\t * @param {Function} errorFunction called if error\n\t\t * @param {Function} callback function(Boolean), called when tag has been set\n\t\t */\n\t\tArticleCommunicator.prototype.addTag = function (tag, errorFunction, callback) {\n\t\t\tPluginAPI.request('article-tags-add', {\n\t\t\t\ttag: tag,\n\t\t\t\tonError: errorFunction\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Add tags for the article\n\t\t *\n\t\t * @param {String} tags Tags to be added\n\t\t * @param {Function} errorFunction called if error\n\t\t * @param {Function} callback function(Boolean), called when tag has been set\n\t\t */\n\t\tArticleCommunicator.prototype.addTags = function (tags, errorFunction, callback) {\n\t\t\tPluginAPI.request('article-tags-add', {\n\t\t\t\ttags: tags,\n\t\t\t\tonError: errorFunction\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Remove tag from article\n\t\t *\n\t\t * @param {String} tag Tag to remove\n\t\t * @param {Function} callback function(Boolean), called when tag has been removed\n\t\t */\n\t\tArticleCommunicator.prototype.removeTag = function (tag, callback) {\n\t\t\tPluginAPI.request('article-tags-remove', {\n\t\t\t\ttag: tag\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Get the selected categories\n\t\t *\n\t\t * @param {Function} callback function([String]), array with category ids\n\t\t */\n\t\tArticleCommunicator.prototype.getSelectedCategories = function (callback) {\n\t\t\tPluginAPI.request('article-categories-selected-get', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Save the currently selected categories\n\t\t *\n\t\t * @param {Function} callback function(Boolean), called when categories has been saved\n\t\t */\n\t\tArticleCommunicator.prototype.saveCategories = function (callback) {\n\t\t\tthis.getSelectedCategories(function (categories) {\n\t\t\t\tthis.setCategories(categories, callback);\n\t\t\t});\n\t\t};\n\t\n\t\t/**\n\t\t * Set selected categories\n\t\t *\n\t\t * @param {Array} categories List of category IDs that should be set\n\t\t * @param {Function} callback function(Boolean), called when categories have been set\n\t\t */\n\t\tArticleCommunicator.prototype.setCategories = function (categories, callback) {\n\t\t\tPluginAPI.request('article-categories-selected-set', {\n\t\t\t\tcategories: categories\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Add the given categories to the list of categories\n\t\t *\n\t\t * @param {Array} categories List of category IDs to add\n\t\t * @param {Function} callback function(Boolean), called when the categories have been set\n\t\t */\n\t\tArticleCommunicator.prototype.addCategories = function (categories, callback) {\n\t\n\t\t\tPluginAPI.request('article-categories-add', {\n\t\t\t\tcategories: categories\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Remove the given categories from the list of categories\n\t\t *\n\t\t * @param {Array} categories List of category IDs to remove\n\t\t * @param {Function} callback function(Boolean), called when the categories have been removed\n\t\t */\n\t\tArticleCommunicator.prototype.removeCategories = function (categories, callback) {\n\t\t\tPluginAPI.request('article-categories-remove', {\n\t\t\t\tcategories: categories\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Set the main category of the current article\n\t\t *\n\t\t * @param {Number} category The ID of the category to set as the main category\n\t\t * @param {Function} callback function(Boolean), called when the main category has been set\n\t\t */\n\t\tArticleCommunicator.prototype.setMainCategory = function (category, callback) {\n\t\t\tPluginAPI.request('article-categories-main-set', {\n\t\t\t\tcategory: category\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Get the source set for the article\n\t\t *\n\t\t * @param {Function} callback function(String), name of the source\n\t\t */\n\t\tArticleCommunicator.prototype.getSource = function (callback) {\n\t\n\t\t\tPluginAPI.request('article-source-get', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Set the source for the article\n\t\t *\n\t\t * @param {String} value The new value to be set as source\n\t\t * @param {Function} callback function(Boolean), called when the source has been set\n\t\t */\n\t\tArticleCommunicator.prototype.setSource = function (value, callback) {\n\t\t\tPluginAPI.request('article-source-set', {\n\t\t\t\tsource: value\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Get the status for the article\n\t\t *\n\t\t * @param {Function} callback function(String), current status\n\t\t */\n\t\tArticleCommunicator.prototype.getStatus = function (callback) {\n\t\t\tPluginAPI.request('article-status-get', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Set the status for the article\n\t\t *\n\t\t * @param {String} status The new status to be set (draft, waiting, published)\n\t\t * @param {Function} callback function(Boolean), called when the source has been set\n\t\t */\n\t\tArticleCommunicator.prototype.setStatus = function (status, callback) {\n\t\t\tPluginAPI.request('article-status-set', {\n\t\t\t\tstatus: status\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Get the published-date\n\t\t *\n\t\t * @param {Function} callback function(String), current published datetime\n\t\t */\n\t\tArticleCommunicator.prototype.getPublishedDatetime = function (callback) {\n\t\t\tPluginAPI.request('article-published-get', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Set the published-date\n\t\t *\n\t\t * @param {String} published Date to be set (YYYY-MM-DD HH:MM:SS)\n\t\t * @param {Function} callback function(Boolean), called when done\n\t\t */\n\t\tArticleCommunicator.prototype.setPublishedDatetime = function (published, callback) {\n\t\t\tPluginAPI.request('article-published-set', {\n\t\t\t\tpublished: published\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Get the authors set in the article\n\t\t *\n\t\t * @param {Function} callback function([String]), currently set authors\n\t\t */\n\t\tArticleCommunicator.prototype.getAuthors = function (callback) {\n\t\t\tPluginAPI.request('article-authors-get', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Set authors for the article\n\t\t *\n\t\t * @param {Array} authors List of authors that should be set\n\t\t * @param {Function} callback function(Boolean), called when it has been set\n\t\t */\n\t\tArticleCommunicator.prototype.setAuthors = function (authors, callback) {\n\t\t\tPluginAPI.request('article-authors-set', {\n\t\t\t\tauthors: authors\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Add the given authors to the list of authors\n\t\t *\n\t\t * @param {Array} authors List of authors to add\n\t\t * @param {Function} callback function(Boolean), called when it has been set\n\t\t */\n\t\tArticleCommunicator.prototype.addAuthors = function (authors, callback) {\n\t\t\tPluginAPI.request('article-authors-add', {\n\t\t\t\tauthors: authors\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Remove the given authors from the list of authors\n\t\t *\n\t\t * @param {Array} authors List of authors to remove\n\t\t * @param {Function} callback function([String]), author list as it is after the authors has been removed\n\t\t */\n\t\tArticleCommunicator.prototype.removeAuthors = function (authors, callback) {\n\t\t\tPluginAPI.request('article-authors-remove', {\n\t\t\t\tauthors: authors\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Set the keyword-list on the article\n\t\t *\n\t\t * @param {Array} keywords List of keywords to add\n\t\t * @param {Function} callback Function to call when keywords have been set\n\t\t */\n\t\tArticleCommunicator.prototype.setKeywords = function (keywords, callback) {\n\t\t\tPluginAPI.request('article-keywords-set', {\n\t\t\t\tkeywords: keywords\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Get the current set of keywords on the article\n\t\t *\n\t\t * @param {Function} callback Function to call with the result\n\t\t */\n\t\tArticleCommunicator.prototype.getKeywords = function (callback) {\n\t\t\tPluginAPI.request('article-keywords-get', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Gets the current article content\n\t\t *\n\t\t * @param {Function} callback function(Object Content)\n\t\t */\n\t\tArticleCommunicator.prototype.getCurrentContent = function (callback) {\n\t\t\tPluginAPI.request('article-content-get', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Updates current article content\n\t\t *\n\t\t * @param {String} content The new content for the article\n\t\t * @param {Function} callback function(Boolean), called when it has been set\n\t\t */\n\t\tArticleCommunicator.prototype.setCurrentContent = function (content, callback) {\n\t\t\tPluginAPI.request('article-content-set', {\n\t\t\t\tcontent: content\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Get the article type of the current article\n\t\t *\n\t\t * @param {Function} callback function(Int)\n\t\t */\n\t\tArticleCommunicator.prototype.getArticletypeId = function (callback) {\n\t\t\tPluginAPI.request('article-type-get', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Set the article type of the current article\n\t\t *\n\t\t * @param {Number} articletypeId The new article type of the article\n\t\t * @param {Function} callback function(Boolean), called when it has been set\n\t\t */\n\t\tArticleCommunicator.prototype.setArticletypeId = function (articletypeId, callback) {\n\t\t\tPluginAPI.request('article-type-set', {\n\t\t\t\tarticletype: articletypeId\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Maximize the app view\n\t\t *\n\t\t * @param {String} title Title to give the maximized view\n\t\t * @param {function} onClose Function to call when the window is closed/minimized\n\t\t */\n\t\tArticleCommunicator.prototype.maximizeAppWindow = function (title, onClose) {\n\t\t\tvar event = 'editor-pane-close-' + new Date().getTime();\n\t\n\t\t\tPluginAPI.request('editor-pane-maximize', {\n\t\t\t\ttitle: title,\n\t\t\t\tevent: event\n\t\t\t});\n\t\t\tPluginAPI.eventListeners.removeAll(event);\n\t\t\tPluginAPI.eventListeners.add(event, onClose);\n\t\t};\n\t\n\t\t/**\n\t\t * Restore the app pane to the default size\n\t\t *\n\t\t * @param {function} callback Callback to call after everything is done\n\t\t */\n\t\tArticleCommunicator.prototype.restoreAppWindow = function (callback) {\n\t\t\tPluginAPI.request('restore-app-window', {}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Get the current byline\n\t\t *\n\t\t * @param {function} callback function(String), xml string with the current byline\n\t\t */\n\t\tArticleCommunicator.prototype.getByline = function (callback) {\n\t\t\tPluginAPI.request('article-byline-get', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Set the byline\n\t\t *\n\t\t * @param {String} byline XML version of byline to use\n\t\t * @param {Boolean} save If true, force save after updating byline information\n\t\t * @param {Function} callback function(Boolean), called when it has been set\n\t\t */\n\t\tArticleCommunicator.prototype.setByline = function (byline, save, callback) {\n\t\t\tPluginAPI.request('article-byline-set', {\n\t\t\t\tsave: save,\n\t\t\t\tbyline: byline\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Set geolocation\n\t\t *\n\t\t * @param {Object} geolocations The location to set\n\t\t * @param {Function} callback function(Boolean), called when it has been set\n\t\t */\n\t\tArticleCommunicator.prototype.setGeolocations = function (geolocations, callback) {\n\t\t\tPluginAPI.request('article-geolocations-set', {\n\t\t\t\tgeolocations: geolocations\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Get geolocation\n\t\t *\n\t\t * @param {Function} callback function(Object), retrieves the currently set geo location\n\t\t */\n\t\tArticleCommunicator.prototype.getGeolocations = function (callback) {\n\t\t\tPluginAPI.request('article-geolocations-get', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Fetches a list of all properties available to an article.\n\t\t *\n\t\t * @param {Function} callback Callback called with an array of property objects.\n\t\t */\n\t\tArticleCommunicator.prototype.getProperties = function (callback) {\n\t\t\tPluginAPI.request('article-properties-get', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Updates and saves one or more property values. The input is a simple object with property names and their\n\t\t * new value. The supplied callback is called with an updated list of properties.\n\t\t *\n\t\t * @example\n\t\t * PluginAPI.Article.setProperties({\n\t * fooProperty: \"bar\",\n\t * barProperty: \"foo\"\n\t * }, function(properties) {\n\t * // Returns a complete and updated list of properties.\n\t * })\n\t\t *\n\t\t * @param {Object} properties An object of property names and corresponding values.\n\t\t * @param {Function} callback Callback called with an updated list of properties.\n\t\t */\n\t\tArticleCommunicator.prototype.setProperties = function (properties, callback) {\n\t\t\tPluginAPI.request('article-properties-set', {\n\t\t\t\tproperties: properties\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Updates and saves a single property.\n\t\t *\n\t\t * @param {String} name The property to update.\n\t\t * @param {String} value The updated value.\n\t\t * @param {Function} callback Callback called with an updated list of properties.\n\t\t */\n\t\tArticleCommunicator.prototype.setProperty = function (name, value, callback) {\n\t\t\tvar data = {};\n\t\t\tdata[name] = value;\n\t\t\tPluginAPI.request('article-properties-set', {\n\t\t\t\tproperties: data\n\t\t\t}, callback);\n\t\t};\n\t\n\t\tArticleCommunicator.prototype.getTopic = function (callback) {\n\t\t\tPluginAPI.request('article-topic-get', null, callback);\n\t\t};\n\t\n\t\tArticleCommunicator.prototype.setTopic = function (name, callback) {\n\t\t\tPluginAPI.request('article-topic-set', {\n\t\t\t\ttopic: name\n\t\t\t}, callback);\n\t\t};\n\t\n\t\treturn new ArticleCommunicator();\n\t};\n\n\n/***/ },\n/* 2 */\n/***/ function(module, exports) {\n\n\t'use strict';\n\t\n\t/**\n\t * @typedef {Object} selectedPluginElementData\n\t *\n\t * @property {String} id The DOM id of the selected element\n\t * @property {String} dpArticleId\n\t * @property {String} externalId\n\t * @property {Boolean} isDigitalAsset\n\t */\n\t\n\t/**\n\t * @param {Api} PluginAPI\n\t * @return {AH5Communicator}\n\t */\n\tmodule.exports = function (PluginAPI) {\n\t\n\t\t/** @type {selectedPluginElementData|null} */\n\t\tvar selectedPluginElement = null;\n\t\n\t\t/**\n\t\t * This will be used by editor apps to communicate with the editor\n\t\t *\n\t\t * Should be used like this:\n\t\t *\n\t\t * PluginAPI.Editor.insertString('string');\n\t\t *\n\t\t * @class\n\t\t * @classdesc Functions for talking with the AH5 editor. Accessed through PluginAPI.Editor\n\t\t * @exports PluginAPI/Editor\n\t\t */\n\t\t/* eslint max-statements: [\"error\", 50, { \"ignoreTopLevelFunctions\": true }]*/\n\t\tvar AH5Communicator = function () {\n\t\t\tthis.DEBUG = false;\n\t\t\tPluginAPI.on('pluginElementClicked', pluginElementSelected);\n\t\t\tPluginAPI.on('pluginElementDeselected', pluginElementDeselected);\n\t\n\t\t\t/**\n\t\t\t * @param {selectedPluginElementData} elementData\n\t\t\t */\n\t\t\tfunction pluginElementSelected(elementData) {\n\t\t\t\tselectedPluginElement = elementData;\n\t\t\t}\n\t\n\t\t\tfunction pluginElementDeselected() {\n\t\t\t\tselectedPluginElement = null;\n\t\t\t}\n\t\t};\n\t\n\t\t/**\n\t\t * Get name of current active editor\n\t\t *\n\t\t * @param {function} callback function(String)\n\t\t */\n\t\tAH5Communicator.prototype.getActiveEditor = function (callback) {\n\t\t\tPluginAPI.request('get-active-editor', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Registers/Modifies a context menu items for a app element\n\t\t * The object send should have the following structure\n\t\t *\n\t\t * @param {Object} action The action object\n\t\t * @param {function} callback function()\n\t\t *\n\t\t * @example\n\t\t * PluginAPI.Editor.registerMenuAction({\n\t\t *\t label: 'label in the menu',\n\t\t *\t icon: '[Optional] url to possible icon image',\n\t\t *\t trigger: '[Optional] css selector, only show menu element when this matches the element',\n\t\t *\t callback: function(id, clickedElementId) {\n\t\t *\t\t // callback function\n\t\t *\t\t // first parameter is id of the app element\n\t\t *\t\t // second paramter is id of closest element to the trigger element that has an id\n\t\t *\t\t //\t in code: $(event.triggerElement).closest('[id]').attr('id');\n\t\t *\t }\n\t\t * })\n\t\t */\n\t\tAH5Communicator.prototype.registerMenuAction = function (action, callback) {\n\t\t\tPluginAPI.request('register-menu-action', action, callback);\n\t\t};\n\t\n\t\n\t\tAH5Communicator.prototype.registerHoverAction = function (action, callback) {\n\t\t\tPluginAPI.request('register-hover-action', action, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Swap positions between the provided element and the adjacent one\n\t\t * in the specified direction\n\t\t * PluginAPI.Editor.directionalCastle({\n\t\t * elementId: 'the provided element id',\n\t\t * direction: 'forward/backward'\n\t\t * })\n\t\t * @param {String} movement Direction\n\t\t * @param {Function} callback\n\t\t * */\n\t\tAH5Communicator.prototype.directionalCastle = function (movement, callback) {\n\t\t\tPluginAPI.request('editor-directional-castle', movement, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Registers/Modifies a group of items to in the context menu\n\t\t * The object send should have the following structure\n\t\t *\n\t\t * @example\n\t\t * PluginAPI.Editor.registerMenuActionGroup({\n\t\t *\t label: 'label for the group in the menu',\n\t\t *\t icon: '[Optional] url to possible icon image',\n\t\t *\t actions: [\n\t\t *\t\t {\n\t\t *\t\t\t label: 'label for the action #1',\n\t\t *\t\t\t callback: function(id, clickedElementId) {\n\t\t *\t\t\t\t // same as for registerMenuAction\n\t\t *\t\t\t }\n\t\t *\t\t },\n\t\t *\t\t {\n\t\t *\t\t\t label: 'label for the action #2',\n\t\t *\t\t\t callback: function(id, clickedElementId) {\n\t\t *\t\t\t\t // same as for registerMenuAction\n\t\t *\t\t\t }\n\t\t *\t\t }\n\t\t *\t ]\n\t\t * })\n\t\t *\n\t\t * @param {Object} group The action object\n\t\t * @param {function} callback function()\n\t\t */\n\t\tAH5Communicator.prototype.registerMenuActionGroup = function (group, callback) {\n\t\t\tPluginAPI.request('register-menu-action-group', group, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Retrieves the type of editor that currently has focus\n\t\t *\n\t\t * @param {function} callback function(String)\n\t\t */\n\t\tAH5Communicator.prototype.getEditorType = function (callback) {\n\t\t\tPluginAPI.request('editor-get-type', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Replace an element in the article\n\t\t *\n\t\t * @param {String} id Id of the element\n\t\t * @param {String} element The new element\n\t\t * @param {function} callback function(Boolean), called after replacement is done\n\t\t */\n\t\tAH5Communicator.prototype.replaceElementById = function (id, element, callback) {\n\t\t\tPluginAPI.request('editor-element-replace-byid', {\n\t\t\t\tid: id,\n\t\t\t\telement: element\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Replace a plugin element in the article\n\t\t *\n\t\t * @param {String} id Id of the element\n\t\t * @param {String} element The new element\n\t\t * @param {function} callback function(Boolean), called after replacement is done\n\t\t */\n\t\tAH5Communicator.prototype.replacePluginElementById = function (id, element, callback) {\n\t\t\tPluginAPI.request('editor-element-replace-plugin-element-byid', {\n\t\t\t\tid: id,\n\t\t\t\telement: element\n\t\t\t}, callback);\n\t\t};\n\t\n\t\n\t\t/**\n\t\t * Delete an element in the article\n\t\t *\n\t\t * @param {String} id Id of the element\n\t\t * @param {function} callback function(Boolean), called after deletion is done\n\t\t */\n\t\tAH5Communicator.prototype.deleteElementById = function (id, callback) {\n\t\t\tPluginAPI.request('editor-element-replace-byid', {\n\t\t\t\tid: id\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Get HTML code of an element\n\t\t *\n\t\t * @param {String} id The element id\n\t\t * @param {function} callback function(String), html content of the element\n\t\t */\n\t\tAH5Communicator.prototype.getHTMLById = function (id, callback) {\n\t\t\tPluginAPI.request('editor-element-get-byid', {\n\t\t\t\tid: id\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Get HTML code of all elements that match the selector\n\t\t *\n\t\t * @param {String} selector The CSS selector\n\t\t * @param {function} callback function([String]), html content of matching elements\n\t\t */\n\t\tAH5Communicator.prototype.getHTMLBySelector = function (selector, callback) {\n\t\t\tPluginAPI.request('editor-elements-get-byselector', {\n\t\t\t\tselector: selector\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Get all categories\n\t\t *\n\t\t * @param {Function} callback function([Object Category]), list of Category objects with id, name and pid\n\t\t */\n\t\tAH5Communicator.prototype.getCategories = function (callback) {\n\t\t\tPluginAPI.request('get-categories', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Returns all the parent categories of the given category\n\t\t *\n\t\t * @param {Object} category The category to find parents of\n\t\t * @param {Function} callback function([Object Category]), array of parent Category objects\n\t\t */\n\t\tAH5Communicator.prototype.getParentCategories = function (category, callback) {\n\t\t\tPluginAPI.request('get-parent-categories', category, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Returns all the parent elements that match the selector\n\t\t *\n\t\t * @param {String} id Id of element to find parents of\n\t\t * @param {String} selector Selector to filter parent elements with\n\t\t * @param {Function} callback function([String]), array of ids\n\t\t */\n\t\tAH5Communicator.prototype.getParentIds = function (id, selector, callback) {\n\t\t\tPluginAPI.request('get-parent-ids', {\n\t\t\t\tid: id,\n\t\t\t\tselector: selector\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Retrieve information about all tagtypes\n\t\t *\n\t\t * @param {Function} callback function([Object Tagtype]), array of tagtypes with id, name and config object\n\t\t */\n\t\tAH5Communicator.prototype.getTagTypes = function (callback) {\n\t\t\tPluginAPI.request('get-tag-types', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Get information about the given tagtype\n\t\t *\n\t\t * @param {String} id The element id\n\t\t * @param {Function} callback function(Object Tagtype), tagtype object with id, name and config object\n\t\t */\n\t\tAH5Communicator.prototype.getTagType = function (id, callback) {\n\t\t\tPluginAPI.request('get-tag-type', {\n\t\t\t\tid: id\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Clears the editor contents\n\t\t *\n\t\t * @param {Function} callback function(Boolean)\n\t\t */\n\t\tAH5Communicator.prototype.clear = function (callback) {\n\t\t\tPluginAPI.request('editor-clear', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Insert a string into the editor\n\t\t *\n\t\t * @param {String} string The string that should be inserted\n\t\t * @param {Function} callback function(String), id of the newly inserted element if it has one\n\t\t */\n\t\tAH5Communicator.prototype.insertString = function (string, callback) {\n\t\t\tPluginAPI.request('editor-insert-string', {\n\t\t\t\tstring: string\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Insert an element into the editor\n\t\t *\n\t\t * Note that the HTML of the element is what will be transferred, and nothing else!\n\t\t * The element will be given the class dp-app-element, and given a unique ID (if none is present)\n\t\t *\n\t\t * @param {Element} element The element that should be inserted\n\t\t * @param {Object/Function} options (can be omitted) Options object, supports option 'select' - set to true to automatically select the inserted element\n\t\t * @param {Function} [callback] function(String), id of the newly inserted element\n\t\t */\n\t\tAH5Communicator.prototype.insertElement = function (element, options, callback) {\n\t\t\tvar select = false;\n\t\t\tif (typeof options === 'object') {\n\t\t\t\toptions = options || {};\n\t\t\t\tselect = typeof options.select === 'boolean' ? options.select : false;\n\t\t\t} else if (typeof callback === 'undefined' && typeof options === 'function') {\n\t\t\t\tcallback = options;\n\t\t\t}\n\t\t\tPluginAPI.request('editor-insert-element', {\n\t\t\t\telement: element.outerHTML,\n\t\t\t\tselect: select\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Remove classes from the element an element in the article\n\t\t *\n\t\t * @param {String} id Id of the element\n\t\t * @param {Array} classes Array of class names\n\t\t * @param {function} callback function(Boolean)\n\t\t */\n\t\tAH5Communicator.prototype.removeClasses = function (id, classes, callback) {\n\t\t\tPluginAPI.request('editor-classes-remove', {\n\t\t\t\tid: id,\n\t\t\t\tclasses: classes\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Add new classes to an element\n\t\t *\n\t\t * @param {String} id Id of the element\n\t\t * @param {Array} classes Array of class names\n\t\t * @param {function} callback function(Boolean)\n\t\t */\n\t\tAH5Communicator.prototype.addClasses = function (id, classes, callback) {\n\t\t\tPluginAPI.request('editor-classes-add', {\n\t\t\t\tid: id,\n\t\t\t\tclasses: classes\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Mark an element as currently selected (green border with default styling)\n\t\t *\n\t\t * @param {String} id Id of the element\n\t\t * @param {function} callback function(Boolean)\n\t\t */\n\t\tAH5Communicator.prototype.markAsActive = function (id, callback) {\n\t\t\tPluginAPI.request('editor-mark-as-active', {\n\t\t\t\tid: id\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Sets the attribute of the element with the given ID to value\n\t\t *\n\t\t * @param {String} id The ID of the element to set the attribute on\n\t\t * @param {String} attribute The attribute to set\n\t\t * @param {String} value What to set the attribute to\n\t\t * @param {Function} callback function(Boolean)\n\t\t */\n\t\tAH5Communicator.prototype.setAttributeById = function (id, attribute, value, callback) {\n\t\t\tPluginAPI.request('editor-element-attribute-set-byid', {\n\t\t\t\tid: id,\n\t\t\t\tattribute: attribute,\n\t\t\t\tvalue: value\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Sets a style of the element with the given ID to value\n\t\t *\n\t\t * @param {String} id The ID of the element to set the attribute on\n\t\t * @param {String} attribute The style attribute to set\n\t\t * @param {String} value What to set the attribute to\n\t\t * @param {Function} callback function(Boolean)\n\t\t */\n\t\tAH5Communicator.prototype.setStyleById = function (id, attribute, value, callback) {\n\t\t\tPluginAPI.request('editor-element-style-set-byid', {\n\t\t\t\tid: id,\n\t\t\t\tattribute: attribute,\n\t\t\t\tvalue: value\n\t\t\t}, callback);\n\t\t};\n\t\n\t\n\t\t/**\n\t\t * Initialize pre registered menus\n\t\t *\n\t\t * Available options are: simplePluginMenu, editContext, deleteButton, floatButtons\n\t\t *\n\t\t * @param {Array} menus Array of menu names\n\t\t * @param {Function} callback function(Boolean)\n\t\t */\n\t\tAH5Communicator.prototype.initMenu = function (menus, callback) {\n\t\t\tPluginAPI.request('editor-initialize-menu', {\n\t\t\t\tmenus: menus\n\t\t\t}, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Opens the plugin editor for a given element.\n\t\t *\n\t\t * @param {String} id Plugin element ID\n\t\t */\n\t\tAH5Communicator.prototype.openPluginElementEditor = function (id) {\n\t\t\tPluginAPI.request('open-element-editor', {\n\t\t\t\tid: id\n\t\t\t});\n\t\t};\n\t\n\t\t/**\n\t\t * Returns the total number of words in the currently open article.\n\t\t *\n\t\t * @param {Function} callback Receives the total word count as its single parameter\n\t\t */\n\t\tAH5Communicator.prototype.getTotalWordCount = function (callback) {\n\t\t\tPluginAPI.request('total-word-count', null, callback);\n\t\t};\n\t\n\t\t/**\n\t\t * Returns the total number of characters in the currently open article.\n\t\t *\n\t\t * @param {Function} callback Receives the total character count as its single parameter\n\t\t */\n\t\tAH5Communicator.prototype.getTotalCharCount = function (callback) {\n\t\t\tPluginAPI.request('total-char-count', null, callback);\n\t\t};\n\t\n\t\tAH5Communicator.prototype.updateAssetOption = function (dpArticleId, key, value, callback) {\n\t\t\tPluginAPI.request('update-asset-option', {dpArticleId: dpArticleId, key: key, value: value}, callback);\n\t\t};\n\t\n\t\tAH5Communicator.prototype.updateAssetData = function (data, callback) {\n\t\t\tPluginAPI.request('update-asset-media', data, callback);\n\t\t};\n\t\n\t\tAH5Communicator.prototype.getAssetData = function (dpArticleId, callback) {\n\t\t\tPluginAPI.request('get-asset-data', {data: dpArticleId}, callback);\n\t\t};\n\t\n\t\tAH5Communicator.prototype.insertNestedAsset = function (parentElementId, markup, data, callback) {\n\t\t\tvar self = this;\n\t\t\tPluginAPI.createEmbeddedObject(\n\t\t\t\tdata.embeddedTypeId,\n\t\t\t\tfunction (dpArticleId) {\n\t\t\t\t\tinsert(dpArticleId, parentElementId, function (data) {\n\t\t\t\t\t\treturn updateEmbeddedAssetRequest(callback);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t);\n\t\n\t\t\tfunction insert(dpArticleId, parentElementId, callback) {\n\t\t\t\tdata.internalId = dpArticleId;\n\t\t\t\tvar elementId = 'asset-' + dpArticleId;\n\t\t\t\tvar $element = $('
');\n\t\t\t\t$element.attr('id', elementId);\n\t\t\t\t$element.attr('data-internalId', dpArticleId);\n\t\t\t\tif (data.externalId) {\n\t $element.attr('data-externalId', data.externalId);\n\t\t\t\t}\n\t\t\t\tif (data.assetClass) {\n\t\t\t\t\t$element.addClass(data.assetClass);\n\t\t\t\t}\n\t\t\t\t$element.addClass('dp-plugin-element');\n\t\t\t\t$element.html(markup);\n\t\t\t\tPluginAPI.Editor.getHTMLById(parentElementId, function (html) {\n\t\t\t\t\tvar d = document.createElement('div');\n\t\t\t\t\td.innerHTML = html;\n\t\t\t\t\td.firstChild.setAttribute('id', parentElementId + 'tmp');\n\t\t\t\t\tself.replacePluginElementById(parentElementId, d.innerHTML, function () {\n\t\t\t\t\t\td = document.createElement('div');\n\t\t\t\t\t\td.innerHTML = html;\n\t\t\t\t\t\tvar assetContainer = d.querySelector('.dp-fact-box-image, .dp-nested-asset-container');\n\t\t\t\t\t\tif (data.isMultiple) {\n\t\t\t\t\t\t\t$(assetContainer).append($element.get(0).outerHTML);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tassetContainer.innerHTML = $element.get(0).outerHTML;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tself.replacePluginElementById(parentElementId + 'tmp', d.innerHTML, callback);\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\t\n\t\t\tfunction updateEmbeddedAssetRequest(callback) {\n\t\t\t\tPluginAPI.request('update-embedded-asset', data, callback);\n\t\t\t}\n\t\t};\n\t\n\t\tAH5Communicator.prototype.insertEmbeddedAsset = function (markup, data, callback) {\n\t\t\tvar self = this;\n\t\t\tvar replaceElement = false;\n\t\t\tif (selectedPluginElement) {\n\t\t\t\tif (data.assetSource !== PluginAPI.getAppName()) {\n\t\t\t\t\tPluginAPI.showErrorMsg('Can\\'t update selected plugin element since it doesn\\'t belong to the \\'' + PluginAPI.getAppName() + '\\' plugin');\n\t\t\t\t\treturn;\n\t\t\t\t} else {\n\t\t\t\t\treplaceElement = true;\n\t\t\t\t}\n\t\t\t}\n\t\n\t\t\tif (selectedPluginElement) {\n\t\t\t\tvar dpArticleId = selectedPluginElement.dpArticleId;\n\t\t\t\tif (!dpArticleId) {\n\t\t\t\t\tthrow Error('Selected plugin element: expected dpArticleId not found (tried reading from attribute \\'data-internal-id\\')');\n\t\t\t\t}\n\t\t\t\tinsert(dpArticleId, function (data) {\n\t\t\t\t\treturn updateEmbeddedAssetRequest(typeof callback === 'function' ? callback(data) : null);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tPluginAPI.createEmbeddedObject(\n\t\t\t\t\tdata.embeddedTypeId,\n\t\t\t\t\tfunction (dpArticleId) {\n\t\t\t\t\t\tinsert(dpArticleId, function (data) {\n\t\t\t\t\t\t\treturn addEmbeddedAssetRequest(typeof callback === 'function' ? callback(data) : null);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t}\n\t\n\t\t\tfunction insert(dpArticleId, callback) {\n\t\t\t\tdata.internalId = dpArticleId;\n\t\t\t\tvar elementId = 'asset-' + dpArticleId;\n\t\t\t\tvar element = document.createElement('div');\n\t\t\t\telement.id = elementId;\n\t\t\t\telement.dataset.internalId = dpArticleId;\n\t\t\t\tif (data.externalId) {\n\t\t\t\t\telement.dataset.externalId = data.externalId;\n\t\t\t\t}\n\t\t\t\tif (data.assetClass) {\n\t\t\t\t\telement.classList.add(data.assetClass);\n\t\t\t\t}\n\t\t\t\telement.innerHTML = markup;\n\t\t\t\tif (!replaceElement) {\n\t\t\t\t\tself.insertElement(element, {select: true});\n\t\t\t\t} else {\n\t\t\t\t\tself.replaceElementById(elementId, element.outerHTML, null);\n\t\t\t\t}\n\t\t\t\tif (typeof callback === 'function') {\n\t\t\t\t\treturn callback();\n\t\t\t\t}\n\t\t\t}\n\t\n\t\t\tfunction addEmbeddedAssetRequest(callback) {\n\t\t\t\tPluginAPI.request('add-embedded-asset', data, callback);\n\t\t\t}\n\t\n\t\t\tfunction updateEmbeddedAssetRequest(callback) {\n\t\t\t\tPluginAPI.request('update-embedded-asset', data, callback);\n\t\t\t}\n\t\t};\n\t\n\t\tAH5Communicator.prototype.getSelectedPluginElement = function (callback) {\n\t\t\tPluginAPI.request('get-selected-plugin-element', {}, callback);\n\t\t};\n\t\n\t\treturn new AH5Communicator();\n\t};\n\n\n/***/ },\n/* 3 */\n/***/ function(module, exports) {\n\n\t'use strict';\n\t\n\tmodule.exports = Listeners;\n\t\n\t/**\n\t * @example\n\t * PluginAPI.on('afterCreate', function() {\n\t * PluginAPI.Article.setSource('Ny Times');\n\t * });\n\t * PluginAPI.on('beforeSave', function() {\n\t * if (!articleIsAwesome()) {\n\t * return false;\n\t * }\n\t * });\n\t *\n\t * @description\n\t *\n\t *

DrPublish provides a large set of default events that an app can listen for. All events that start their name with 'before' can be stopped by an app. This is done by returning 'false' from the callback function, as in the 'beforeSave' example given below.

\n\t *

Other apps can also supply their own events using the PluginAPI.emit(...) function. Documention on these events are up to each app to create.

\n\t *

Available Events

\n\t *

addCategory

\n\t *
\n\t *

triggered after a category has been added to the article

\n\t *
\n\t *

addTag

\n\t *
\n\t *

triggered after a tag had been added to the article

\n\t *
\n\t *

appPaneMaximized

\n\t *
\n\t *

triggered when the app pane is maximized

\n\t *
\n\t *

appPaneRestored

\n\t *
\n\t *

triggered when the app pane is restored to its' original size

\n\t *
\n\t *

appAuthenticated

\n\t *
\n\t *

triggered when an app has been authenticated

\n\t *
\n\t *

changedCustomMeta

\n\t *
\n\t *

triggered when a custom meta property is changed/set, parameter is an object with property name and value

\n\t *
\n\t *

receivedFocus

\n\t *
\n\t *

triggered when a plugin receives focus. Receives a parameter object that has two predefined values: previousPluginName - name of previous plugin, givenFocus - true when focus was sent from another plugin. The parameter object can also contain other keys supplied by the plugin losing focus.

\n\t *
\n\t *

afterCreate

\n\t *
\n\t *

triggered after a new article has been created

\n\t *
\n\t *

beforeDelete

\n\t *
\n\t *

triggered before an article is deleted

\n\t *
\n\t *

afterDelete

\n\t *
\n\t *

triggered after an article has been deleted

\n\t *
\n\t *

afterLoad

\n\t *
\n\t *

triggered after an article has been loaded

\n\t *
\n\t *

afterPublish

\n\t *
\n\t *

triggered after an article has been published

\n\t *
\n\t *

afterSave

\n\t *
\n\t *

triggered after an article has been saved

\n\t *
\n\t *

beforeCreate

\n\t *
\n\t *

triggered before a new article is created

\n\t *
\n\t *

beforeLoad

\n\t *
\n\t *

triggered before an article is loaded into the editor

\n\t *
\n\t *

beforePreview

\n\t *
\n\t *

triggered before the article is opened in the preview

\n\t *
\n\t *

beforeSave

\n\t *
\n\t *

triggered before an article is saved

\n\t *
\n\t *

beforePublish

\n\t *
\n\t *

triggered before an article is published

\n\t *
\n\t *

editorFocus

\n\t *
\n\t *

triggered when an editor gets focus

\n\t *
\n\t *

editorUnfocus

\n\t *
\n\t *

triggered when an editor loses focus

\n\t *
\n\t *

editorsLostFocus

\n\t *
\n\t *

triggered when all editors loses focus

\n\t *
\n\t *

editorReady

\n\t *
\n\t *

triggered when the editor has been fully loaded and is ready for input

\n\t *
\n\t *

modifiedContent

\n\t *
\n\t *

triggered whenever content changes in the article

\n\t *
\n\t *

elementRemoved

\n\t *
\n\t *

triggered when a plugin element from the current plugin is removed, receives an object with element id as a parameter

\n\t *
\n\t *

pluginElementClicked

\n\t *
\n\t *

triggered when someone clicks on a plugin element in the editor

\n\t *
\n\t *

pluginElementSelected

\n\t *
\n\t *

triggers when someone selects a plugin element in the editor

\n\t *
\n\t *

pluginElementDeselected

\n\t *
\n\t *

triggered when someone deselects a plugin element in the editor

\n\t *
\n\t */\n\tfunction Listeners() {\n\t\tthis._listeners = {};\n\t}\n\t\n\t/**\n\t * Adds a new listener\n\t *\n\t * @param {String} event Event name\n\t * @param {Function} callback Function to call when an even of the type is received\n\t * @return {int|undefined} The index of the new listener\n\t */\n\tListeners.prototype.add = function (event, callback) {\n\t\tif (typeof callback !== 'function') {\n\t\t\tthrow Error('Listener callback must be a function.');\n\t\t}\n\t\n\t\tif (this._listeners[event] === undefined) {\n\t\t\tthis._listeners[event] = [];\n\t\t}\n\t\n\t\tthis._listeners[event].push(callback);\n\t\treturn this._listeners[event].length - 1;\n\t};\n\t\n\t/**\n\t * Removes the listener at the given index\n\t *\n\t * @param {String} event Event type\n\t * @param {Function} index The index of the event handler to remove\n\t */\n\tListeners.prototype.remove = function (event, index) {\n\t\tif (this._listeners[event] === undefined || this._listeners[event][index] === undefined) {\n\t\t\treturn;\n\t\t}\n\t\n\t\t/*\n\t\t * Set to null instead of remove to retain callback indexes\n\t\t */\n\t\tthis._listeners[event][index] = false;\n\t};\n\t\n\t/**\n\t * Removes all listeners for the given event type, or if !event then removes all listeners\n\t *\n\t * @param {String} event Event type to remove handlers for (!event for all)\n\t */\n\tListeners.prototype.removeAll = function (event) {\n\t\tif (!event) {\n\t\t\tthis._listeners = [];\n\t\t} else {\n\t\t\tthis._listeners[event] = [];\n\t\t}\n\t};\n\t\n\t/**\n\t * Notifies all registered listeners that an event has occurred\n\t *\n\t * If the payload has a key `data`, the value of that field will be passed to listener. If not, the entire payload will\n\t * be passed on.\n\t *\n\t * @param {String} event Event type\n\t * @param {Object} payload The event data\n\t * @return {Boolean} Whether to continue with the action (for events named `before*`)\n\t */\n\tListeners.prototype.notify = function (event, payload) {\n\t\tvar returnValue = true;\n\t\tif (this._listeners[event] === undefined) {\n\t\t\treturn returnValue;\n\t\t}\n\t\n\t\t// If the payload is an object with a key data, we use that value as the payload we pass to the listener functions.\n\t\t// This is needed as we have some inconsistencies in how we pass data around. This normalization should preferably\n\t\t// be done at the call site.\n\t\tthis._listeners[event].forEach(function (listenerFn) {\n\t\t\tif (typeof listenerFn !== 'function') {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar res = null;\n\t\t\tif (payload && payload.params && payload.params === true) {\n\t\t\t\tres = listenerFn.apply(null, payload.data);\n\t\t\t} else if (typeof payload === 'object' && payload !== null && typeof payload.data !== 'undefined') {\n\t\t\t\tres = listenerFn(payload.data);\n\t\t\t} else {\n\t\t\t\tres = listenerFn(payload);\n\t\t\t}\n\t\t\tif (res === false) {\n\t\t\t\treturnValue = false;\n\t\t\t}\n\t\t});\n\t\treturn returnValue;\n\t};\n\n\n/***/ }\n/******/ ])\n});\n;\n\n\n/** WEBPACK FOOTER **\n ** bundle.js\n **/"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n/** WEBPACK FOOTER **\n ** webpack/bootstrap b7ce02d6d601da7cb8b9\n **/","/* global pm:false*/\n'use strict';\n\nvar articleCommunicator = require('./articleCommunicator');\nvar ah5Communicator = require('./AH5Communicator');\nvar Listeners = require('./Listeners');\n\n/**\n * @extends Api\n * @property {ArticleCommunicator} Article\n * @property {AH5Communicator} Editor\n */\n\n/* eslint max-statements: [\"error\", 50, { \"ignoreTopLevelFunctions\": true }]*/\nvar PluginAPI = (function () {\n\n\t/**\n\t *\n\t * Namespace for all public DrPublish methods available from apps.\n\t *\n\t * @class\n\t * @classdesc The basic API object\n\t * @exports PluginAPI\n\t *\n\t */\n\tvar Api = function () {\n\t\tthis.DEBUG = false;\n\n\t\tthis.Version = '3.0';\n\t\tthis.Editor = null;\n\t\tthis.Article = null;\n\t\tthis.errorListeners = new Listeners();\n\t\tthis.eventListeners = new Listeners();\n\t\tthis.appName = '';\n\n\t\tvar self = this;\n\n\t\tpm.bind('event', eventListener, '*');\n\n\t\t/**\n\t\t * @param {Object} event\n\t\t * @param {String} event.type\n\t\t * @param {*} event.data\n * @return {boolean|Object} True if none of listeners want to stop the processing\n */\n\t\tfunction eventListener(event) {\n\t\t\tvar continueProcessing = self.eventListeners.notify(\n\t\t\t\tevent.type,\n\t\t\t\tupdateObjectWithEventFunctions(event.data)\n\t\t\t);\n\n\t\t\tif (continueProcessing === false) {\n\t\t\t\treturn {abort: true};\n\t\t\t}\n\n\t\t\treturn true;\n\n\t\t\t/**\n\t\t\t * data can be be anything, but if it's an object, we'll iterate over the keys and look for any values\n\t\t\t * that should be treated as function calls.\n\t\t\t *\n\t\t\t * To be treated as a function call, the value must be an object where `type === 'function'`, and have a key\n\t\t\t * `eventKey` which is the event name that should be passed to `PluginAPI.request()`\n\t\t\t *\n\t\t\t * @param {*} data\n * @return {*}\n */\n\t\t\tfunction updateObjectWithEventFunctions(data) {\n\t\t\t\tfor (var key in data) {\n\t\t\t\t\tif (data.hasOwnProperty(key)) {\n\t\t\t\t\t\tif (typeof data[key] === 'object' && data[key] !== null && data[key].type === 'function') {\n\t\t\t\t\t\t\tdata[key] = createEventFunction(data[key].eventKey);\n\t\t\t\t\t\t} else if (typeof data[key] === 'object' && data[key] !== null && typeof data[key].map === 'function') {\n\t\t\t\t\t\t\tdata[key] = data[key].map(updateObjectWithEventFunctions);\n\t\t\t\t\t\t} else if (typeof data[key] === 'object' && data[key] !== null) {\n\t\t\t\t\t\t\tdata[key] = updateObjectWithEventFunctions(data[key]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn data;\n\t\t\t}\n\n\t\t\tfunction createEventFunction(eventName) {\n\t\t\t\treturn function (data) {\n\t\t\t\t\tPluginAPI.request(eventName, data);\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t};\n\n\t/**\n\t * Dispatches a request to DrPublish, and returns the reply to callback On error, notifies all error listeners based on the index .type of the thrown object\n\t *\n\t * @param {String} callSpec What do you want to call?\n\t * @param {Object} data The data attached to the request\n\t * @param {Function} [callback] The function to call upon return\n\t */\n\tApi.prototype.request = function (callSpec, data, callback) {\n\t\tvar self = this;\n\t\tif (this.DEBUG) {\n\t\t\tconsole.info(this.getAppName() + ': Requesting ' + callSpec + ' from parent with data', data);\n\t\t}\n\n\t\tif (!data) {\n\t\t\tdata = {};\n\t\t}\n\n\t\tif (typeof callback === 'undefined') {\n\t\t\tcallback = null;\n\t\t}\n\n\t\tif (typeof data.length === 'number') {\n\t\t\tdata = {data: data};\n\t\t}\n\n\t\t// eslint-disable-next-line camelcase\n\t\tdata.src_app = this.getAppName();\n\n\t\tvar createEventFunction = function (func, eventKey) {\n\t\t\treturn function () {\n\t\t\t\tself.eventListeners.remove(eventKey, eventKey);\n\t\t\t\treturn func.apply(null, arguments);\n\t\t\t};\n\t\t};\n\n\t\tvar createCallbackObject = function (key, callback) {\n\t\t\tvar random = Math.floor(Math.random() * 1000);\n\t\t\tvar eventKey = key + random + 'functioncallback' + (new Date()).getTime();\n\t\t\tvar eventFunction = createEventFunction(callback, eventKey);\n\t\t\tself.eventListeners.add(eventKey, eventFunction);\n\t\t\treturn {\n\t\t\t\ttype: 'function',\n\t\t\t\teventKey: eventKey\n\t\t\t};\n\t\t};\n\n\t\tvar updateObject = function (data) {\n\t\t\tfor (var key in data) {\n\t\t\t\tif (data.hasOwnProperty(key)) {\n\t\t\t\t\tvar val = data[key];\n\t\t\t\t\tif (typeof val === 'function') {\n\t\t\t\t\t\tdata[key] = createCallbackObject(key, val);\n\t\t\t\t\t} else if (typeof val === 'object' && val !== null && typeof val.map === 'function') {\n\t\t\t\t\t\tdata[key] = val.map(updateObject);\n\t\t\t\t\t} else if (typeof val === 'object' && val !== null) {\n\t\t\t\t\t\tdata[key] = updateObject(val);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn data;\n\t\t};\n\t\tdata = updateObject(data);\n\n\t\tpm({\n\t\t\ttarget: parent,\n\t\t\ttype: callSpec,\n\t\t\tdata: data,\n\t\t\tsuccess: callback,\n\t\t\terror: function (data) {\n\t\t\t\tself.errorListeners.notify(data.type, data);\n\t\t\t},\n\t\t\torigin: '*', // TODO: Find a way of avoiding all-origins\n\t\t\thash: false\n\t\t});\n\t};\n\n\n\t/**\n\t * Creates a new tag\n\t *\n\t * @param {String} tag The tag to create\n\t * @param {Function} callback function(Boolean)\n\t */\n\tApi.prototype.openTagCreationDialog = function (tag, callback) {\n\t\tthis.request('create-tag', {\n\t\t\ttag: tag\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Reloads the app's iframe\n\t */\n\tApi.prototype.reloadIframe = function () {\n\n\t\tthis.request('app-reload', {\n\t\t\tapp: this.getAppName()\n\t\t});\n\t};\n\n\t/**\n\t * Get the name of the loaded app\n\t *\n\t * @return {String} The name of the app, or false if it couldn't be detected\n\t */\n\tApi.prototype.getAppName = function () {\n\t\treturn this.appName;\n\t};\n\n\t/**\n\t * Set the name of the app\n\t *\n\t * @param {String} name The name of the app\n\t */\n\tApi.prototype.setAppName = function (name) {\n\t\tthis.appName = name;\n\t};\n\n\t/**\n\t * Show info-message to the user\n\t *\n\t * @param {String} msg Message to be displayed\n\t */\n\tApi.prototype.showInfoMsg = function (msg) {\n\n\t\tthis.request('show-message-info', {\n\t\t\tmessage: msg\n\t\t});\n\t};\n\n\t/**\n\t * Show warning-message to the user\n\t *\n\t * @param {String} msg Message to be displayed\n\t */\n\tApi.prototype.showWarningMsg = function (msg) {\n\n\t\tthis.request('show-message-warning', {\n\t\t\tmessage: msg\n\t\t});\n\t};\n\n\t/**\n\t * Show error-message to the user\n\t *\n\t * @param {String} msg Message to be displayed\n\t */\n\tApi.prototype.showErrorMsg = function (msg) {\n\n\t\tthis.request('show-message-error', {\n\t\t\tmessage: msg\n\t\t});\n\t};\n\n\t/**\n\t * Show the loader\n\t *\n\t * @param {String} msg Message to display in progress loader\n\t */\n\tApi.prototype.showLoader = function (msg) {\n\t\tthis.request('show-loader', {\n\t\t\tmessage: msg\n\t\t});\n\t};\n\n\t/**\n\t * Hide the loader\n\t */\n\tApi.prototype.hideLoader = function () {\n\t\tthis.request('hide-loader');\n\t};\n\n\t/**\n\t * Loads an old revision of an article\n\t *\n\t * @param {Number} id The id of the revision to load\n\t * @param {Function} callback The function to call when the new revision has been loaded\n\t * @private\n\t */\n\tApi.prototype.__loadArticleRevision = function (id, callback) {\n\t\tthis.request('load-revision', {\n\t\t\trevision: id\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Creates a new tag\n\t *\n\t * @param {String} tag JSON object with the tag to create, must contain tagTypeId and name properties\n\t * @param {Function} callback function(Boolean)\n\t */\n\tApi.prototype.createTag = function (tag, callback) {\n\t\tthis.request('tag-create', {\n\t\t\ttag: tag\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Sends a query to DrLib\n\t *\n\t * @example\n\t * PluginAPI.searchDrLib({\n * query: 'articles.json?q=awesome',\n * secure: true,\n * success: function(data) {\n * data.items.forEach(doStuffWithArticle);\n * },\n * error: function(data) {\n * console.warn('something went wrong');\n * }\n * })\n\t *\n\t * @param {Object} data Object with three properties; 'query' which is the query to send to DrLib, 'success' which is the callback to execute on success, and 'secure' a boolean to add the internal API key to the query and thus allow searching on unpublished article. This callback's parameter is an object which is the query result as an object. See the json output of DrLib to learn more about this object\n\t * @param {Function} callback function(Boolean)\n\t *\n\t */\n\tApi.prototype.searchDrLib = function (data, callback) {\n\t\tthis.request('drlib-search', {\n\t\t\tquery: data.query,\n\t\t\taccess: data.access,\n\t\t\tsecure: data.secure,\n\t\t\tsuccess: data.success,\n\t\t\terror: data.error\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Generates proper html code to represent the dom element. This is NOT an asynchronous function\n\t *\n\t * @param {Object|Element} element The dom node to convert\n\t * @return {String} The html code\n\t */\n\tApi.prototype.convertDomToHTML = function (element) {\n\t\t// Support for passing in a jQuery element\n\t\tif (typeof element === 'object' && typeof element.wrap === 'function') {\n\t\t\treturn element.wrap('
').parent().html();\n\t\t}\n\t\treturn element.outerHTML;\n\t};\n\n\t/**\n\t * Generates an url to a published article\n\t *\n\t * @param {String} id The id of the article to generate url for\n\t * @param {Function} callback function(String), where the parameter is the generated url\n\t */\n\tApi.prototype.generateArticleUrl = function (id, callback) {\n\t\tthis.request('generate-article-url', {\n\t\t\tid: id\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Extends the PluginAPI with custom functionality that other apps can use\n\t *\n\t * @param {String} group Group name for functionality to add\n\t * @param {String} name Name of the specific function to add\n\t * @param {Function} action function(Object) Function to call when the API is invoked, recieves one parameter as given in PluginAPI.callExtendedApi and return value is passed back to the caller\n\t */\n\tApi.prototype.extendApi = function (group, name, action) {\n\t\tvar self = this;\n\t\tthis.request('extend-api', {\n\t\t\tgroup: group,\n\t\t\tname: name,\n\t\t\taction: function (data) {\n\t\t\t\tvar a = action(data.data);\n\t\t\t\tself.request(data.eventKey, {'data': a});\n\t\t\t}\n\t\t});\n\t};\n\n\t/**\n\t * Call the extended PluginAPI\n\t *\n\t * @param {String} group Group name for functionality to call\n\t * @param {String} name Name of the specific function to call\n\t * @param {Object} data Data object to pass as parameter to the api call\n\t * @param {Function} callback function(Object) Function to recieve the API response, parameter is the response from the API call\n\t */\n\tApi.prototype.callExtendedApi = function (group, name, data, callback) {\n\t\tthis.request('call-extended-api', {\n\t\t\tgroup: group,\n\t\t\tname: name,\n\t\t\tdata: data,\n\t\t\tcallback: callback\n\t\t});\n\t};\n\n\t/**\n\t * Gets logged in user\n\t *\n\t * @param {Function} callback function(Object)\n\t */\n\tApi.prototype.getCurrentUser = function (callback) {\n\t\tthis.request('get-current-user', null, callback);\n\t};\n\n\t/**\n\t * Get configuration information about the app\n\t *\n\t * @param {Function} callback function(Object)\n\t */\n\tApi.prototype.getConfiguration = function (callback) {\n\t\tthis.request('get-configuration', null, callback);\n\t};\n\n\t/**\n\t * Get DrPublish configuratin\n\t *\n\t * @param {Function} callback function(Object)\n\t */\n\tApi.prototype.getDrPublishConfiguration = function (callback) {\n\t\tthis.request('get-drpublish-configuration', null, callback);\n\t};\n\n\t/**\n\t * Set configuration information about the app\n\t *\n\t * @param {Object} config The configuration object to save\n\t * @param {Object} options Object, can have three keys.\n\t * 'onlyPublication' (boolean) If true the configuration is set for the current publication only\n\t * 'success' (function) Called if the configuration was saved successfully\n\t * 'error' (function) Called if there was an error, recieves and error object as first parameter\n\t * @param {Function} callback function()\n\t */\n\tApi.prototype.setConfiguration = function (config, options, callback) {\n\t\t// support old function signature\n\t\tif (typeof options === 'boolean') {\n\t\t\toptions = {\n\t\t\t\tonlyPublication: options\n\t\t\t};\n\t\t} else if (typeof options !== 'object' || options === null) {\n\t\t\toptions = {};\n\t\t}\n\t\tvar data = {\n\t\t\tconfig: config,\n\t\t\tonlyPublication: typeof options.onlyPublication === 'boolean' ? options.onlyPublication : false,\n\t\t\tsuccess: typeof options.success === 'function' ? options.success : null,\n\t\t\terror: typeof options.error === 'function' ? options.error : null\n\t\t};\n\t\tthis.request('set-configuration', data, callback);\n\t};\n\n\t/**\n\t * Emits an event to DrPublish, and possibly other apps\n\t *\n\t * @param {String} name Name of the event\n\t * @param {String} data Data object to send with the event\n\t */\n\tApi.prototype.emit = function (name, data) {\n\t\tthis.request('emit-api-event', {\n\t\t\tname: name,\n\t\t\tdata: data\n\t\t});\n\t};\n\n\t/**\n\t * Listen for an event. If the callback returns false the event may cancel continued actions, e.g beforeSave can cancel article save. Look at documentation for Listeners to learn more.\n\t *\n\t * @param {String} name Name of the event\n\t * @param {Function} callback function(Object) Function to call when the event is triggered. Recieves one data object parameter of the form {source: , data: }\n\t */\n\tApi.prototype.on = function (name, callback) {\n\t\tvar self = this;\n\t\tself.eventListeners.add(name, callback);\n\t\tthis.request('on-api-event', {\n\t\t\tname: name\n\t\t});\n\t};\n\n\t/**\n\t * Increase the counter of actions required by the user, used to tell the user that the plugin requires input of some kind\n\t *\n\t * @param {Function} callback function(Object) function to call once the counter has been increased, returns the new counter value\n\t */\n\tApi.prototype.increaseRequiredActionCounter = function (callback) {\n\t\tthis.request('increase-required-action-counter', {}, callback);\n\t};\n\n\t/**\n\t * Decrease the counter of actions required by the user, used to tell the user that the plugin requires input of some kind\n\t *\n\t * @param {Function} callback function(Object) function to call once the counter has been decrease, returns current counter value\n\t */\n\tApi.prototype.decreaseRequiredActionCounter = function (callback) {\n\t\tthis.request('decrease-required-action-counter', {}, callback);\n\t};\n\n\t/**\n\t * Clear the counter of actions required by the user, used to tell the user that the plugin requires input of some kind\n\t *\n\t * @param {Function} callback function(Object) function to call once the counter has been cleared\n\t */\n\tApi.prototype.clearRequiredActionCounter = function (callback) {\n\t\tthis.request('clear-required-action-counter', {}, callback);\n\t};\n\n\t/**\n\t * Set the counter of actions required by the user, used to tell the user that the plugin requires input of some kind\n\t *\n\t * @param {Number} count The value to set the counter to\n\t * @param {Function} callback function(Object) function to call once the counter has been cleared\n\t */\n\tApi.prototype.setRequiredActionCounter = function (count, callback) {\n\t\tthis.request('set-required-action-counter', {count: count}, callback);\n\t};\n\n\t/**\n\t * Create a new instance of the Api class\n\t * @private\n\t * @return {Api}\n\t */\n\tApi.prototype.create = function () {\n\t\treturn new Api();\n\t};\n\n\t/**\n\t * Create an embedded object of the given type\n\t *\n\t * @param {Number} typeId Type Id of the embedded object to create\n\t * @param {Function} callback function(embeddedObjectId) called once the object has been created, first parameter is the new embedded object id\n\t */\n\tApi.prototype.createEmbeddedObject = function (typeId, callback) {\n\t\tthis.request('create-embedded-object', {typeId: typeId, callback: callback});\n\t};\n\n\t/**\n\t * Get information about the available embedded object types\n\t *\n\t * @param {Function} callback function([Object]) recieves an array with objects describing the available embedded object types in the form of `{typeId: 'embedded object type id', cssClass: 'css class used to style the objects'}`\n\t */\n\tApi.prototype.getEmbeddedObjectTypes = function (callback) {\n\t\tthis.request('get-embedded-object-types', null, callback);\n\t};\n\n\t/**\n\t * Gives focus to another plugin\n\t *\n\t * @param {String} pluginName The name of the plugin to recieve focus\n\t * @param {Object} argument Optional option argument to pass along to the plugin recieving focus\n\t * @param {Boolean} start Flag to decide if the plugin should be started if it has not been loaded previously, default true\n\t * @return {Boolean}\n\t */\n\tApi.prototype.giveFocus = function (pluginName, argument, start) {\n\t\tif (typeof pluginName !== 'string' || pluginName === '') {\n\t\t\treturn false;\n\t\t}\n\t\tif (typeof start !== 'boolean') {\n\t\t\tstart = true;\n\t\t}\n\t\tthis.request('give-focus', {pluginName: pluginName, start: start, argument: argument});\n\t\treturn true;\n\t};\n\n\n\t/**\n\t * Hide the plugin, so it is no longer visible on the list of open plugins\n\t * @return {Boolean}\n\t */\n\tApi.prototype.hide = function () {\n\t\tthis.request('hide');\n\t\treturn true;\n\t};\n\n\t/**\n\t *

Creates a jQuery UI modal in the main editor window, detached from the plugin itself. Modals are unique on a\n\t * per-plugin basis, meaning that a plugin can only have a single modal at a time. Creating a new modal will\n\t * overwrite the previous.

\n\t *\n\t * See the official documentation for a list of available options.

\n\t *\n\t *

Note that you do not have direct access to the DOM of the modal. Use the provided helper methods to\n\t * manipulate or read from the modal:\n\t *

\n\t *

\n\t *\n\t * @example\n\t *\n\t * PluginAPI.createModal('

This is a modal

', {\n * buttons: {\n * Ok: function () {\n * alert('Ok!');\n * }\n * }\n * });\n\t *\n\t * PluginAPI.updateModal('

This is the same modal

');\n\t *\n\t * PluginAPI.createModal('

This is a brand new modal

', {\n * buttons: {\n * cancel: function() {\n * PluginAPI.closeModal(true);\n * }\n * }\n * });\n\t *\n\t * @param {String} content An HTML string\n\t * @param {Object} options A standard jQuery UI options object.\n\t * @return {Boolean}\n\t */\n\tApi.prototype.createModal = function (content, options) {\n\t\tthis.request('create-custom-modal', {content: content, options: options});\n\t\treturn true;\n\t};\n\n\t/**\n\t * Updates the HTML content of a live modal. Has no effect if the modal does not exist.\n\t *\n\t * @param {String} content An HTML string\n\t * @return {Boolean}\n\t */\n\tApi.prototype.updateModal = function (content) {\n\t\tthis.request('update-custom-modal', {content: content});\n\t\treturn true;\n\t};\n\n\t/**\n\t * Closes and optionally deletes the modal. Has no effect if the modal does not exists.\n\t *\n\t * @param {Boolean} destroy Whether or not to delete the modal\n\t * @return {Boolean}\n\t */\n\tApi.prototype.closeModal = function (destroy) {\n\t\tthis.request('close-custom-modal', {destroy: destroy});\n\t\treturn true;\n\t};\n\n\t/**\n\t * Returns the values of all input or select elements within a modal.\n\t *\n\t * The values are keyed by one of the following properties in order of priority: element ID, element name\n\t * or input type + index.\n\t *\n\t * @example\n\t * Given a modal with the following HTML content:\n\t *\n\t *
\n\t * \n\t * \n\t * \n\t *
\n\t *\n\t * getModalInputs would return:\n\t *\n\t * {\n * \"number-0\": {VALUE}\n * \"name\": {VALUE},\n * \"languages\": \"en\"\n * }\n\t *\n\t * @param {Function} callback\n\t */\n\tApi.prototype.getModalInputs = function (callback) {\n\t\tthis.request('get-custom-modal-inputs', null, callback);\n\t};\n\n\t/**\n\t * unlocks the plugin after authentication. In order to use the plugin, calling this method is required\n\t * for all plugins having a secret defined within the publication config.\n\t *\n\t */\n\tApi.prototype.confirmAuthenticated = function () {\n\t\tthis.request('confirm-authenticated', {\n\t\t\tpluginName: this.appName\n\t\t});\n\t};\n\n\treturn new Api();\n})();\n\n\nPluginAPI.Article = articleCommunicator(PluginAPI);\nPluginAPI.Editor = ah5Communicator(PluginAPI);\n\nmodule.exports = PluginAPI;\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./js/PluginAPI.js\n ** module id = 0\n ** module chunks = 0\n **/","'use strict';\n\n/**\n * @param {Api} PluginAPI\n * @return {ArticleCommunicator}\n */\nmodule.exports = function (PluginAPI) {\n\t/**\n\t * This class is used for communicating with the article, typically setting and getting values of metadata or in the article content itself.\n\t *\n\t * @class\n\t * @classdesc Functions for talking with the DrPublish article object. Accessed through PluginAPI.Article\n\t * @exports PluginAPI/Article\n\t */\n\n /* eslint max-statements: [\"error\", 50, { \"ignoreTopLevelFunctions\": true }]*/\n\tvar ArticleCommunicator = function () {\n\t\tthis.DEBUG = false;\n\t};\n\n\t/**\n\t * Give focus to yourself\n\t *\n\t * @param {Function} callback function(Boolean), called as the app gets focus\n\t */\n\tArticleCommunicator.prototype.focusApp = function (callback) {\n\t\tPluginAPI.request('app-focus', {}, callback);\n\t};\n\t/**\n\t * Start the given app\n\t *\n\t * @param {String} name Name of the app from settings.php\n\t * @param {Object} options Options for initializing the app\n\t * @param {Function} callback function(Boolean), called after app is started\n\t */\n\tArticleCommunicator.prototype.startApp = function (name, options, callback) {\n\t\tPluginAPI.request('app-start', {\n\t\t\tapp: name,\n\t\t\toption: options\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Stop the given app\n\t *\n\t * @param {String} name Name of the app from settings.php\n\t */\n\tArticleCommunicator.prototype.stopApp = function (name) {\n\t\tPluginAPI.request('app-stop', {\n\t\t\tapp: name\n\t\t});\n\t};\n\n\t/**\n\t * Get the id of the article currently edited\n\t *\n\t * @param {Function} callback function(Int), id of the current article\n\t */\n\tArticleCommunicator.prototype.getId = function (callback) {\n\t\tPluginAPI.request('article-id-get', null, callback);\n\t};\n\n\n\t/**\n\t * Get the guid of the article package currently edited\n\t *\n\t * @param {Function} callback function(Int), id of the current article\n\t */\n\tArticleCommunicator.prototype.getPackageId = function (callback) {\n\t\tPluginAPI.request('package-id-get', null, callback);\n\t};\n\n\n\t/**\n\t * Get the guid of the article package currently edited\n\t *\n\t * @param {Function} callback function(Int), id of the current article\n\t */\n\tArticleCommunicator.prototype.getPackageGuid = function (callback) {\n\t\tPluginAPI.request('package-guid-get', null, callback);\n\t};\n\n\t/**\n\t * Clear the meta information summary\n\t *\n\t * @param {Function} callback function(Boolean), called when meta data has been cleared\n\t */\n\tArticleCommunicator.prototype.clearMetaInfo = function (callback) {\n\t\tPluginAPI.request('article-metainfo-clear', null, callback);\n\t};\n\n\t/**\n\t * Get tags used in the article\n\t *\n\t * @param {Function} callback function([Object Tag]), array with tags connected to an article\n\t */\n\tArticleCommunicator.prototype.getTags = function (callback) {\n\t\tPluginAPI.request('article-tags-get', null, callback);\n\t};\n\n\t/**\n\t * Retrieve custom meta value for the article\n\t *\n\t * @param {String} name Name of the custom meta value\n\t * @param {Function} callback function(Object), the parameter is an object containing the given custom meta value\n\t */\n\tArticleCommunicator.prototype.getCustomMeta = function (name, callback) {\n\t\tPluginAPI.request('article-custom-meta-get', {\n\t\t\tname: name\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Set custom meta value for the article\n\t *\n\t * @param {String} name Name of the meta value\n\t * @param {Object} value Value to set\n\t * @param {Function} callback function()\n\t */\n\tArticleCommunicator.prototype.setCustomMeta = function (name, value, callback) {\n\t\tPluginAPI.request('article-custom-meta-set', {\n\t\t\tname: name,\n\t\t\tvalue: value\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Set tags for the article\n\t *\n\t * @param {Array} tags List of tags that should be set\n\t * @param {Boolean} save Set to true to force save once the tags are updated\n\t * @param {Function} callback function(Boolean), called when tags have been set\n\t */\n\tArticleCommunicator.prototype.setTags = function (tags, save, callback) {\n\t\tPluginAPI.request('article-tags-set', {\n\t\t\tsave: save,\n\t\t\ttags: tags\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Add tag for the article\n\t *\n\t * @param {String} tag Tag to be added\n\t * @param {Function} errorFunction called if error\n\t * @param {Function} callback function(Boolean), called when tag has been set\n\t */\n\tArticleCommunicator.prototype.addTag = function (tag, errorFunction, callback) {\n\t\tPluginAPI.request('article-tags-add', {\n\t\t\ttag: tag,\n\t\t\tonError: errorFunction\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Add tags for the article\n\t *\n\t * @param {String} tags Tags to be added\n\t * @param {Function} errorFunction called if error\n\t * @param {Function} callback function(Boolean), called when tag has been set\n\t */\n\tArticleCommunicator.prototype.addTags = function (tags, errorFunction, callback) {\n\t\tPluginAPI.request('article-tags-add', {\n\t\t\ttags: tags,\n\t\t\tonError: errorFunction\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Remove tag from article\n\t *\n\t * @param {String} tag Tag to remove\n\t * @param {Function} callback function(Boolean), called when tag has been removed\n\t */\n\tArticleCommunicator.prototype.removeTag = function (tag, callback) {\n\t\tPluginAPI.request('article-tags-remove', {\n\t\t\ttag: tag\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Get the selected categories\n\t *\n\t * @param {Function} callback function([String]), array with category ids\n\t */\n\tArticleCommunicator.prototype.getSelectedCategories = function (callback) {\n\t\tPluginAPI.request('article-categories-selected-get', null, callback);\n\t};\n\n\t/**\n\t * Save the currently selected categories\n\t *\n\t * @param {Function} callback function(Boolean), called when categories has been saved\n\t */\n\tArticleCommunicator.prototype.saveCategories = function (callback) {\n\t\tthis.getSelectedCategories(function (categories) {\n\t\t\tthis.setCategories(categories, callback);\n\t\t});\n\t};\n\n\t/**\n\t * Set selected categories\n\t *\n\t * @param {Array} categories List of category IDs that should be set\n\t * @param {Function} callback function(Boolean), called when categories have been set\n\t */\n\tArticleCommunicator.prototype.setCategories = function (categories, callback) {\n\t\tPluginAPI.request('article-categories-selected-set', {\n\t\t\tcategories: categories\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Add the given categories to the list of categories\n\t *\n\t * @param {Array} categories List of category IDs to add\n\t * @param {Function} callback function(Boolean), called when the categories have been set\n\t */\n\tArticleCommunicator.prototype.addCategories = function (categories, callback) {\n\n\t\tPluginAPI.request('article-categories-add', {\n\t\t\tcategories: categories\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Remove the given categories from the list of categories\n\t *\n\t * @param {Array} categories List of category IDs to remove\n\t * @param {Function} callback function(Boolean), called when the categories have been removed\n\t */\n\tArticleCommunicator.prototype.removeCategories = function (categories, callback) {\n\t\tPluginAPI.request('article-categories-remove', {\n\t\t\tcategories: categories\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Set the main category of the current article\n\t *\n\t * @param {Number} category The ID of the category to set as the main category\n\t * @param {Function} callback function(Boolean), called when the main category has been set\n\t */\n\tArticleCommunicator.prototype.setMainCategory = function (category, callback) {\n\t\tPluginAPI.request('article-categories-main-set', {\n\t\t\tcategory: category\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Get the source set for the article\n\t *\n\t * @param {Function} callback function(String), name of the source\n\t */\n\tArticleCommunicator.prototype.getSource = function (callback) {\n\n\t\tPluginAPI.request('article-source-get', null, callback);\n\t};\n\n\t/**\n\t * Set the source for the article\n\t *\n\t * @param {String} value The new value to be set as source\n\t * @param {Function} callback function(Boolean), called when the source has been set\n\t */\n\tArticleCommunicator.prototype.setSource = function (value, callback) {\n\t\tPluginAPI.request('article-source-set', {\n\t\t\tsource: value\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Get the status for the article\n\t *\n\t * @param {Function} callback function(String), current status\n\t */\n\tArticleCommunicator.prototype.getStatus = function (callback) {\n\t\tPluginAPI.request('article-status-get', null, callback);\n\t};\n\n\t/**\n\t * Set the status for the article\n\t *\n\t * @param {String} status The new status to be set (draft, waiting, published)\n\t * @param {Function} callback function(Boolean), called when the source has been set\n\t */\n\tArticleCommunicator.prototype.setStatus = function (status, callback) {\n\t\tPluginAPI.request('article-status-set', {\n\t\t\tstatus: status\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Get the published-date\n\t *\n\t * @param {Function} callback function(String), current published datetime\n\t */\n\tArticleCommunicator.prototype.getPublishedDatetime = function (callback) {\n\t\tPluginAPI.request('article-published-get', null, callback);\n\t};\n\n\t/**\n\t * Set the published-date\n\t *\n\t * @param {String} published Date to be set (YYYY-MM-DD HH:MM:SS)\n\t * @param {Function} callback function(Boolean), called when done\n\t */\n\tArticleCommunicator.prototype.setPublishedDatetime = function (published, callback) {\n\t\tPluginAPI.request('article-published-set', {\n\t\t\tpublished: published\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Get the authors set in the article\n\t *\n\t * @param {Function} callback function([String]), currently set authors\n\t */\n\tArticleCommunicator.prototype.getAuthors = function (callback) {\n\t\tPluginAPI.request('article-authors-get', null, callback);\n\t};\n\n\t/**\n\t * Set authors for the article\n\t *\n\t * @param {Array} authors List of authors that should be set\n\t * @param {Function} callback function(Boolean), called when it has been set\n\t */\n\tArticleCommunicator.prototype.setAuthors = function (authors, callback) {\n\t\tPluginAPI.request('article-authors-set', {\n\t\t\tauthors: authors\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Add the given authors to the list of authors\n\t *\n\t * @param {Array} authors List of authors to add\n\t * @param {Function} callback function(Boolean), called when it has been set\n\t */\n\tArticleCommunicator.prototype.addAuthors = function (authors, callback) {\n\t\tPluginAPI.request('article-authors-add', {\n\t\t\tauthors: authors\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Remove the given authors from the list of authors\n\t *\n\t * @param {Array} authors List of authors to remove\n\t * @param {Function} callback function([String]), author list as it is after the authors has been removed\n\t */\n\tArticleCommunicator.prototype.removeAuthors = function (authors, callback) {\n\t\tPluginAPI.request('article-authors-remove', {\n\t\t\tauthors: authors\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Set the keyword-list on the article\n\t *\n\t * @param {Array} keywords List of keywords to add\n\t * @param {Function} callback Function to call when keywords have been set\n\t */\n\tArticleCommunicator.prototype.setKeywords = function (keywords, callback) {\n\t\tPluginAPI.request('article-keywords-set', {\n\t\t\tkeywords: keywords\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Get the current set of keywords on the article\n\t *\n\t * @param {Function} callback Function to call with the result\n\t */\n\tArticleCommunicator.prototype.getKeywords = function (callback) {\n\t\tPluginAPI.request('article-keywords-get', null, callback);\n\t};\n\n\t/**\n\t * Gets the current article content\n\t *\n\t * @param {Function} callback function(Object Content)\n\t */\n\tArticleCommunicator.prototype.getCurrentContent = function (callback) {\n\t\tPluginAPI.request('article-content-get', null, callback);\n\t};\n\n\t/**\n\t * Updates current article content\n\t *\n\t * @param {String} content The new content for the article\n\t * @param {Function} callback function(Boolean), called when it has been set\n\t */\n\tArticleCommunicator.prototype.setCurrentContent = function (content, callback) {\n\t\tPluginAPI.request('article-content-set', {\n\t\t\tcontent: content\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Get the article type of the current article\n\t *\n\t * @param {Function} callback function(Int)\n\t */\n\tArticleCommunicator.prototype.getArticletypeId = function (callback) {\n\t\tPluginAPI.request('article-type-get', null, callback);\n\t};\n\n\t/**\n\t * Set the article type of the current article\n\t *\n\t * @param {Number} articletypeId The new article type of the article\n\t * @param {Function} callback function(Boolean), called when it has been set\n\t */\n\tArticleCommunicator.prototype.setArticletypeId = function (articletypeId, callback) {\n\t\tPluginAPI.request('article-type-set', {\n\t\t\tarticletype: articletypeId\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Maximize the app view\n\t *\n\t * @param {String} title Title to give the maximized view\n\t * @param {function} onClose Function to call when the window is closed/minimized\n\t */\n\tArticleCommunicator.prototype.maximizeAppWindow = function (title, onClose) {\n\t\tvar event = 'editor-pane-close-' + new Date().getTime();\n\n\t\tPluginAPI.request('editor-pane-maximize', {\n\t\t\ttitle: title,\n\t\t\tevent: event\n\t\t});\n\t\tPluginAPI.eventListeners.removeAll(event);\n\t\tPluginAPI.eventListeners.add(event, onClose);\n\t};\n\n\t/**\n\t * Restore the app pane to the default size\n\t *\n\t * @param {function} callback Callback to call after everything is done\n\t */\n\tArticleCommunicator.prototype.restoreAppWindow = function (callback) {\n\t\tPluginAPI.request('restore-app-window', {}, callback);\n\t};\n\n\t/**\n\t * Get the current byline\n\t *\n\t * @param {function} callback function(String), xml string with the current byline\n\t */\n\tArticleCommunicator.prototype.getByline = function (callback) {\n\t\tPluginAPI.request('article-byline-get', null, callback);\n\t};\n\n\t/**\n\t * Set the byline\n\t *\n\t * @param {String} byline XML version of byline to use\n\t * @param {Boolean} save If true, force save after updating byline information\n\t * @param {Function} callback function(Boolean), called when it has been set\n\t */\n\tArticleCommunicator.prototype.setByline = function (byline, save, callback) {\n\t\tPluginAPI.request('article-byline-set', {\n\t\t\tsave: save,\n\t\t\tbyline: byline\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Set geolocation\n\t *\n\t * @param {Object} geolocations The location to set\n\t * @param {Function} callback function(Boolean), called when it has been set\n\t */\n\tArticleCommunicator.prototype.setGeolocations = function (geolocations, callback) {\n\t\tPluginAPI.request('article-geolocations-set', {\n\t\t\tgeolocations: geolocations\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Get geolocation\n\t *\n\t * @param {Function} callback function(Object), retrieves the currently set geo location\n\t */\n\tArticleCommunicator.prototype.getGeolocations = function (callback) {\n\t\tPluginAPI.request('article-geolocations-get', null, callback);\n\t};\n\n\t/**\n\t * Fetches a list of all properties available to an article.\n\t *\n\t * @param {Function} callback Callback called with an array of property objects.\n\t */\n\tArticleCommunicator.prototype.getProperties = function (callback) {\n\t\tPluginAPI.request('article-properties-get', null, callback);\n\t};\n\n\t/**\n\t * Updates and saves one or more property values. The input is a simple object with property names and their\n\t * new value. The supplied callback is called with an updated list of properties.\n\t *\n\t * @example\n\t * PluginAPI.Article.setProperties({\n * fooProperty: \"bar\",\n * barProperty: \"foo\"\n * }, function(properties) {\n * // Returns a complete and updated list of properties.\n * })\n\t *\n\t * @param {Object} properties An object of property names and corresponding values.\n\t * @param {Function} callback Callback called with an updated list of properties.\n\t */\n\tArticleCommunicator.prototype.setProperties = function (properties, callback) {\n\t\tPluginAPI.request('article-properties-set', {\n\t\t\tproperties: properties\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Updates and saves a single property.\n\t *\n\t * @param {String} name The property to update.\n\t * @param {String} value The updated value.\n\t * @param {Function} callback Callback called with an updated list of properties.\n\t */\n\tArticleCommunicator.prototype.setProperty = function (name, value, callback) {\n\t\tvar data = {};\n\t\tdata[name] = value;\n\t\tPluginAPI.request('article-properties-set', {\n\t\t\tproperties: data\n\t\t}, callback);\n\t};\n\n\tArticleCommunicator.prototype.getTopic = function (callback) {\n\t\tPluginAPI.request('article-topic-get', null, callback);\n\t};\n\n\tArticleCommunicator.prototype.setTopic = function (name, callback) {\n\t\tPluginAPI.request('article-topic-set', {\n\t\t\ttopic: name\n\t\t}, callback);\n\t};\n\n\treturn new ArticleCommunicator();\n};\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./js/articleCommunicator.js\n ** module id = 1\n ** module chunks = 0\n **/","'use strict';\n\n/**\n * @typedef {Object} selectedPluginElementData\n *\n * @property {String} id The DOM id of the selected element\n * @property {String} dpArticleId\n * @property {String} externalId\n * @property {Boolean} isDigitalAsset\n */\n\n/**\n * @param {Api} PluginAPI\n * @return {AH5Communicator}\n */\nmodule.exports = function (PluginAPI) {\n\n\t/** @type {selectedPluginElementData|null} */\n\tvar selectedPluginElement = null;\n\n\t/**\n\t * This will be used by editor apps to communicate with the editor\n\t *\n\t * Should be used like this:\n\t *\n\t * PluginAPI.Editor.insertString('string');\n\t *\n\t * @class\n\t * @classdesc Functions for talking with the AH5 editor. Accessed through PluginAPI.Editor\n\t * @exports PluginAPI/Editor\n\t */\n\t/* eslint max-statements: [\"error\", 50, { \"ignoreTopLevelFunctions\": true }]*/\n\tvar AH5Communicator = function () {\n\t\tthis.DEBUG = false;\n\t\tPluginAPI.on('pluginElementClicked', pluginElementSelected);\n\t\tPluginAPI.on('pluginElementDeselected', pluginElementDeselected);\n\n\t\t/**\n\t\t * @param {selectedPluginElementData} elementData\n\t\t */\n\t\tfunction pluginElementSelected(elementData) {\n\t\t\tselectedPluginElement = elementData;\n\t\t}\n\n\t\tfunction pluginElementDeselected() {\n\t\t\tselectedPluginElement = null;\n\t\t}\n\t};\n\n\t/**\n\t * Get name of current active editor\n\t *\n\t * @param {function} callback function(String)\n\t */\n\tAH5Communicator.prototype.getActiveEditor = function (callback) {\n\t\tPluginAPI.request('get-active-editor', null, callback);\n\t};\n\n\t/**\n\t * Registers/Modifies a context menu items for a app element\n\t * The object send should have the following structure\n\t *\n\t * @param {Object} action The action object\n\t * @param {function} callback function()\n\t *\n\t * @example\n\t * PluginAPI.Editor.registerMenuAction({\n\t *\t label: 'label in the menu',\n\t *\t icon: '[Optional] url to possible icon image',\n\t *\t trigger: '[Optional] css selector, only show menu element when this matches the element',\n\t *\t callback: function(id, clickedElementId) {\n\t *\t\t // callback function\n\t *\t\t // first parameter is id of the app element\n\t *\t\t // second paramter is id of closest element to the trigger element that has an id\n\t *\t\t //\t in code: $(event.triggerElement).closest('[id]').attr('id');\n\t *\t }\n\t * })\n\t */\n\tAH5Communicator.prototype.registerMenuAction = function (action, callback) {\n\t\tPluginAPI.request('register-menu-action', action, callback);\n\t};\n\n\n\tAH5Communicator.prototype.registerHoverAction = function (action, callback) {\n\t\tPluginAPI.request('register-hover-action', action, callback);\n\t};\n\n\t/**\n\t * Swap positions between the provided element and the adjacent one\n\t * in the specified direction\n\t * PluginAPI.Editor.directionalCastle({\n\t * elementId: 'the provided element id',\n\t * direction: 'forward/backward'\n\t * })\n\t * @param {String} movement Direction\n\t * @param {Function} callback\n\t * */\n\tAH5Communicator.prototype.directionalCastle = function (movement, callback) {\n\t\tPluginAPI.request('editor-directional-castle', movement, callback);\n\t};\n\n\t/**\n\t * Registers/Modifies a group of items to in the context menu\n\t * The object send should have the following structure\n\t *\n\t * @example\n\t * PluginAPI.Editor.registerMenuActionGroup({\n\t *\t label: 'label for the group in the menu',\n\t *\t icon: '[Optional] url to possible icon image',\n\t *\t actions: [\n\t *\t\t {\n\t *\t\t\t label: 'label for the action #1',\n\t *\t\t\t callback: function(id, clickedElementId) {\n\t *\t\t\t\t // same as for registerMenuAction\n\t *\t\t\t }\n\t *\t\t },\n\t *\t\t {\n\t *\t\t\t label: 'label for the action #2',\n\t *\t\t\t callback: function(id, clickedElementId) {\n\t *\t\t\t\t // same as for registerMenuAction\n\t *\t\t\t }\n\t *\t\t }\n\t *\t ]\n\t * })\n\t *\n\t * @param {Object} group The action object\n\t * @param {function} callback function()\n\t */\n\tAH5Communicator.prototype.registerMenuActionGroup = function (group, callback) {\n\t\tPluginAPI.request('register-menu-action-group', group, callback);\n\t};\n\n\t/**\n\t * Retrieves the type of editor that currently has focus\n\t *\n\t * @param {function} callback function(String)\n\t */\n\tAH5Communicator.prototype.getEditorType = function (callback) {\n\t\tPluginAPI.request('editor-get-type', null, callback);\n\t};\n\n\t/**\n\t * Replace an element in the article\n\t *\n\t * @param {String} id Id of the element\n\t * @param {String} element The new element\n\t * @param {function} callback function(Boolean), called after replacement is done\n\t */\n\tAH5Communicator.prototype.replaceElementById = function (id, element, callback) {\n\t\tPluginAPI.request('editor-element-replace-byid', {\n\t\t\tid: id,\n\t\t\telement: element\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Replace a plugin element in the article\n\t *\n\t * @param {String} id Id of the element\n\t * @param {String} element The new element\n\t * @param {function} callback function(Boolean), called after replacement is done\n\t */\n\tAH5Communicator.prototype.replacePluginElementById = function (id, element, callback) {\n\t\tPluginAPI.request('editor-element-replace-plugin-element-byid', {\n\t\t\tid: id,\n\t\t\telement: element\n\t\t}, callback);\n\t};\n\n\n\t/**\n\t * Delete an element in the article\n\t *\n\t * @param {String} id Id of the element\n\t * @param {function} callback function(Boolean), called after deletion is done\n\t */\n\tAH5Communicator.prototype.deleteElementById = function (id, callback) {\n\t\tPluginAPI.request('editor-element-replace-byid', {\n\t\t\tid: id\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Get HTML code of an element\n\t *\n\t * @param {String} id The element id\n\t * @param {function} callback function(String), html content of the element\n\t */\n\tAH5Communicator.prototype.getHTMLById = function (id, callback) {\n\t\tPluginAPI.request('editor-element-get-byid', {\n\t\t\tid: id\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Get HTML code of all elements that match the selector\n\t *\n\t * @param {String} selector The CSS selector\n\t * @param {function} callback function([String]), html content of matching elements\n\t */\n\tAH5Communicator.prototype.getHTMLBySelector = function (selector, callback) {\n\t\tPluginAPI.request('editor-elements-get-byselector', {\n\t\t\tselector: selector\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Get all categories\n\t *\n\t * @param {Function} callback function([Object Category]), list of Category objects with id, name and pid\n\t */\n\tAH5Communicator.prototype.getCategories = function (callback) {\n\t\tPluginAPI.request('get-categories', null, callback);\n\t};\n\n\t/**\n\t * Returns all the parent categories of the given category\n\t *\n\t * @param {Object} category The category to find parents of\n\t * @param {Function} callback function([Object Category]), array of parent Category objects\n\t */\n\tAH5Communicator.prototype.getParentCategories = function (category, callback) {\n\t\tPluginAPI.request('get-parent-categories', category, callback);\n\t};\n\n\t/**\n\t * Returns all the parent elements that match the selector\n\t *\n\t * @param {String} id Id of element to find parents of\n\t * @param {String} selector Selector to filter parent elements with\n\t * @param {Function} callback function([String]), array of ids\n\t */\n\tAH5Communicator.prototype.getParentIds = function (id, selector, callback) {\n\t\tPluginAPI.request('get-parent-ids', {\n\t\t\tid: id,\n\t\t\tselector: selector\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Retrieve information about all tagtypes\n\t *\n\t * @param {Function} callback function([Object Tagtype]), array of tagtypes with id, name and config object\n\t */\n\tAH5Communicator.prototype.getTagTypes = function (callback) {\n\t\tPluginAPI.request('get-tag-types', null, callback);\n\t};\n\n\t/**\n\t * Get information about the given tagtype\n\t *\n\t * @param {String} id The element id\n\t * @param {Function} callback function(Object Tagtype), tagtype object with id, name and config object\n\t */\n\tAH5Communicator.prototype.getTagType = function (id, callback) {\n\t\tPluginAPI.request('get-tag-type', {\n\t\t\tid: id\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Clears the editor contents\n\t *\n\t * @param {Function} callback function(Boolean)\n\t */\n\tAH5Communicator.prototype.clear = function (callback) {\n\t\tPluginAPI.request('editor-clear', null, callback);\n\t};\n\n\t/**\n\t * Insert a string into the editor\n\t *\n\t * @param {String} string The string that should be inserted\n\t * @param {Function} callback function(String), id of the newly inserted element if it has one\n\t */\n\tAH5Communicator.prototype.insertString = function (string, callback) {\n\t\tPluginAPI.request('editor-insert-string', {\n\t\t\tstring: string\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Insert an element into the editor\n\t *\n\t * Note that the HTML of the element is what will be transferred, and nothing else!\n\t * The element will be given the class dp-app-element, and given a unique ID (if none is present)\n\t *\n\t * @param {Element} element The element that should be inserted\n\t * @param {Object/Function} options (can be omitted) Options object, supports option 'select' - set to true to automatically select the inserted element\n\t * @param {Function} [callback] function(String), id of the newly inserted element\n\t */\n\tAH5Communicator.prototype.insertElement = function (element, options, callback) {\n\t\tvar select = false;\n\t\tif (typeof options === 'object') {\n\t\t\toptions = options || {};\n\t\t\tselect = typeof options.select === 'boolean' ? options.select : false;\n\t\t} else if (typeof callback === 'undefined' && typeof options === 'function') {\n\t\t\tcallback = options;\n\t\t}\n\t\tPluginAPI.request('editor-insert-element', {\n\t\t\telement: element.outerHTML,\n\t\t\tselect: select\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Remove classes from the element an element in the article\n\t *\n\t * @param {String} id Id of the element\n\t * @param {Array} classes Array of class names\n\t * @param {function} callback function(Boolean)\n\t */\n\tAH5Communicator.prototype.removeClasses = function (id, classes, callback) {\n\t\tPluginAPI.request('editor-classes-remove', {\n\t\t\tid: id,\n\t\t\tclasses: classes\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Add new classes to an element\n\t *\n\t * @param {String} id Id of the element\n\t * @param {Array} classes Array of class names\n\t * @param {function} callback function(Boolean)\n\t */\n\tAH5Communicator.prototype.addClasses = function (id, classes, callback) {\n\t\tPluginAPI.request('editor-classes-add', {\n\t\t\tid: id,\n\t\t\tclasses: classes\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Mark an element as currently selected (green border with default styling)\n\t *\n\t * @param {String} id Id of the element\n\t * @param {function} callback function(Boolean)\n\t */\n\tAH5Communicator.prototype.markAsActive = function (id, callback) {\n\t\tPluginAPI.request('editor-mark-as-active', {\n\t\t\tid: id\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Sets the attribute of the element with the given ID to value\n\t *\n\t * @param {String} id The ID of the element to set the attribute on\n\t * @param {String} attribute The attribute to set\n\t * @param {String} value What to set the attribute to\n\t * @param {Function} callback function(Boolean)\n\t */\n\tAH5Communicator.prototype.setAttributeById = function (id, attribute, value, callback) {\n\t\tPluginAPI.request('editor-element-attribute-set-byid', {\n\t\t\tid: id,\n\t\t\tattribute: attribute,\n\t\t\tvalue: value\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Sets a style of the element with the given ID to value\n\t *\n\t * @param {String} id The ID of the element to set the attribute on\n\t * @param {String} attribute The style attribute to set\n\t * @param {String} value What to set the attribute to\n\t * @param {Function} callback function(Boolean)\n\t */\n\tAH5Communicator.prototype.setStyleById = function (id, attribute, value, callback) {\n\t\tPluginAPI.request('editor-element-style-set-byid', {\n\t\t\tid: id,\n\t\t\tattribute: attribute,\n\t\t\tvalue: value\n\t\t}, callback);\n\t};\n\n\n\t/**\n\t * Initialize pre registered menus\n\t *\n\t * Available options are: simplePluginMenu, editContext, deleteButton, floatButtons\n\t *\n\t * @param {Array} menus Array of menu names\n\t * @param {Function} callback function(Boolean)\n\t */\n\tAH5Communicator.prototype.initMenu = function (menus, callback) {\n\t\tPluginAPI.request('editor-initialize-menu', {\n\t\t\tmenus: menus\n\t\t}, callback);\n\t};\n\n\t/**\n\t * Opens the plugin editor for a given element.\n\t *\n\t * @param {String} id Plugin element ID\n\t */\n\tAH5Communicator.prototype.openPluginElementEditor = function (id) {\n\t\tPluginAPI.request('open-element-editor', {\n\t\t\tid: id\n\t\t});\n\t};\n\n\t/**\n\t * Returns the total number of words in the currently open article.\n\t *\n\t * @param {Function} callback Receives the total word count as its single parameter\n\t */\n\tAH5Communicator.prototype.getTotalWordCount = function (callback) {\n\t\tPluginAPI.request('total-word-count', null, callback);\n\t};\n\n\t/**\n\t * Returns the total number of characters in the currently open article.\n\t *\n\t * @param {Function} callback Receives the total character count as its single parameter\n\t */\n\tAH5Communicator.prototype.getTotalCharCount = function (callback) {\n\t\tPluginAPI.request('total-char-count', null, callback);\n\t};\n\n\tAH5Communicator.prototype.updateAssetOption = function (dpArticleId, key, value, callback) {\n\t\tPluginAPI.request('update-asset-option', {dpArticleId: dpArticleId, key: key, value: value}, callback);\n\t};\n\n\tAH5Communicator.prototype.updateAssetData = function (data, callback) {\n\t\tPluginAPI.request('update-asset-media', data, callback);\n\t};\n\n\tAH5Communicator.prototype.getAssetData = function (dpArticleId, callback) {\n\t\tPluginAPI.request('get-asset-data', {data: dpArticleId}, callback);\n\t};\n\n\tAH5Communicator.prototype.insertNestedAsset = function (parentElementId, markup, data, callback) {\n\t\tvar self = this;\n\t\tPluginAPI.createEmbeddedObject(\n\t\t\tdata.embeddedTypeId,\n\t\t\tfunction (dpArticleId) {\n\t\t\t\tinsert(dpArticleId, parentElementId, function (data) {\n\t\t\t\t\treturn updateEmbeddedAssetRequest(callback);\n\t\t\t\t});\n\t\t\t}\n\t\t);\n\n\t\tfunction insert(dpArticleId, parentElementId, callback) {\n\t\t\tdata.internalId = dpArticleId;\n\t\t\tvar elementId = 'asset-' + dpArticleId;\n\t\t\tvar $element = $('
');\n\t\t\t$element.attr('id', elementId);\n\t\t\t$element.attr('data-internalId', dpArticleId);\n\t\t\tif (data.externalId) {\n $element.attr('data-externalId', data.externalId);\n\t\t\t}\n\t\t\tif (data.assetClass) {\n\t\t\t\t$element.addClass(data.assetClass);\n\t\t\t}\n\t\t\t$element.addClass('dp-plugin-element');\n\t\t\t$element.html(markup);\n\t\t\tPluginAPI.Editor.getHTMLById(parentElementId, function (html) {\n\t\t\t\tvar d = document.createElement('div');\n\t\t\t\td.innerHTML = html;\n\t\t\t\td.firstChild.setAttribute('id', parentElementId + 'tmp');\n\t\t\t\tself.replacePluginElementById(parentElementId, d.innerHTML, function () {\n\t\t\t\t\td = document.createElement('div');\n\t\t\t\t\td.innerHTML = html;\n\t\t\t\t\tvar assetContainer = d.querySelector('.dp-fact-box-image, .dp-nested-asset-container');\n\t\t\t\t\tif (data.isMultiple) {\n\t\t\t\t\t\t$(assetContainer).append($element.get(0).outerHTML);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tassetContainer.innerHTML = $element.get(0).outerHTML;\n\t\t\t\t\t}\n\t\t\t\t\tself.replacePluginElementById(parentElementId + 'tmp', d.innerHTML, callback);\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\t\tfunction updateEmbeddedAssetRequest(callback) {\n\t\t\tPluginAPI.request('update-embedded-asset', data, callback);\n\t\t}\n\t};\n\n\tAH5Communicator.prototype.insertEmbeddedAsset = function (markup, data, callback) {\n\t\tvar self = this;\n\t\tvar replaceElement = false;\n\t\tif (selectedPluginElement) {\n\t\t\tif (data.assetSource !== PluginAPI.getAppName()) {\n\t\t\t\tPluginAPI.showErrorMsg('Can\\'t update selected plugin element since it doesn\\'t belong to the \\'' + PluginAPI.getAppName() + '\\' plugin');\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\treplaceElement = true;\n\t\t\t}\n\t\t}\n\n\t\tif (selectedPluginElement) {\n\t\t\tvar dpArticleId = selectedPluginElement.dpArticleId;\n\t\t\tif (!dpArticleId) {\n\t\t\t\tthrow Error('Selected plugin element: expected dpArticleId not found (tried reading from attribute \\'data-internal-id\\')');\n\t\t\t}\n\t\t\tinsert(dpArticleId, function (data) {\n\t\t\t\treturn updateEmbeddedAssetRequest(typeof callback === 'function' ? callback(data) : null);\n\t\t\t});\n\t\t} else {\n\t\t\tPluginAPI.createEmbeddedObject(\n\t\t\t\tdata.embeddedTypeId,\n\t\t\t\tfunction (dpArticleId) {\n\t\t\t\t\tinsert(dpArticleId, function (data) {\n\t\t\t\t\t\treturn addEmbeddedAssetRequest(typeof callback === 'function' ? callback(data) : null);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\n\t\tfunction insert(dpArticleId, callback) {\n\t\t\tdata.internalId = dpArticleId;\n\t\t\tvar elementId = 'asset-' + dpArticleId;\n\t\t\tvar element = document.createElement('div');\n\t\t\telement.id = elementId;\n\t\t\telement.dataset.internalId = dpArticleId;\n\t\t\tif (data.externalId) {\n\t\t\t\telement.dataset.externalId = data.externalId;\n\t\t\t}\n\t\t\tif (data.assetClass) {\n\t\t\t\telement.classList.add(data.assetClass);\n\t\t\t}\n\t\t\telement.innerHTML = markup;\n\t\t\tif (!replaceElement) {\n\t\t\t\tself.insertElement(element, {select: true});\n\t\t\t} else {\n\t\t\t\tself.replaceElementById(elementId, element.outerHTML, null);\n\t\t\t}\n\t\t\tif (typeof callback === 'function') {\n\t\t\t\treturn callback();\n\t\t\t}\n\t\t}\n\n\t\tfunction addEmbeddedAssetRequest(callback) {\n\t\t\tPluginAPI.request('add-embedded-asset', data, callback);\n\t\t}\n\n\t\tfunction updateEmbeddedAssetRequest(callback) {\n\t\t\tPluginAPI.request('update-embedded-asset', data, callback);\n\t\t}\n\t};\n\n\tAH5Communicator.prototype.getSelectedPluginElement = function (callback) {\n\t\tPluginAPI.request('get-selected-plugin-element', {}, callback);\n\t};\n\n\treturn new AH5Communicator();\n};\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./js/AH5Communicator.js\n ** module id = 2\n ** module chunks = 0\n **/","'use strict';\n\nmodule.exports = Listeners;\n\n/**\n * @example\n * PluginAPI.on('afterCreate', function() {\n * PluginAPI.Article.setSource('Ny Times');\n * });\n * PluginAPI.on('beforeSave', function() {\n * if (!articleIsAwesome()) {\n * return false;\n * }\n * });\n *\n * @description\n *\n *

DrPublish provides a large set of default events that an app can listen for. All events that start their name with 'before' can be stopped by an app. This is done by returning 'false' from the callback function, as in the 'beforeSave' example given below.

\n *

Other apps can also supply their own events using the PluginAPI.emit(...) function. Documention on these events are up to each app to create.

\n *

Available Events

\n *

addCategory

\n *
\n *

triggered after a category has been added to the article

\n *
\n *

addTag

\n *
\n *

triggered after a tag had been added to the article

\n *
\n *

appPaneMaximized

\n *
\n *

triggered when the app pane is maximized

\n *
\n *

appPaneRestored

\n *
\n *

triggered when the app pane is restored to its' original size

\n *
\n *

appAuthenticated

\n *
\n *

triggered when an app has been authenticated

\n *
\n *

changedCustomMeta

\n *
\n *

triggered when a custom meta property is changed/set, parameter is an object with property name and value

\n *
\n *

receivedFocus

\n *
\n *

triggered when a plugin receives focus. Receives a parameter object that has two predefined values: previousPluginName - name of previous plugin, givenFocus - true when focus was sent from another plugin. The parameter object can also contain other keys supplied by the plugin losing focus.

\n *
\n *

afterCreate

\n *
\n *

triggered after a new article has been created

\n *
\n *

beforeDelete

\n *
\n *

triggered before an article is deleted

\n *
\n *

afterDelete

\n *
\n *

triggered after an article has been deleted

\n *
\n *

afterLoad

\n *
\n *

triggered after an article has been loaded

\n *
\n *

afterPublish

\n *
\n *

triggered after an article has been published

\n *
\n *

afterSave

\n *
\n *

triggered after an article has been saved

\n *
\n *

beforeCreate

\n *
\n *

triggered before a new article is created

\n *
\n *

beforeLoad

\n *
\n *

triggered before an article is loaded into the editor

\n *
\n *

beforePreview

\n *
\n *

triggered before the article is opened in the preview

\n *
\n *

beforeSave

\n *
\n *

triggered before an article is saved

\n *
\n *

beforePublish

\n *
\n *

triggered before an article is published

\n *
\n *

editorFocus

\n *
\n *

triggered when an editor gets focus

\n *
\n *

editorUnfocus

\n *
\n *

triggered when an editor loses focus

\n *
\n *

editorsLostFocus

\n *
\n *

triggered when all editors loses focus

\n *
\n *

editorReady

\n *
\n *

triggered when the editor has been fully loaded and is ready for input

\n *
\n *

modifiedContent

\n *
\n *

triggered whenever content changes in the article

\n *
\n *

elementRemoved

\n *
\n *

triggered when a plugin element from the current plugin is removed, receives an object with element id as a parameter

\n *
\n *

pluginElementClicked

\n *
\n *

triggered when someone clicks on a plugin element in the editor

\n *
\n *

pluginElementSelected

\n *
\n *

triggers when someone selects a plugin element in the editor

\n *
\n *

pluginElementDeselected

\n *
\n *

triggered when someone deselects a plugin element in the editor

\n *
\n */\nfunction Listeners() {\n\tthis._listeners = {};\n}\n\n/**\n * Adds a new listener\n *\n * @param {String} event Event name\n * @param {Function} callback Function to call when an even of the type is received\n * @return {int|undefined} The index of the new listener\n */\nListeners.prototype.add = function (event, callback) {\n\tif (typeof callback !== 'function') {\n\t\tthrow Error('Listener callback must be a function.');\n\t}\n\n\tif (this._listeners[event] === undefined) {\n\t\tthis._listeners[event] = [];\n\t}\n\n\tthis._listeners[event].push(callback);\n\treturn this._listeners[event].length - 1;\n};\n\n/**\n * Removes the listener at the given index\n *\n * @param {String} event Event type\n * @param {Function} index The index of the event handler to remove\n */\nListeners.prototype.remove = function (event, index) {\n\tif (this._listeners[event] === undefined || this._listeners[event][index] === undefined) {\n\t\treturn;\n\t}\n\n\t/*\n\t * Set to null instead of remove to retain callback indexes\n\t */\n\tthis._listeners[event][index] = false;\n};\n\n/**\n * Removes all listeners for the given event type, or if !event then removes all listeners\n *\n * @param {String} event Event type to remove handlers for (!event for all)\n */\nListeners.prototype.removeAll = function (event) {\n\tif (!event) {\n\t\tthis._listeners = [];\n\t} else {\n\t\tthis._listeners[event] = [];\n\t}\n};\n\n/**\n * Notifies all registered listeners that an event has occurred\n *\n * If the payload has a key `data`, the value of that field will be passed to listener. If not, the entire payload will\n * be passed on.\n *\n * @param {String} event Event type\n * @param {Object} payload The event data\n * @return {Boolean} Whether to continue with the action (for events named `before*`)\n */\nListeners.prototype.notify = function (event, payload) {\n\tvar returnValue = true;\n\tif (this._listeners[event] === undefined) {\n\t\treturn returnValue;\n\t}\n\n\t// If the payload is an object with a key data, we use that value as the payload we pass to the listener functions.\n\t// This is needed as we have some inconsistencies in how we pass data around. This normalization should preferably\n\t// be done at the call site.\n\tthis._listeners[event].forEach(function (listenerFn) {\n\t\tif (typeof listenerFn !== 'function') {\n\t\t\treturn;\n\t\t}\n\t\tvar res = null;\n\t\tif (payload && payload.params && payload.params === true) {\n\t\t\tres = listenerFn.apply(null, payload.data);\n\t\t} else if (typeof payload === 'object' && payload !== null && typeof payload.data !== 'undefined') {\n\t\t\tres = listenerFn(payload.data);\n\t\t} else {\n\t\t\tres = listenerFn(payload);\n\t\t}\n\t\tif (res === false) {\n\t\t\treturnValue = false;\n\t\t}\n\t});\n\treturn returnValue;\n};\n\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./js/Listeners.js\n ** module id = 3\n ** module chunks = 0\n **/"],"sourceRoot":""} \ No newline at end of file