From bda56f9bf866881a6f87d1729ea319d6857d816b Mon Sep 17 00:00:00 2001 From: michael Date: Thu, 11 Dec 2014 10:41:51 +0100 Subject: [PATCH] Set to mirror the develop branch on the last point where the classes where named AppAPI (commit 76baed6... Merge pull request #4 from aptoma/docs-update) --- Gruntfile.js | 62 + README.md | 48 +- bower.json | 10 + conf.json | 1 - doc/AH5Communicator.js.html | 805 ++- doc/AppAPI.html | 2736 ------- doc/AppAPI.js.html | 999 ++- ...{ArticleCommunicator.html => Article.html} | 4708 +++++++----- doc/ArticleCommunicator.js.html | 1028 +-- doc/{AH5Communicator.html => Editor.html} | 2669 ++++--- doc/Listeners.js.html | 304 +- doc/global.html | 412 +- doc/img/glyphicons-halflings-white.png | Bin 0 -> 8777 bytes doc/img/glyphicons-halflings.png | Bin 0 -> 12799 bytes doc/index.html | 269 +- doc/module-AppApi.html | 4422 ++++++++++++ doc/modules.list.html | 242 + doc/scripts/URI.js | 1429 ++++ doc/scripts/bootstrap-dropdown.js | 169 + doc/scripts/bootstrap-tab.js | 144 + doc/scripts/docstrap.lib.js | 9 + doc/scripts/prettify/jquery.min.js | 6 + doc/scripts/prettify/lang-css.js | 23 +- doc/scripts/prettify/prettify.js | 524 +- doc/scripts/sunlight.js | 1157 +++ doc/scripts/toc.js | 100 + doc/styles/darkstrap.css | 960 +++ doc/styles/jsdoc-default.css | 11 +- doc/styles/site.amelia.css | 6369 +++++++++++++++++ doc/styles/site.cerulean.css | 5701 +++++++++++++++ doc/styles/site.cosmo.css | 5944 +++++++++++++++ doc/styles/site.cyborg.css | 6151 ++++++++++++++++ doc/styles/site.darkstrap.css | 5638 +++++++++++++++ doc/styles/site.flatly.css | 5993 ++++++++++++++++ doc/styles/site.journal.css | 5745 +++++++++++++++ doc/styles/site.readable.css | 5433 ++++++++++++++ doc/styles/site.simplex.css | 5758 +++++++++++++++ doc/styles/site.slate.css | 6204 ++++++++++++++++ doc/styles/site.spacelab.css | 5796 +++++++++++++++ doc/styles/site.spruce.css | 5938 +++++++++++++++ doc/styles/site.superhero.css | 6106 ++++++++++++++++ doc/styles/site.united.css | 5545 ++++++++++++++ doc/styles/sunlight.dark.css | 345 + doc/styles/sunlight.default.css | 344 + example/index.php | 26 +- js/AH5Communicator.js | 572 +- js/AppAPI.js | 819 ++- js/ArticleCommunicator.js | 237 +- js/Listeners.js | 109 +- jsdoc.conf | 4 + karma.conf.js | 72 + package.json | 17 + test/AppAPI-test.js | 205 + 53 files changed, 100412 insertions(+), 7906 deletions(-) create mode 100644 Gruntfile.js create mode 100644 bower.json delete mode 120000 conf.json delete mode 100644 doc/AppAPI.html rename doc/{ArticleCommunicator.html => Article.html} (56%) rename doc/{AH5Communicator.html => Editor.html} (54%) create mode 100644 doc/img/glyphicons-halflings-white.png create mode 100644 doc/img/glyphicons-halflings.png create mode 100644 doc/module-AppApi.html create mode 100644 doc/modules.list.html create mode 100644 doc/scripts/URI.js create mode 100644 doc/scripts/bootstrap-dropdown.js create mode 100644 doc/scripts/bootstrap-tab.js create mode 100644 doc/scripts/docstrap.lib.js create mode 100644 doc/scripts/prettify/jquery.min.js create mode 100644 doc/scripts/sunlight.js create mode 100644 doc/scripts/toc.js create mode 100644 doc/styles/darkstrap.css create mode 100644 doc/styles/site.amelia.css create mode 100644 doc/styles/site.cerulean.css create mode 100644 doc/styles/site.cosmo.css create mode 100644 doc/styles/site.cyborg.css create mode 100644 doc/styles/site.darkstrap.css create mode 100644 doc/styles/site.flatly.css create mode 100644 doc/styles/site.journal.css create mode 100644 doc/styles/site.readable.css create mode 100644 doc/styles/site.simplex.css create mode 100644 doc/styles/site.slate.css create mode 100644 doc/styles/site.spacelab.css create mode 100644 doc/styles/site.spruce.css create mode 100644 doc/styles/site.superhero.css create mode 100644 doc/styles/site.united.css create mode 100644 doc/styles/sunlight.dark.css create mode 100644 doc/styles/sunlight.default.css create mode 100644 karma.conf.js create mode 100644 package.json create mode 100644 test/AppAPI-test.js diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..467db07 --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,62 @@ +/* global module:false */ + +module.exports = function(grunt) { + "use strict"; + + require('time-grunt')(grunt); + + grunt.loadNpmTasks('grunt-karma'); + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-contrib-watch'); + grunt.loadNpmTasks('grunt-jsdoc'); + + grunt.registerTask('ci', ['jshint', 'karma:ci']); + + grunt.initConfig({ + jshint: { + options: { + jshintrc: true + }, + all: ['Gruntfile.js', 'js/*.js', 'test/**/*.js'] + }, + + karma: { + ci: { + configFile: 'karma.conf.js', + background: false, + singleRun: true, + browsers: ['PhantomJS'] + }, + unit: { + configFile: 'karma.conf.js', + background: true, + browsers: ['PhantomJS'] + }, + autowatch: { + configFile: 'karma.conf.js', + autoWatch: true, + browsers: ['PhantomJS'] + } + }, + + watch: { + scripts: { + files: ['js/**/*.js', 'test/**/*.js'], + tasks: ['jshint', 'karma:autowatch'], + options: { + spawn: false + } + } + }, + + jsdoc: { + dist: { + src: ['README.md', 'js/*.js'], + options: { + destination: 'doc', + template : "node_modules/grunt-jsdoc/node_modules/ink-docstrap/template" + } + } + } + }); +}; diff --git a/README.md b/README.md index 74de474..3ac8b7d 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,52 @@ Take a look at the example app to see how to get started. There you will see an When you're bored of that you can look through the method listings avaiable on the right and that is hopefully enough to set you on the right track to create any app you want. +Costum configuration +============== +Apps can ask for and specify a customized configuration object. The API function to retrieve the configuration option is AppAPI.getConfiguration, and you can find documentation on that in the AppAPI module. + +To specify the format of the configuration object the App needs to provide an URL where other applications (in most cases DrPublish's App Admin tool) can recieve an [JSON schema](http://json-schema.org/) describing the desired configuration setup. In case of DrPublish this URL is then registered alongside the URL to the app in the Publication configuration. + +A simple example JSON schema for an image app could look like: +```JSON +{ + "search": { + "type": "string", + "title": "Default Search", + "required": true + }, + "images": { + "type": "array", + "title": "Image Sizes", + "items": { + "type": "object", + "title": "Image Size", + "properties": { + "name": { + "type": "string", + "title": "name", + "required": true + }, + "filter": { + "type": "string", + "title": "Filter", + "enum": [ + "grayscale", + "sepia", + "none" + ] + }, + "height": { + "type": "integer", + "title": "Height" + } + } + } + } +} +``` + + Authentication explained ============== When an app is loaded DrPublish send an encrypted token to the app, this is done so the app can check that it is actually being loaded by a DrPublish instance with a valid user logged in. Apps should always verify this token, otherwise this security aspect dissappears. @@ -53,4 +99,4 @@ Note especially warnings and errors since these indicate that something of speci Documentation Generation ======================== -Documentation has been generated using [jsdoc](https://github.com/jsdoc3/jsdoc) and the supplied conf.json file +Documentation has been generated using [jsdoc](https://github.com/jsdoc3/jsdoc) and the supplied jsdoc.json file diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..8203b23 --- /dev/null +++ b/bower.json @@ -0,0 +1,10 @@ +{ + "name": "plugin-api", + "repository": { + "type": "git", + "url": "https://github.com/aptoma/no.aptoma.plugin-api.git" + }, + "dependencies": { + "jquery": "2.1.1" + } +} diff --git a/conf.json b/conf.json deleted file mode 120000 index 61617e1..0000000 --- a/conf.json +++ /dev/null @@ -1 +0,0 @@ -jsdoc.conf \ No newline at end of file diff --git a/doc/AH5Communicator.js.html b/doc/AH5Communicator.js.html index 5323951..08c6089 100644 --- a/doc/AH5Communicator.js.html +++ b/doc/AH5Communicator.js.html @@ -1,261 +1,307 @@ + - - JSDoc: Source: AH5Communicator.js - - - - - - + + DocStrap Source: AH5Communicator.js + + + + + + - -
- -

Source: AH5Communicator.js

- +
+ + +
+ + +
+ +
+ + + +

Source: AH5Communicator.js

+
+
+
/* global AppAPI: true */
 
+AppAPI.Editor = (function () {
+    "use strict";
 
-    
-    
-
-
/* global AppAPI: true */
-/**
- * This will be used by editor apps to communicate with the editor
- *
- * Should be used like this:
- *
- * AppAPI.Editor.insert('string');
- *
- * @class
- * @classdesc Functions for talking with the AH5 editor. Accessed through AppAPI.Editor
- */
-var AH5Communicator = {
-	/**
-	 * Get name of current active editor
+    /**
+     * This will be used by editor apps to communicate with the editor
+     *
+     * Should be used like this:
+     *
+     * AppAPI.Editor.insert('string');
+     *
+     * @class
+     * @classdesc Functions for talking with the AH5 editor. Accessed through AppAPI.Editor
+     * @exports AppAPI/Editor
+     */
+    var AH5Communicator = function() {
+        this.DEBUG = false;
+    };
+    /**
+     * Get name of current active editor
      * 
-	 * @param {function} callback function(String)
-	 */
-	getActiveEditor: function (callback) {
-		AppAPI.request('get-active-editor', null, callback);
-	},
-	/**
-	 * Registers/Modifies a context menu items for a app element
-	 * The object send should have the following structure
-	 *
-	 * @param {Object} action The action object
-	 * @param {function} callback function()
+     * @param {function} callback function(String)
+     */
+    AH5Communicator.prototype.getActiveEditor = function (callback) {
+        AppAPI.request('get-active-editor', null, callback);
+    };
+    /**
+     * Registers/Modifies a context menu items for a app element
+     * The object send should have the following structure
+     *
+     * @param {Object} action The action object
+     * @param {function} callback function()
      *
      * @example
-	 * AppAPI.Editor.registerMenuAction({
-	 *      label: 'label in the menu',
-	 *      icon: '[Optional] url to possible icon image',
-	 *      trigger: '[Optional] css selector, only show menu element when this matches the element',
-	 *      callback: function(id, clickedElementId) {
-	 *          // callback function
+     * AppAPI.Editor.registerMenuAction({
+     *      label: 'label in the menu',
+     *      icon: '[Optional] url to possible icon image',
+     *      trigger: '[Optional] css selector, only show menu element when this matches the element',
+     *      callback: function(id, clickedElementId) {
+     *          // callback function
      *          // first parameter is id of the app element
      *          // second paramter is id of closest element to the trigger element that has an id
      *          //      in code: $(event.triggerElement).closest('[id]').attr('id');						
-	 *      }
-	 * })
-	 */
-	registerMenuAction: function (action, callback) {
-		AppAPI.request('register-menu-action', action, callback);
-	},
-
-	/**
-	 * Registers/Modifies a group of items to in the context menu
-	 * The object send should have the following structure
+     *      }
+     * })
+     */
+    AH5Communicator.prototype.registerMenuAction = function (action, callback) {
+        AppAPI.request('register-menu-action', action, callback);
+    };
+
+    /**
+     * Registers/Modifies a group of items to in the context menu
+     * The object send should have the following structure
      *
      * @example
-	 * AppAPI.Editor.registerMenuActionGroup({
-	 *      label: 'label for the group in the menu',
-	 *      icon: '[Optional] url to possible icon image',
-	 *      actions: [
-	 *          {
-	 *              label: 'label for the action #1',
-	 *              callback: function(id, clickedElementId) {
+     * AppAPI.Editor.registerMenuActionGroup({
+     *      label: 'label for the group in the menu',
+     *      icon: '[Optional] url to possible icon image',
+     *      actions: [
+     *          {
+     *              label: 'label for the action #1',
+     *              callback: function(id, clickedElementId) {
      *                  // same as for registerMenuAction
-	 *              }
-	 *          },
-	 *          {
-	 *              label: 'label for the action #2',
-	 *              callback: function(id, clickedElementId) {
+     *              }
+     *          },
+     *          {
+     *              label: 'label for the action #2',
+     *              callback: function(id, clickedElementId) {
      *                  // same as for registerMenuAction
-	 *              }
-	 *          }
-	 *      ]
-	 * })
-	 *
-	 * @param {Object} group The action object
-	 * @param {function} callback function()
-	 */
-	registerMenuActionGroup: function (group, callback) {
-		AppAPI.request('register-menu-action-group', group, function(typeNames) {
-			if (typeNames.length !== group.actions.length) {
-				if (this.DEBUG) {
-                    console.warn('wrong amount of callback events recieved, not good');
-                }
-				return;
-			}
-            var createMenuAction = function(func) {
-                if (typeof func === 'function') {
-                    return function(data) {
-                        func(data.id);
-                    };
-                } else {
-                    return function() {};
-                }
-            };
-			for (var i=0; i<typeNames.length; i++) {
-				var menuAction = createMenuAction(group.actions[i].callback);
-
-				AppAPI.eventListeners.add(typeNames[i], menuAction);
-			}
-
-            callback(typeNames);
-		});
-	},
-
-	/**
-	 * Retrieves the type of editor that currently has focus
-	 *
-	 * @param {function} callback function(String)
-	 */
-	getEditorType: function(callback) {
-		AppAPI.request('editor-get-type', null, callback);
-	},
-
-	/**
-	 * Replace an element in the article
-	 *
-	 * @param {String} id Id of the element
-	 * @param {String} element The new element
-	 * @param {function} callback function(Boolean), called after replacement is done
-	 */
-	replaceElementById: function(id, element, callback) {
-		AppAPI.request('editor-element-replace-byid', {
-			id: id,
-			element: element
-		}, callback);
-	},
-
-	/**
-	 * Get HTML code of an element
-	 *
-	 * @param {String} id The element id
-	 * @param {function} callback function(String), html content of the element
-	 */
-	getHTMLById: function(id, callback) {
-		AppAPI.request('editor-element-get-byid', {
-			id: id
-		}, callback);
-	},
-
-	/**
-	 * Get HTML code of all elements that match the selector
-	 *
-	 * @param {String} selector The CSS selector
-	 * @param {function} callback function([String]), html content of matching elements
-	 */
-	getHTMLBySelector: function(selector, callback) {
-		AppAPI.request('editor-elements-get-byselector', {
-			selector: selector
-		}, callback);
-	},
-
-	/**
-	 * Get all categories
-	 *
-	 * @param {Function} callback function([Object Category]), list of Category objects with id, name and pid
-	 */
-	getCategories: function(callback) {
-		AppAPI.request('get-categories', null, callback);
-	},
-
-	/**
-	 * Returns all the parent categories of the given category
-	 *
-	 * @param {Object} category The category to find parents of
-	 * @param {Function} callback function([Object Category]), array of parent Category objects
-	 */
-	getParentCategories: function(category, callback) {
-		AppAPI.request('get-parent-categories', category, callback);
-	},
-
-	/**
-	 * Returns all the parent elements that match the selector
-	 *
-	 * @param {String} id Id of element to find parents of
-	 * @param {String} selector Selector to filter parent elements with
-	 * @param {Function} callback function([String]), array of ids
-	 */
-	getParentIds: function(id, selector, callback) {
-		AppAPI.request('get-parent-ids', {
+     *              }
+     *          }
+     *      ]
+     * })
+     *
+     * @param {Object} group The action object
+     * @param {function} callback function()
+     */
+    AH5Communicator.prototype.registerMenuActionGroup = function (group, callback) {
+        AppAPI.request('register-menu-action-group', group, callback);
+    };
+
+    /**
+     * Retrieves the type of editor that currently has focus
+     *
+     * @param {function} callback function(String)
+     */
+    AH5Communicator.prototype.getEditorType = function(callback) {
+        AppAPI.request('editor-get-type', null, callback);
+    };
+
+    /**
+     * Replace an element in the article
+     *
+     * @param {String} id Id of the element
+     * @param {String} element The new element
+     * @param {function} callback function(Boolean), called after replacement is done
+     */
+    AH5Communicator.prototype.replaceElementById = function(id, element, callback) {
+        AppAPI.request('editor-element-replace-byid', {
+            id: id,
+            element: element
+        }, callback);
+    };
+
+    /**
+     * Delete an element in the article
+     *
+     * @param {String} id Id of the element
+     * @param {function} callback function(Boolean), called after deletion is done
+     */
+    AH5Communicator.prototype.deleteElementById = function(id, callback) {
+        AppAPI.request('editor-element-replace-byid', {
+            id: id
+        }, callback);
+    };
+
+    /**
+     * Get HTML code of an element
+     *
+     * @param {String} id The element id
+     * @param {function} callback function(String), html content of the element
+     */
+    AH5Communicator.prototype.getHTMLById = function(id, callback) {
+        AppAPI.request('editor-element-get-byid', {
+            id: id
+        }, callback);
+    };
+
+    /**
+     * Get HTML code of all elements that match the selector
+     *
+     * @param {String} selector The CSS selector
+     * @param {function} callback function([String]), html content of matching elements
+     */
+    AH5Communicator.prototype.getHTMLBySelector = function(selector, callback) {
+        AppAPI.request('editor-elements-get-byselector', {
+            selector: selector
+        }, callback);
+    };
+
+    /**
+     * Get all categories
+     *
+     * @param {Function} callback function([Object Category]), list of Category objects with id, name and pid
+     */
+    AH5Communicator.prototype.getCategories = function(callback) {
+        AppAPI.request('get-categories', null, callback);
+    };
+
+    /**
+     * Returns all the parent categories of the given category
+     *
+     * @param {Object} category The category to find parents of
+     * @param {Function} callback function([Object Category]), array of parent Category objects
+     */
+    AH5Communicator.prototype.getParentCategories = function(category, callback) {
+        AppAPI.request('get-parent-categories', category, callback);
+    };
+
+    /**
+     * Returns all the parent elements that match the selector
+     *
+     * @param {String} id Id of element to find parents of
+     * @param {String} selector Selector to filter parent elements with
+     * @param {Function} callback function([String]), array of ids
+     */
+    AH5Communicator.prototype.getParentIds = function(id, selector, callback) {
+        AppAPI.request('get-parent-ids', {
             id: id,
             selector: selector
         }, callback);
-	},
-
-	/**
-	 * Retrieve information about all tagtypes
-	 *
-	 * @param {Function} callback function([Object Tagtype]), array of tagtypes with id, name and config object
-	 */
-	getTagTypes: function(callback) {
-		AppAPI.request('get-tag-types', null, callback);
-	},
-
-	/**
-	 * Get information about the given tagtype
-	 *
-	 * @param {String} id The element id
-	 * @param {Function} callback function(Object Tagtype), tagtype object with id, name and config object
-	 */
-	getTagType: function(id, callback) {
-		AppAPI.request('get-tag-type', {
-			id: id
-		}, callback);
-	},
-
-	/**
-	 * Clears the editor contents
-	 *
-	 * @param {Function} callback function(Boolean)
-	 */
-	clear: function(callback) {
-		AppAPI.request('editor-clear', null, callback);
-	},
-
-	/**
-	 * Insert a string into the editor
-	 *
-	 * @param {String} string The string that should be inserted
-	 * @param {Function} callback function(String), id of the newly inserted element if it has one
-	 */
-	insertString: function(string, callback) {
-		AppAPI.request('editor-insert-string', {
-			string: string
-		}, callback);
-	},
-
-	/**
-	 * Insert an element into the editor
-	 *
-	 * Note that the HTML of the element is what will be transferred, and nothing else!
-	 * The element will be given the class dp-app-element, and given a unique ID (if none is present)
-	 *
-	 * @param {Element} element The element that should be inserted
-	 * @param {Options/Function} options (can be omitted) Options object, supports option 'select' - set to true to automatically select the inserted element
-	 * @param {Function} callback function(String), id of the newly inserted element
-	 */
-	insertElement: function(element, options, callback) {
+    };
+
+    /**
+     * Retrieve information about all tagtypes
+     *
+     * @param {Function} callback function([Object Tagtype]), array of tagtypes with id, name and config object
+     */
+    AH5Communicator.prototype.getTagTypes = function(callback) {
+        AppAPI.request('get-tag-types', null, callback);
+    };
+
+    /**
+     * Get information about the given tagtype
+     *
+     * @param {String} id The element id
+     * @param {Function} callback function(Object Tagtype), tagtype object with id, name and config object
+     */
+    AH5Communicator.prototype.getTagType = function(id, callback) {
+        AppAPI.request('get-tag-type', {
+            id: id
+        }, callback);
+    };
+
+    /**
+     * Clears the editor contents
+     *
+     * @param {Function} callback function(Boolean)
+     */
+    AH5Communicator.prototype.clear = function(callback) {
+        AppAPI.request('editor-clear', null, callback);
+    };
+
+    /**
+     * Insert a string into the editor
+     *
+     * @param {String} string The string that should be inserted
+     * @param {Function} callback function(String), id of the newly inserted element if it has one
+     */
+    AH5Communicator.prototype.insertString = function(string, callback) {
+        AppAPI.request('editor-insert-string', {
+            string: string
+        }, callback);
+    };
+
+    /**
+     * Insert an element into the editor
+     *
+     * Note that the HTML of the element is what will be transferred, and nothing else!
+     * The element will be given the class dp-app-element, and given a unique ID (if none is present)
+     *
+     * @param {Element} element The element that should be inserted
+     * @param {Options/Function} options (can be omitted) Options object, supports option 'select' - set to true to automatically select the inserted element
+     * @param {Function} callback function(String), id of the newly inserted element
+     */
+    AH5Communicator.prototype.insertElement = function(element, options, callback) {
         var select = false;
         if (typeof options === 'object') {
             options = options || {};
@@ -263,121 +309,200 @@ 

Source: AH5Communicator.js

} else if (typeof callback === 'undefined' && typeof options === 'function') { callback = options; } - AppAPI.request('editor-insert-element', { - element: jQuery('<div>').append(element).html(), + AppAPI.request('editor-insert-element', { + element: jQuery('<div>').append(element).html(), select: select - }, callback); - }, - - /** - * Remove classes from the element an element in the article - * - * @param {String} id Id of the element - * @param {Array} classes Array of class names - * @param {function} callback function(Boolean) - */ - removeClasses: function(id, classes, callback) { - AppAPI.request('editor-classes-remove', { - id: id, - classes: classes - }, callback); - }, - - /** - * Add new classes to an element - * - * @param {String} id Id of the element - * @param {Array} classes Array of class names - * @param {function} callback function(Boolean) - */ - addClasses: function(id, classes, callback) { - AppAPI.request('editor-classes-add', { - id: id, - classes: classes - }, callback); - }, - - /** - * Mark an element as currently selected (green border with default styling) - * - * @param {String} id Id of the element - * @param {function} callback function(Boolean) - */ - markAsActive: function(id, callback) { - AppAPI.request('editor-mark-as-active', { - id: id - }, callback); - }, - - /** - * Sets the attribute of the element with the given ID to value - * - * @param {String} id The ID of the element to set the attribute on - * @param {String} attribute The attribute to set - * @param {String} value What to set the attribute to - * @param {Function} callback function(Boolean) - */ - setAttributeById: function(id, attribute, value, callback) { - AppAPI.request('editor-element-attribute-set-byid', { - id: id, - attribute: attribute, - value: value - }, callback); - }, - - /** - * Sets a style of the element with the given ID to value - * - * @param {String} id The ID of the element to set the attribute on - * @param {String} attribute The style attribute to set - * @param {String} value What to set the attribute to - * @param {Function} callback function(Boolean) - */ - setStyleById: function(id, attribute, value, callback) { - AppAPI.request('editor-element-style-set-byid', { - id: id, - attribute: attribute, - value: value - }, callback); - }, - - /** - * Initialize pre registered menus + }, callback); + }; + + /** + * Remove classes from the element an element in the article + * + * @param {String} id Id of the element + * @param {Array} classes Array of class names + * @param {function} callback function(Boolean) + */ + AH5Communicator.prototype.removeClasses = function(id, classes, callback) { + AppAPI.request('editor-classes-remove', { + id: id, + classes: classes + }, callback); + }; + + /** + * Add new classes to an element + * + * @param {String} id Id of the element + * @param {Array} classes Array of class names + * @param {function} callback function(Boolean) + */ + AH5Communicator.prototype.addClasses = function(id, classes, callback) { + AppAPI.request('editor-classes-add', { + id: id, + classes: classes + }, callback); + }; + + /** + * Mark an element as currently selected (green border with default styling) + * + * @param {String} id Id of the element + * @param {function} callback function(Boolean) + */ + AH5Communicator.prototype.markAsActive = function(id, callback) { + AppAPI.request('editor-mark-as-active', { + id: id + }, callback); + }; + + /** + * Sets the attribute of the element with the given ID to value + * + * @param {String} id The ID of the element to set the attribute on + * @param {String} attribute The attribute to set + * @param {String} value What to set the attribute to + * @param {Function} callback function(Boolean) + */ + AH5Communicator.prototype.setAttributeById = function(id, attribute, value, callback) { + AppAPI.request('editor-element-attribute-set-byid', { + id: id, + attribute: attribute, + value: value + }, callback); + }; + + /** + * Sets a style of the element with the given ID to value + * + * @param {String} id The ID of the element to set the attribute on + * @param {String} attribute The style attribute to set + * @param {String} value What to set the attribute to + * @param {Function} callback function(Boolean) + */ + AH5Communicator.prototype.setStyleById = function(id, attribute, value, callback) { + AppAPI.request('editor-element-style-set-byid', { + id: id, + attribute: attribute, + value: value + }, callback); + }; + + /** + * Initialize pre registered menus * - * Available options are: simplePluginMenu, editContext - * - * @param {Array} menus Array of menu names - * @param {Function} callback function(Boolean) - */ - initMenu: function(menus, callback) { - AppAPI.request('editor-initialize-menu', { - menus: menus - }, callback); - } + * Available options are: simplePluginMenu, editContext, deleteButton, floatButtons + * + * @param {Array} menus Array of menu names + * @param {Function} callback function(Boolean) + */ + AH5Communicator.prototype.initMenu = function(menus, callback) { + AppAPI.request('editor-initialize-menu', { + menus: menus + }, callback); + }; + + return new AH5Communicator(); + +})(); +
+
+
+ + + + + +
+ +
+
+ + + + DocStrap Copyright © 2012-2014 The contributors to the JSDoc3 and DocStrap projects. + +
+ + + Documentation generated by JSDoc 3.2.2 + on Tue Dec 9th 2014 using the DocStrap template. + +
+
+ + +
+
+ +
+ + + + + + -
- + + -
-
- Documentation generated by JSDoc 3.2.1 on Fri Nov 01 2013 12:31:00 GMT+0100 (CET) -
+ + - - diff --git a/doc/AppAPI.html b/doc/AppAPI.html deleted file mode 100644 index b05eb42..0000000 --- a/doc/AppAPI.html +++ /dev/null @@ -1,2736 +0,0 @@ - - - - - JSDoc: Class: AppAPI - - - - - - - - - - -
- -

Class: AppAPI

- - - - - -
- -
-

- AppAPI -

- -

The basic API object

- -
- -
-
- - - - -
-

new AppAPI()

- - -
-
- - -
-

Namespace for all public Dr.Published methods available from apps.

- -

Listeners can be added through the Listeners objects AppAPI.errorListeners and AppAPI.eventListeners

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 11 -
- - - - - - - -
- - - - - - - - - -
- - -
- - - - - - - - - - - - - - -

Methods

- -
- -
-

<static> __loadArticleRevision(id, callback)

- - -
-
- - -
-

Loads an old revision of an article

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
id - - -Number - - - -

The id of the revision to load

callback - - -Function - - - -

The function to call when the new revision has been loaded

- - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 316 -
- - - - - - - -
- - - - - - - - - -
- - - -
-

<static> addListeners(listeners)

- - -
-
- - -
-

Add listeners.

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
listeners - - -Object - - - -

An object where Key is event name, and value is the callback function. See documentation for Listeners for more information

- - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 306 -
- - - - - - - -
- - - - - - - - - -
- - - -
-

<static> convertDomToHTML(dom) → {String}

- - -
-
- - -
-

Generates proper html code to represent the dom element. This is NOT an asynchronous function

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
dom - - -Object - - - -

The dom node to convert

- - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 376 -
- - - - - - - -
- - - - - - - -
Returns:
- - -
-

The html code

-
- - - -
-
- Type -
-
- -String - - -
-
- - - - -
- - - -
-

<static> createTag(tag, callback)

- - -
-
- - -
-

Creates a new tag

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
tag - - -String - - - -

JSON object with the tag to create, must contain tagTypeId and name properties

callback - - -Function - - - -

function(Boolean)

- - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 328 -
- - - - - - - -
- - - - - - - - - -
- - - -
-

<static> doDirectAuthentication(signature, iv)

- - -
-
- - -
-

Directly authenticates with the DrPublish API with the given -signature and iv

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
signature - - -String - - - -

Signature to send

iv - - -String - - - -

Iv to send

- - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 87 -
- - - - - - - -
- - - - - - - - - -
- - - -
-

<static> doStandardAuthentication(url)

- - -
-
- - -
-

Performs authentication to DrPublish by sending a GET request -to the given URL (or ajax.php?do=authenticate-app if nothing -else is specified), and using .signature and .iv from the response -object as the authentication reply to the DrPublish API

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
url - - -String - - - -

Url to call, default is 'ajax.php?do=authentication-app'

- - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 63 -
- - - - - - - -
- - - - - - - - - -
- - - -
-

<static> generateArticleUrl(id, callback)

- - -
-
- - -
-

Generates an url to a published article

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
id - - -String - - - -

The id of the article to generate url for

callback - - -Function - - - -

function(String), where the parameter is the generated url

- - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 389 -
- - - - - - - -
- - - - - - - - - -
- - - -
-

<static> getAppName() → {String}

- - -
-
- - -
-

Get the name of the loaded app

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 234 -
- - - - - - - -
- - - - - - - -
Returns:
- - -
-

The name of the app, or false if it couldn't be detected

-
- - - -
-
- Type -
-
- -String - - -
-
- - - - -
- - - -
-

<static> getConfiguration(callback)

- - -
-
- - -
-

Get configuration information about the app

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -Function - - - -

function(Object)

- - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 210 -
- - - - - - - -
- - - - - - - - - -
- - - -
-

<static> getCurrentUser(callback)

- - -
-
- - -
-

Gets logged in user

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callback - - -Function - - - -

function(Object)

- - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 340 -
- - - - - - - -
- - - - - - - - - -
- - - -
-

<static> hideLoader()

- - -
-
- - -
-

Hide the loader

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 297 -
- - - - - - - -
- - - - - - - - - -
- - - -
-

<static> initialize()

- - -
-
- - -
-

Constructor for this class

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 15 -
- - - - - - - -
- - - - - - - - - -
- - - -
-

<static> openTagCreationDialog(tag, callback)

- - -
-
- - -
-

Creates a new tag

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
tag - - -String - - - -

The tag to create

callback - - -Function - - - -

function(Boolean)

- - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 189 -
- - - - - - - -
- - - - - - - - - -
- - - -
-

<static> reloadIframe()

- - -
-
- - -
-

Reloads the app's iframe

-
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 198 -
- - - - - - - -
- - - - - - - - - -
- - - -
-

<static> request(callSpec, data, callback)

- - -
-
- - -
-

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

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
callSpec - - -String - - - -

What do you want to call?

data - - -Object - - - -

The data attached to the request

callback - - -Function - - - -

The function to call upon return

- - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 110 -
- - - - - - - -
- - - - - - - - - -
- - - -
-

<static> searchDrLib(data, callback)

- - -
-
- - -
-

Sends a query to DrLib

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
data - - -Object - - - -

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

callback - - -Function - - - -

function(Boolean)

- - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 360 -
- - - - - - - -
- - - - - - - - - -
Example
- -
AppAPI.searchDrLib({
-     query: 'articles.json?q=awesome',
-     secure: true
-     success: function(data) {
-         data.items.forEach(doStuffWithArticle);
-     }
-})
- - -
- - - -
-

<static> setAppName(name)

- - -
-
- - -
-

Set the name of the app

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
name - - -String - - - -

The name of the app

- - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 243 -
- - - - - - - -
- - - - - - - - - -
- - - -
-

<static> setConfiguration(config, onlyPublication, callback)

- - -
-
- - -
-

Set configuration information about the app

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -Object - - - -

The configuration object to save

onlyPublication - - -Boolean - - - -

If true the configuration is set for the current publication only

callback - - -Function - - - -

function()

- - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 221 -
- - - - - - - -
- - - - - - - - - -
- - - -
-

<static> showErrorMsg(msg)

- - -
-
- - -
-

Show error-message to the user

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
msg - - -String - - - -

Message to be displayed

- - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 276 -
- - - - - - - -
- - - - - - - - - -
- - - -
-

<static> showInfoMsg(msg)

- - -
-
- - -
-

Show info-message to the user

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
msg - - -String - - - -

Message to be displayed

- - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 252 -
- - - - - - - -
- - - - - - - - - -
- - - -
-

<static> showLoader(msg)

- - -
-
- - -
-

Show the loader

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
msg - - -String - - - -

Message to display in progress loader

- - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 288 -
- - - - - - - -
- - - - - - - - - -
- - - -
-

<static> showWarningMsg(msg)

- - -
-
- - -
-

Show warning-message to the user

-
- - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
msg - - -String - - - -

Message to be displayed

- - - -
- - - - - - - - - - - - - - - - - - - -
Source:
-
  • - AppAPI.js, line 264 -
- - - - - - - -
- - - - - - - - - -
- -
- - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 3.2.0-dev on Thu Feb 20 2014 15:58:35 GMT+0100 (CET) -
- - - - diff --git a/doc/AppAPI.js.html b/doc/AppAPI.js.html index eb564e6..7591594 100644 --- a/doc/AppAPI.js.html +++ b/doc/AppAPI.js.html @@ -1,167 +1,218 @@ + - - JSDoc: Source: AppAPI.js - - - - - - + + DocStrap Source: AppAPI.js + + + + + + - -
- -

Source: AppAPI.js

- +
+ + +
+ + +
+ +
+ + + +

Source: AppAPI.js

+
+
+
/* global Listeners: true, pm: true */
 
+/* jshint maxstatements:34 */
+var AppAPI = (function() {
+    "use strict";
 
-    
-    
-
-
/* global Listeners: true, pm: true */
-/**
- *
- * Namespace for all public Dr.Published methods available from apps.
- *
- * Listeners can be added through the Listeners objects AppAPI.errorListeners and AppAPI.eventListeners
- * @class
- * @classdesc The basic API object
- *
- */
-var AppAPI = {
-	/**
-	 * Constructor for this class
-	 */
-	initialize: function () {
-		this.DEBUG = false;
-
-		this.Version = '1.0';
-		this.Editor = null;
-		this.Article = null;
-		this.errorListeners = new Listeners();
-		this.eventListeners = new Listeners();
-		this.authenticated = false;
-		this.appName = '';
-
-		var _this = this;
-
-		// Stores requests that couldn't be sent until we've been auth'd
-		this.backlog = [];
-		this.eventListeners.add('appAuthenticated', function() {
-			_this.authenticated = true;
-			if(_this.backlog.length > 0) {
-				if (_this.DEBUG) {
-                    console.warn(_this.getAppName() + ": Authenticated, now executing backlog (" + _this.backlog.length + " items)");
+    /**
+     *
+     * Namespace for all public DrPublish methods available from apps.
+     *
+     * @class
+     * @classdesc The basic API object
+     * @exports AppApi
+     *
+     */
+    var Api = function () {
+        this.DEBUG = false;
+
+        this.Version = '1.0';
+        this.Editor = null;
+        this.Article = null;
+        this.errorListeners = new Listeners();
+        this.eventListeners = new Listeners();
+        this.authenticated = false;
+        this.appName = '';
+
+        var self = this;
+
+        // Stores requests that couldn't be sent until we've been auth'd
+        this.backlog = [];
+        this.eventListeners.add('appAuthenticated', function() {
+            self.authenticated = true;
+            if(self.backlog.length > 0) {
+                if (self.DEBUG) {
+                    console.warn(self.getAppName() + ": Authenticated, now executing backlog (" + self.backlog.length + " items)");
                 }
-				for(var i = _this.backlog.length - 1; i >= 0; i--) {
-					_this.request(_this.backlog[i]['spec'], _this.backlog[i]['data'], _this.backlog[i]['callback']);
-					_this.backlog.splice(i, 1);
-				}
-			}
-		});
-
-		pm.bind("event", function(data) {
-			data = _this.eventListeners.notify(data.type, data.data);
-			if (typeof data === 'undefined') {
-				return true;
-			}
+                for(var i = self.backlog.length - 1; i >= 0; i--) {
+                    self.request(self.backlog[i]['spec'], self.backlog[i]['data'], self.backlog[i]['callback']);
+                    self.backlog.splice(i, 1);
+                }
+            }
+        });
+
+        pm.bind("event", function(data) {
+            data = self.eventListeners.notify(data.type, data.data);
+            if (typeof data === 'undefined') {
+                return true;
+            }
             if (data === false) {
                 return {'abort': true};
             }
-			return data;
-		}, "*");
-	},
-
-	/**
-	 * Performs authentication to DrPublish by sending a GET request
-	 * to the given URL (or ajax.php?do=authenticate-app if nothing
-	 * else is specified), and using .signature and .iv from the response
-	 * object as the authentication reply to the DrPublish API
-	 *
-	 * @param {String} url Url to call, default is 'ajax.php?do=authentication-app'
-	 */
-	doStandardAuthentication: function(url) {
-        var _this = this;
-		url = url || 'ajax.php?do=authenticate-app';
-
-		jQuery.getJSON(url, { app: this.getAppName() },
-			function(reply) {
-				if(reply) {
-					AppAPI.doDirectAuthentication(reply.signature, reply.iv);
-				} else {
-					if (this.DEBUG) {
-                        console.err(_this.getAppName() + ": No authentication token provided by backend", reply);
+            return data;
+        }, "*");
+    };
+
+    /**
+     * Performs authentication to DrPublish by sending a GET request
+     * to the given URL (or ajax.php?do=authenticate-app if nothing
+     * else is specified), and using .signature and .iv from the response
+     * object as the authentication reply to the DrPublish API
+     *
+     * @param {String} url Url to call, default is 'ajax.php?do=authentication-app'
+     */
+    Api.prototype.doStandardAuthentication = function(url) {
+        var self = this;
+        url = url || 'ajax.php?do=authenticate-app';
+
+        jQuery.getJSON(url, {app: this.getAppName()},
+            function(reply) {
+                if(reply) {
+                    self.doDirectAuthentication(reply.signature, reply.iv);
+                } else {
+                    if (this.DEBUG) {
+                        console.err(self.getAppName() + ": No authentication token provided by backend", reply);
                     }
-				}
-			}
-		);
-	},
-
-	/**
-	 * Directly authenticates with the DrPublish API with the given
-	 * signature and iv
-	 *
-	 * @param {String} signature Signature to send
-	 * @param {String} iv Iv to send
-	 */
-	doDirectAuthentication: function(signature, iv) {
-		pm({
-			target: parent,
-			type: "app-loaded",
-			origin: "*",
-			data: {
-				app: this.getAppName (),
-				signature: signature,
-				iv: iv
-			}
-		});
-		if (this.DEBUG) {
+                }
+            }
+        );
+    };
+
+    /**
+     * Directly authenticates with the DrPublish API with the given
+     * signature and iv
+     *
+     * @param {String} signature Signature to send
+     * @param {String} iv Iv to send
+     */
+    Api.prototype.doDirectAuthentication = function(signature, iv) {
+        pm({
+            target: parent,
+            type: "app-loaded",
+            origin: "*",
+            data: {
+                app: this.getAppName (),
+                signature: signature,
+                iv: iv
+            }
+        });
+        if (this.DEBUG) {
             console.log(this.getAppName() + ": Sent app-loaded signal with auth token to DrPublish");
         }
-	},
-
-	/**
-	 * 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
-	 *
-	 * @param {String} callSpec What do you want to call?
-	 * @param {Object} data The data attached to the request
-	 * @param {Function} callback The function to call upon return
-	 */
-	request: function(callSpec, data, callback) {
-
-		if (this.DEBUG) {
+    };
+
+    /**
+     * 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
+     *
+     * @param {String} callSpec What do you want to call?
+     * @param {Object} data The data attached to the request
+     * @param {Function} callback The function to call upon return
+     */
+    Api.prototype.request = function(callSpec, data, callback) {
+        var self = this;
+        if (this.DEBUG) {
             console.info(this.getAppName() + ': Requesting ' + callSpec + ' from parent with data', data);
         }
 
-		if(data == null) {
-			data = {};
-		}
+        if(data == null) {
+            data = {};
+        }
 
-        if (typeof callback !== 'function') {
+        if (typeof callback === 'undefined') {
             callback = null;
         }
 
-		data['src_app'] = this.getAppName ();
+        data['src_app'] = this.getAppName ();
 
-		if(!this.authenticated) {
-			if (this.DEBUG) {
+        if(!this.authenticated) {
+            if (this.DEBUG) {
                 console.warn("Call for " + callSpec + " delayed until app is authenticated");
             }
-			this.backlog.push({ spec: callSpec, data: data, callback: callback });
-			return;
-		}
+            this.backlog.push({ spec: callSpec, data: data, callback: callback });
+            return;
+        }
 
         var createEventFunction = function(func, eventKey) {
             return function() {
-                func.apply(null, arguments);
-                AppAPI.eventListeners.remove(eventKey, eventKey);
+                self.eventListeners.remove(eventKey, eventKey);
+                return func.apply(null, arguments);
             };
         };
 
@@ -170,7 +221,7 @@ 

Source: AppAPI.js

var random = Math.floor(Math.random()*1000); var eventKey = key+random+'functioncallback'+(new Date()).getTime(); var eventFunction = createEventFunction(callback, eventKey); - AppAPI.eventListeners.add(eventKey, eventFunction); + self.eventListeners.add(eventKey, eventFunction); return { type: 'function', eventKey: eventKey @@ -192,220 +243,514 @@

Source: AppAPI.js

}; data = updateObject(data); - var _this = this; - pm({ - target: parent, - type: callSpec, - data: data, - success: callback, - error: function(data) { - _this.errorListeners.notify(data.type, data); - }, - origin: "*", // TODO: Find a way of avoiding all-origins - hash: false - }); - }, - - - /** - * Creates a new tag - * - * @param {String} tag The tag to create - * @param {Function} callback function(Boolean) - */ - openTagCreationDialog: function (tag, callback) { - this.request("create-tag", { - tag: tag - }, callback); - }, - - /** - * Reloads the app's iframe - */ - reloadIframe: function () { - - this.request("app-reload", { - app: this.getAppName () - }); - }, - - /** - * Get the name of the loaded app - * - * @returns {String} The name of the app, or false if it couldn't be detected - */ - getAppName: function () { - return this.appName; - }, - - /** - * Set the name of the app - * - * @param {String} name The name of the app - */ - setAppName: function (name) { - this.appName = name; - }, - - /** - * Show info-message to the user - * - * @param {String} msg Message to be displayed - */ - showInfoMsg: function(msg) { - - this.request("show-message-info", { - message: msg - }); - }, - - /** - * Show warning-message to the user - * - * @param {String} msg Message to be displayed - */ - showWarningMsg: function(msg) { - - this.request("show-message-warning", { - message: msg - }); - }, - - /** - * Show error-message to the user - * - * @param {String} msg Message to be displayed - */ - showErrorMsg: function(msg) { - - this.request("show-message-error", { - message: msg - }); - }, - - /** - * Show the loader - * - * @param {String} msg Message to display in progress loader - */ - showLoader: function(msg) { - this.request("show-loader", { - message: msg - }); - }, - - /** - * Hide the loader - */ - hideLoader: function() { - this.request("hide-loader"); - }, - - /** - * Add listeners. - * - * @param {Object} listeners An object where Key is event name, and value is the callback function. See documentation for Listeners for more information - */ - addListeners: function(listeners) { - AppAPI.eventListeners.addAll(listeners); - }, - - /** - * Loads an old revision of an article - * - * @param {Number} id The id of the revision to load - * @param {Function} callback The function to call when the new revision has been loaded - */ - __loadArticleRevision: function(id, callback) { - this.request("load-revision", { - revision: id - }, callback); - }, - - /** - * Creates a new tag - * - * @param {String} tag JSON object with the tag to create, must contain tagTypeId and name properties - * @param {Function} callback function(Boolean) - */ - createTag: function(tag, callback) { - AppAPI.request('tag-create', { + pm({ + target: parent, + type: callSpec, + data: data, + success: callback, + error: function(data) { + self.errorListeners.notify(data.type, data); + }, + origin: "*", // TODO: Find a way of avoiding all-origins + hash: false + }); + }; + + + /** + * Creates a new tag + * + * @param {String} tag The tag to create + * @param {Function} callback function(Boolean) + */ + Api.prototype.openTagCreationDialog = function (tag, callback) { + this.request("create-tag", { tag: tag }, callback); - }, + }; + + /** + * Reloads the app's iframe + */ + Api.prototype.reloadIframe = function () { - /** - * Sends a query to DrLib + this.request("app-reload", { + app: this.getAppName () + }); + }; + + /** + * Get the name of the loaded app + * + * @returns {String} The name of the app, or false if it couldn't be detected + */ + Api.prototype.getAppName = function () { + return this.appName; + }; + + /** + * Set the name of the app + * + * @param {String} name The name of the app + */ + Api.prototype.setAppName = function (name) { + this.appName = name; + }; + + /** + * Show info-message to the user + * + * @param {String} msg Message to be displayed + */ + Api.prototype.showInfoMsg = function(msg) { + + this.request("show-message-info", { + message: msg + }); + }; + + /** + * Show warning-message to the user + * + * @param {String} msg Message to be displayed + */ + Api.prototype.showWarningMsg = function(msg) { + + this.request("show-message-warning", { + message: msg + }); + }; + + /** + * Show error-message to the user + * + * @param {String} msg Message to be displayed + */ + Api.prototype.showErrorMsg = function(msg) { + + this.request("show-message-error", { + message: msg + }); + }; + + /** + * Show the loader + * + * @param {String} msg Message to display in progress loader + */ + Api.prototype.showLoader = function(msg) { + this.request("show-loader", { + message: msg + }); + }; + + /** + * Hide the loader + */ + Api.prototype.hideLoader = function() { + this.request("hide-loader"); + }; + + /** + * @deprecated Use AppAPI.on(...) instead + */ + Api.prototype.addListeners = function(listeners) { + var createCallback = function(callback) { + return function(data) { + callback(data.data); + }; + }; + for (var eventName in listeners) { + if (listeners.hasOwnProperty(eventName)) { + var callback = listeners[eventName]; + var callWrapper = createCallback(callback); + this.on(eventName, callWrapper); + } + } + }; + + /** + * Loads an old revision of an article + * + * @param {Number} id The id of the revision to load + * @param {Function} callback The function to call when the new revision has been loaded + * @private + */ + Api.prototype.__loadArticleRevision = function(id, callback) { + this.request("load-revision", { + revision: id + }, callback); + }; + + /** + * Creates a new tag + * + * @param {String} tag JSON object with the tag to create, must contain tagTypeId and name properties + * @param {Function} callback function(Boolean) + */ + Api.prototype.createTag = function(tag, callback) { + this.request('tag-create', { + tag: tag + }, callback); + }; + + /** + * Sends a query to DrLib * * @example - * AppAPI.searchDrLib({ - * query: 'articles.json?q=awesome', - * secure: true - * success: function(data) { + * AppAPI.searchDrLib({ + * query: 'articles.json?q=awesome', + * secure: true, + * success: function(data) { * data.items.forEach(doStuffWithArticle); - * } - * }) - * - * @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 - * @param {Function} callback function(Boolean) - * - */ - searchDrLib: function(data, callback) { - AppAPI.request('drlib-search', { + * }, + * error: function(data) { + * console.warn('something went wrong'); + * } + * }) + * + * @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 + * @param {Function} callback function(Boolean) + * + */ + Api.prototype.searchDrLib = function(data, callback) { + this.request('drlib-search', { query: data.query, + access: data.access, secure: data.secure, - success: data.success + success: data.success, + error: data.error }, callback); - }, - - /** - * Generates proper html code to represent the dom element. This is NOT an asynchronous function - * - * @param {Object} dom The dom node to convert - * @return {String} The html code - */ - //TODO: This function should also be able to take a DOMElement or similar. - convertDomToHTML: function(dom) { + }; + + /** + * Generates proper html code to represent the dom element. This is NOT an asynchronous function + * + * @param {Object} dom The dom node to convert + * @return {String} The html code + */ + //TODO: This function should also be able to take a DOMElement or similar. + Api.prototype.convertDomToHTML = function(dom) { if (typeof dom === 'object' && typeof dom.wrap === 'function') { return dom.wrap("<div>").parent().html(); } return ''; - }, - - /** - * Generates an url to a published article - * - * @param {String} id The id of the article to generate url for - * @param {Function} callback function(String), where the parameter is the generated url - */ - generateArticleUrl: function(id, callback) { - AppAPI.request('generate-article-url', { + }; + + /** + * Generates an url to a published article + * + * @param {String} id The id of the article to generate url for + * @param {Function} callback function(String), where the parameter is the generated url + */ + Api.prototype.generateArticleUrl = function(id, callback) { + this.request('generate-article-url', { id: id }, callback); - } -}; + }; -AppAPI.initialize(); -
-
-
+ /** + * Extends the AppAPI with custom functionality that other apps can use + * + * @param {String} group Group name for functionality to add + * @param {String} name Name of the specific function to add + * @param {Function} action function(Object) Function to call when the API is invoked, recieves one parameter as given in AppAPI.callExtendedApi and return value is passed back to the caller + */ + Api.prototype.extendApi = function(group, name, action) { + var self = this; + this.request('extend-api', { + group: group, + name: name, + action: function(data) { + var a = action(data.data); + self.request(data.eventKey, {'data': a}); + } + }); + }; + /** + * Call the extended AppAPI + * + * @param {String} group Group name for functionality to call + * @param {String} name Name of the specific function to call + * @param {Object} data Data object to pass as parameter to the api call + * @param {Function} action function(Object) Function to recieve the API response, parameter is the response from the API call + */ + Api.prototype.callExtendedApi = function(group, name, data, callback) { + this.request('call-extended-api', { + group: group, + name: name, + data: data, + callback: callback + }); + }; + + /** + * Gets logged in user + * + * @param {Function} callback function(Object) + */ + Api.prototype.getCurrentUser = function(callback) { + this.request('get-current-user', null, callback); + }; + + /** + * Get configuration information about the app + * + * @param {Function} callback function(Object) + */ + Api.prototype.getConfiguration = function (callback) { + this.request('get-configuration', null, callback); + }; + + /** + * Set configuration information about the app + * + * @param {Object} config The configuration object to save + * @param {Object} options Object, can have three keys. + * 'onlyPublication' (boolean) If true the configuration is set for the current publication only + * 'success' (function) Called if the configuration was saved successfully + * 'error' (function) Called if there was an error, recieves and error object as first parameter + * @param {Function} callback function() + */ + Api.prototype.setConfiguration = function (config, options, callback) { + // support old function signature + if (typeof options === 'boolean') { + options = { + onlyPublication: options + }; + } else if (typeof options !== 'object' || options === null) { + options = {}; + } + var data = { + config: config, + onlyPublication: typeof options.onlyPublication === 'boolean' ? options.onlyPublication : false, + success: typeof options.success === 'function' ? options.success : null, + error: typeof options.error === 'function' ? options.error : null + }; + this.request('set-configuration', data, callback); + }; + + /** + * Emits an event to DrPublish, and possibly other apps + * + * @param {String} name Name of the event + * @param {String} data Data object to send with the event + */ + Api.prototype.emit = function(name, data) { + this.request('emit-api-event', { + name: name, + data: data + }); + }; + + /** + * 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. + * + * @param {String} name Name of the event + * @param {Function} callback function(Object) Function to call when the event is triggered. Recieves one data object parameter of the form {source: <source app name or DrPublish>, data: <data object>} + */ + Api.prototype.on = function(name, callback) { + var self = this; + self.eventListeners.add(name, callback); + this.request('on-api-event', { + name: name, + }); + }; + + /** + * Increase the counter of actions required by the user, used to tell the user that the plugin requires input of some kind + * + * @param {Function} callback function(Object) function to call once the counter has been increased, returns the new counter value + */ + Api.prototype.increaseRequiredActionCounter = function(callback) { + this.request('increase-required-action-counter', {}, callback); + }; + + /** + * Decrease the counter of actions required by the user, used to tell the user that the plugin requires input of some kind + * + * @param {Function} callback function(Object) function to call once the counter has been decrease, returns current counter value + */ + Api.prototype.decreaseRequiredActionCounter = function(callback) { + this.request('decrease-required-action-counter', {}, callback); + }; + + /** + * Clear the counter of actions required by the user, used to tell the user that the plugin requires input of some kind + * + * @param {Function} callback function(Object) function to call once the counter has been cleared + */ + Api.prototype.clearRequiredActionCounter = function(callback) { + this.request('clear-required-action-counter', {}, callback); + }; + + /** + * Set the counter of actions required by the user, used to tell the user that the plugin requires input of some kind + * + * @param {Number} count The value to set the counter to + * @param {Function} callback function(Object) function to call once the counter has been cleared + */ + Api.prototype.setRequiredActionCounter = function(count, callback) { + this.request('set-required-action-counter', {count: count}, callback); + }; + + /** + * Create a new instance of the Api class + * + * @private + */ + Api.prototype.create = function() { + return new Api(); + }; + + /** + * Create an embedded object of the given type + * + * @param {Number} typeId Type Id of the embedded object to create + * @param {Function} callback function(embeddedObjectId) called once the object has been created, first parameter is the new embedded object id + */ + Api.prototype.createEmbeddedObject = function(typeId, callback) { + this.request('create-embedded-object', {typeId: typeId, callback: callback}); + }; + + /** + * Get information about the available embedded object types + * + * @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'}` + */ + Api.prototype.getEmbeddedObjectTypes = function(callback) { + this.request('get-embedded-object-types', null, callback); + }; + + /** + * Gives focus to another plugin + * + * @param {String} pluginName The name of the plugin to recieve focus + * @param {Object} argument Optional option argument to pass along to the plugin recieving focus + * @param {Boolean} start Flag to decide if the plugin should be started if it has not been loaded previously, default true + */ + Api.prototype.giveFocus = function(pluginName, argument, start) { + if (typeof pluginName !== 'string' || pluginName === '') { + return false; + } + if (typeof start !== 'boolean') { + start = true; + } + this.request('give-focus', {pluginName: pluginName, start: start, argument: argument}); + return true; + }; + + + /** + * Hide the plugin, so it is no longer visible on the list of open plugins + */ + Api.prototype.hide = function() { + this.request('hide'); + return true; + }; + + return new Api(); +})(); +
+
+
+ + + + + +
+ +
+
+ + + + DocStrap Copyright © 2012-2014 The contributors to the JSDoc3 and DocStrap projects. + +
+ + + Documentation generated by JSDoc 3.2.2 + on Tue Dec 9th 2014 using the DocStrap template. + +
+
+ + +
+
+ +
+ + + + + + -
- + + -
-
- Documentation generated by JSDoc 3.2.1 on Fri Nov 01 2013 12:31:00 GMT+0100 (CET) -
+ + - - diff --git a/doc/ArticleCommunicator.html b/doc/Article.html similarity index 56% rename from doc/ArticleCommunicator.html rename to doc/Article.html index 70808b0..b4d506a 100644 --- a/doc/ArticleCommunicator.html +++ b/doc/Article.html @@ -1,130 +1,151 @@ + - - JSDoc: Class: ArticleCommunicator - - - - - - - - - + + Documentation Module: AppAPI/Article -
- -

Class: ArticleCommunicator

- - + + + + + +
+ + +
+ + +
+ +
+ + + +

Module: AppAPI/Article

- +

- ArticleCommunicator + AppAPI/Article

-

Functions for talking with the DrPublish article object. Accessed through AppAPI.Article

+
Functions for talking with the DrPublish article object. Accessed through AppAPI.Article
-
+
- + -
-

new ArticleCommunicator()

- - -
-
- - -
-

This class is used for communicating with the article, typically setting and getting values of metadata or in the article content itself.

-
- +
This class is used for communicating with the article, typically setting and getting values of metadata or in the article content itself.
+ - - - - - - - -
- - - - +
+ - - - - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 8 -
- - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - -
+
+ + + + + + - - - - - - - +

Methods

- +
-

<static> addAuthors(authors, callback)

+

addAuthors(authors, callback)

@@ -132,7 +153,7 @@

<static> -

Add the given authors to the list of authors

+ Add the given authors to the list of authors

@@ -144,31 +165,31 @@

<static> Parameters:

- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
authors @@ -177,77 +198,79 @@
Parameters:

List of authors to add

List of authors to add
callback -Function +function

function(Boolean), called when it has been set

function(Boolean), called when it has been set
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 270 -
- - - - - - - - + @@ -260,7 +283,7 @@
Parameters:
-

<static> addCategories(categories, callback)

+

addCategories(categories, callback)

@@ -268,7 +291,7 @@

<static> -

Add the given categories to the list of categories

+ Add the given categories to the list of categories

@@ -280,31 +303,31 @@

<static> Parameters:

- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
categories @@ -313,77 +336,79 @@
Parameters:

List of category IDs to add

List of category IDs to add
callback -Function +function

function(Boolean), called when the categories have been set

function(Boolean), called when the categories have been set
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 148 -
- - - - - - - - + @@ -396,7 +421,7 @@
Parameters:
-

<static> addDossiers(dossiers, callback)

+

addDossiers(dossiers, callback)

@@ -404,7 +429,7 @@

<static> -

Add the given dossiers to the list of dossiers

+ Add the given dossiers to the list of dossiers

@@ -416,31 +441,31 @@

<static> Parameters:

- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
dossiers @@ -449,77 +474,79 @@
Parameters:

List of dossiers to add

List of dossiers to add
callback -Function +function

function(Boolean), called when it has been set

function(Boolean), called when it has been set
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 303 -
- - - - - - - - + @@ -532,7 +559,7 @@
Parameters:
-

<static> addTag(tag, errorFunction, callback)

+

addTag(tag, errorFunction, callback)

@@ -540,7 +567,7 @@

<static> add
-

Add tag for the article

+ Add tag for the article
@@ -552,31 +579,31 @@

<static> add

Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
tag @@ -585,100 +612,102 @@
Parameters:

Tag to be added

Tag to be added
errorFunction -Function +function

called if error

called if error
callback -Function +function

function(Boolean), called when tag has been set

function(Boolean), called when tag has been set
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 91 -
- - - - - - - - + @@ -691,7 +720,7 @@
Parameters:
-

<static> clearMetaInfo(callback)

+

clearMetaInfo(callback)

@@ -699,7 +728,7 @@

<static> -

Clear the meta information summary

+ Clear the meta information summary

@@ -711,87 +740,89 @@

<static> Parameters:

- +
- + + + - - - + - + - + - + + + - - - - + + - +
NameTypeDescription
callback -Function +function

function(Boolean), called when meta data has been cleared

function(Boolean), called when meta data has been cleared
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 57 -
- - - - - - - - + @@ -804,7 +835,7 @@
Parameters:
-

<static> focusApp(callback)

+

focusApp(callback)

@@ -812,7 +843,7 @@

<static> f
-

Give focus to yourself

+ Give focus to yourself
@@ -824,87 +855,89 @@

<static> f

Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + - +
NameTypeDescription
callback -Function +function

function(Boolean), called as the app gets focus

function(Boolean), called as the app gets focus
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 15 -
- - - - - - - - + @@ -917,7 +950,7 @@
Parameters:
-

<static> getArticletypeId(callback)

+

getArticletypeId(callback)

@@ -925,7 +958,7 @@

<static>
-

Get the article type of the current article

+ Get the article type of the current article
@@ -937,87 +970,89 @@

<static>
Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + - +
NameTypeDescription
callback -Function +function

function(Int)

function(Int)
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 347 -
- - - - - - - - + @@ -1030,7 +1065,7 @@
Parameters:
-

<static> getAuthors(callback)

+

getAuthors(callback)

@@ -1038,7 +1073,7 @@

<static> -

Get the authors set in the article

+ Get the authors set in the article

@@ -1050,87 +1085,89 @@

<static> Parameters:

- +
- + + + - - - + - + - + - + + + - - - - + + - +
NameTypeDescription
callback -Function +function

function([String]), currently set authors

function([String]), currently set authors
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 248 -
- - - - - - - - - - + @@ -1143,7 +1180,7 @@
Parameters:
-

<static> getByline(callback)

+

getByline(callback)

@@ -1151,7 +1188,7 @@

<static>
-

Get the current byline

+ Get the current byline
@@ -1163,31 +1200,31 @@

<static>

Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + - +
NameTypeDescription
callback @@ -1196,54 +1233,56 @@
Parameters:

function(String), xml string with the current byline

function(String), xml string with the current byline
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 394 -
- - - - - - - - + @@ -1256,7 +1295,7 @@
Parameters:
-

<static> getCurrentContent(callback)

+

getCurrentContent(callback)

@@ -1264,7 +1303,7 @@

<static>
-

Gets the current article content

+ Gets the current article content
@@ -1276,87 +1315,89 @@

<static>
Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + - +
NameTypeDescription
callback -Function +function

function(Object Content)

function(Object Content)
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 326 -
- - - - - - - - + @@ -1369,7 +1410,7 @@
Parameters:
-

<static> getDossiers(callback)

+

getCustomMeta(name, callback)

@@ -1377,7 +1418,7 @@

<static> -

Get the dossiers set in the article

+ Retrieve custom meta value for the article @@ -1389,58 +1430,110 @@

<static> Parameters:

- +
- + + + - - - + - + - + - - + + + + + + + + + + + + + + + + + + + - + + - +
NameTypeDescription
callbackname -Function +String Name of the custom meta value
callback + +function + + +

function([Object Dossiers]), current dossiers

function(Object), the parameter is an object containing the given custom meta value
+
- - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + @@ -1450,27 +1543,115 @@
Parameters:
+ + + + +
+

getDossiers(callback)

+
+
+
+ Get the dossiers set in the article +
+ -
Source:
-
  • - ArticleCommunicator.js, line 293 -
+
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
callback + + +function + + + + function([Object Dossiers]), current dossiers
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + @@ -1482,7 +1663,7 @@
Parameters:
-

<static> getId(callback)

+

getGeolocations(callback)

@@ -1490,7 +1671,7 @@

<static> getI
-

Get the id of the article currently edited

+ Get geolocation
@@ -1502,87 +1683,89 @@

<static> getI

Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + - +
NameTypeDescription
callback -Function +function

function(Int), id of the current article

function(Object), retrieves the currently set geo location
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 48 -
- - - - - - - - + @@ -1595,7 +1778,7 @@
Parameters:
-

<static> getPublishedDatetime(callback)

+

getId(callback)

@@ -1603,7 +1786,7 @@

<stat
-

Get the published-date

+ Get the id of the article currently edited
@@ -1615,87 +1798,89 @@

<stat
Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + - +
NameTypeDescription
callback -Function +function

function(String), current published datetime

function(Int), id of the current article
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 227 -
- - - - - - - - + @@ -1708,7 +1893,7 @@
Parameters:
-

<static> getSelectedCategories(callback)

+

getKeywords(callback)

@@ -1716,7 +1901,7 @@

<sta
-

Get the selected categories

+ Get the current set of keywords on the article
@@ -1728,87 +1913,89 @@

<sta
Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + - +
NameTypeDescription
callback -Function +function

function([String]), array with category ids

Function to call with the result
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 115 -
- - - - - - - - + @@ -1821,7 +2008,7 @@
Parameters:
-

<static> getSource(callback)

+

getPublishedDatetime(callback)

@@ -1829,7 +2016,7 @@

<static>
-

Get the source set for the article

+ Get the published-date
@@ -1841,87 +2028,89 @@

<static>

Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + - +
NameTypeDescription
callback -Function +function

function(String), name of the source

function(String), current published datetime
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 184 -
- - - - - - - - + @@ -1934,7 +2123,7 @@
Parameters:
-

<static> getStatus(callback)

+

getSelectedCategories(callback)

@@ -1942,7 +2131,7 @@

<static>
-

Get the status for the article

+ Get the selected categories
@@ -1954,87 +2143,89 @@

<static>

Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + - +
NameTypeDescription
callback -Function +function

function(String), current status

function([String]), array with category ids
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 206 -
- - - - - - - - + @@ -2047,7 +2238,7 @@
Parameters:
-

<static> getTags(callback)

+

getSource(callback)

@@ -2055,7 +2246,7 @@

<static> ge
-

Get tags used in the article

+ Get the source set for the article
@@ -2067,87 +2258,89 @@

<static> ge

Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + - +
NameTypeDescription
callback -Function +function

function([Object Tag]), array with tags connected to an article

function(String), name of the source
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 66 -
- - - - - - - - + @@ -2160,7 +2353,7 @@
Parameters:
-

<static> maximizeAppWindow(title, onClose)

+

getStatus(callback)

@@ -2168,7 +2361,7 @@

<static>
-

Maximize the app view

+ Get the status for the article
@@ -2180,54 +2373,31 @@

<static>
Parameters:
- +
- + + + - - - + - + - - - - - - - - - - - - - - - - - - - + + + + - - - - + + - +
NameTypeDescription
title - - -String - - -

Title to give the maximized view

onClosecallback @@ -2236,54 +2406,56 @@
Parameters:

Function to call when the window is closed/minimized

function(String), current status
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 369 -
- - - - - - - - + @@ -2296,7 +2468,7 @@
Parameters:
-

<static> removeAuthors(authors, callback)

+

getTags(callback)

@@ -2304,7 +2476,7 @@

<static> -

Remove the given authors from the list of authors

+ Get tags used in the article @@ -2316,110 +2488,89 @@

<static> Parameters:

- +
- + + + - - - + - + - - - - - - - - - - - - - - - - - - + + + - - - - + + - +
NameTypeDescription
authors - - -Array - - -

List of authors to remove

callback -Function +function

function([String]), author list as it is after the authors has been removed

function([Object Tag]), array with tags connected to an article
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 282 -
- - - - - - - - + @@ -2432,7 +2583,7 @@
Parameters:
-

<static> removeCategories(categories, callback)

+

maximizeAppWindow(title, onClose)

@@ -2440,7 +2591,7 @@

<static>
-

Remove the given categories from the list of categories

+ Maximize the app view
@@ -2452,110 +2603,112 @@

<static>
Parameters:
- +
- + + + - - - + - + - + - - + + + + - - - - + + + - - + - - + + + + - - - - + + - +
NameTypeDescription
categoriestitle -Array +String

List of category IDs to remove

Title to give the maximized view
callbackonClose -Function +function

function(Boolean), called when the categories have been removed

Function to call when the window is closed/minimized
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 161 -
- - - - - - - - + @@ -2568,7 +2721,7 @@
Parameters:
-

<static> removeDossiers(dossiers, callback)

+

removeAuthors(authors, callback)

@@ -2576,7 +2729,7 @@

<static> -

Remove the given dossiers from the list of dossiers

+ Remove the given authors from the list of authors @@ -2588,31 +2741,31 @@

<static> Parameters:

- +
- + + + - - - + - + - + - - + + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
dossiersauthors @@ -2621,77 +2774,79 @@
Parameters:

List of authors to remove

List of authors to remove
callback -Function +function

function([Object Dossiers]), current dossiers

function([String]), author list as it is after the authors has been removed
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 315 -
- - - - - - - - + @@ -2704,7 +2859,7 @@
Parameters:
-

<static> removeTag(tag, callback)

+

removeCategories(categories, callback)

@@ -2712,7 +2867,7 @@

<static>
-

Remove tag from article

+ Remove the given categories from the list of categories
@@ -2724,110 +2879,112 @@

<static>

Parameters:
- +
- + + + - - - + - + - + - - + + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
tagcategories -String +Array

Tag to remove

List of category IDs to remove
callback -Function +function

function(Boolean), called when tag has been removed

function(Boolean), called when the categories have been removed
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 104 -
- - - - - - - - + @@ -2840,7 +2997,7 @@
Parameters:
-

<static> restoreAppWindow(callback)

+

removeDossiers(dossiers, callback)

@@ -2848,7 +3005,7 @@

<static>
-

Restore the app pane to the default size

+ Remove the given dossiers from the list of dossiers
@@ -2860,31 +3017,54 @@

<static>
Parameters:
- +
- + + + - - - + - + + + + + + + + + + + + + + + + + - + + + + + + + + + + + +
NameTypeDescription
dossiers + + +Array + + + + List of authors to remove
callback @@ -2893,54 +3073,700 @@
Parameters:
function([Object Dossiers]), current dossiers
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+

removeTag(tag, callback)

+ + +
+
+ + +
+ Remove tag from article +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + +
NameTypeDescription
tag + +String + + +

Callback to call after everything is done

Tag to remove
callback + + +function + + + + function(Boolean), called when tag has been removed
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + +
+ + +
+

restoreAppWindow(callback)

+ + +
+
+ +
+ Restore the app pane to the default size +
+ + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
callback + + +function + + + + Callback to call after everything is done
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

saveCategories(callback)

+ + +
+
+ + +
+ Save the currently selected categories +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
callback + + +function + + + + function(Boolean), called when categories has been saved
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

setArticletypeId(articletypeId, callback)

+ + +
+
+ + +
+ Set the article type of the current article +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
articletypeId + + +Number + + + + The new article type of the article
callback + + +function + + + + function(Boolean), called when it has been set
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

setAuthors(authors, callback)

+ + +
+
+ + +
+ Set authors for the article +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
authors + + +Array + + + + List of authors that should be set
callback + + +function + + + + function(Boolean), called when it has been set
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 385 -
- - - - - - - - + @@ -2953,7 +3779,7 @@
Parameters:
-

<static> saveCategories(callback)

+

setByline(byline, save, callback)

@@ -2961,7 +3787,7 @@

<static> -

Save the currently selected categories

+ Set the byline @@ -2973,87 +3799,135 @@

<static> Parameters:

- +
- + + + - - - + - + - + - - + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + +
NameTypeDescription
callbackbyline -Function +String XML version of byline to use
save + +Boolean + + +

function(Boolean), called when categories has been saved

If true, force save after updating byline information
callback + + +function + + + + function(Boolean), called when it has been set
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 124 -
- - - - - - - - + @@ -3066,7 +3940,7 @@
Parameters:
-

<static> setArticletypeId(articletypeId, callback)

+

setCategories(categories, callback)

@@ -3074,7 +3948,7 @@

<static>
-

Set the article type of the current article

+ Set selected categories
@@ -3086,110 +3960,112 @@

<static>
Parameters:
- +
- + + + - - - + - + - + - - + + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
articletypeIdcategories -Number +Array

The new article type of the article

List of category IDs that should be set
callback -Function +function

function(Boolean), called when it has been set

function(Boolean), called when categories have been set
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 357 -
- - - - - - - - + @@ -3202,7 +4078,7 @@
Parameters:
-

<static> setAuthors(authors, callback)

+

setCurrentContent(content, callback)

@@ -3210,7 +4086,7 @@

<static> -

Set authors for the article

+ Updates current article content @@ -3222,110 +4098,112 @@

<static> Parameters:

- +
- + + + - - - + - + - + - - + + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
authorscontent -Array +String

List of authors that should be set

The new content for the article
callback -Function +function

function(Boolean), called when it has been set

function(Boolean), called when it has been set
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 258 -
- - - - - - - - + @@ -3338,7 +4216,7 @@
Parameters:
-

<static> setByline(byline, save, callback)

+

setCustomMeta(name, value, callback)

@@ -3346,7 +4224,7 @@

<static>
-

Set the byline

+ Set custom meta value for the article
@@ -3358,31 +4236,31 @@

<static>

Parameters:
- +
- + + + - - - + - + - + - - + + + + - - - - + + + - - + - - + + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
bylinename @@ -3391,100 +4269,102 @@
Parameters:

XML version of byline to use

Name of the meta value
savevalue -Boolean +Object

If true, force save after updating byline information

Value to set
callback -Function +function

function(Boolean), called when it has been set

function()
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 405 -
- - - - - - - - + @@ -3497,7 +4377,7 @@
Parameters:
-

<static> setCategories(categories, callback)

+

setGeolocations(geolocations, callback)

@@ -3505,7 +4385,7 @@

<static> -

Set selected categories

+ Set geolocation @@ -3517,110 +4397,112 @@

<static> Parameters:

- +
- + + + - - - + - + - + - - + + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
categoriesgeolocations -Array +Object

List of category IDs that should be set

The location to set
callback -Function +function

function(Boolean), called when categories have been set

function(Boolean), called when it has been set
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 136 -
- - - - - - - - + @@ -3633,7 +4515,7 @@
Parameters:
-

<static> setCurrentContent(content, callback)

+

setKeywords(keywords, callback)

@@ -3641,7 +4523,7 @@

<static>
-

Updates current article content

+ Set the keyword-list on the article
@@ -3653,110 +4535,112 @@

<static>
Parameters:
- +
- + + + - - - + - + - + - - + + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
contentkeywords -String +Array

The new content for the article

List of keywords to add
callback -Function +function

function(Boolean), called when it has been set

Function to call when keywords have been set
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 336 -
- - - - - - - - + @@ -3769,7 +4653,7 @@
Parameters:
-

<static> setMainCategory(category, callback)

+

setMainCategory(category, callback)

@@ -3777,7 +4661,7 @@

<static> <
-

Set the main category of the current article

+ Set the main category of the current article
@@ -3789,31 +4673,31 @@

<static> <
Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
category @@ -3822,77 +4706,79 @@
Parameters:

The ID of the category to set as the main category

The ID of the category to set as the main category
callback -Function +function

function(Boolean), called when the main category has been set

function(Boolean), called when the main category has been set
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 173 -
- - - - - - - - + @@ -3905,7 +4791,7 @@
Parameters:
-

<static> setPublishedDatetime(published, callback)

+

setPublishedDatetime(published, callback)

@@ -3913,7 +4799,7 @@

<stat
-

Set the published-date

+ Set the published-date
@@ -3925,31 +4811,31 @@

<stat
Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + - - - -
NameTypeDescription
published @@ -3958,77 +4844,79 @@
Parameters:

Date to be set (YYYY-MM-DD HH:MM:SS)

Date to be set (YYYY-MM-DD HH:MM:SS)
callback -Function +function

function(Boolean), called when done

function(Boolean), called when done
- - - -
- - - - - + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 237 -
- - - - - - - -
+ @@ -4041,7 +4929,7 @@
Parameters:
-

<static> setSource(value, callback)

+

setSource(value, callback)

@@ -4049,7 +4937,7 @@

<static>
-

Set the source for the article

+ Set the source for the article
@@ -4061,31 +4949,31 @@

<static>

Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
value @@ -4094,77 +4982,79 @@
Parameters:

The new value to be set as source

The new value to be set as source
callback -Function +function

function(Boolean), called when the source has been set

function(Boolean), called when the source has been set
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 195 -
- - - - - - - - + @@ -4177,7 +5067,7 @@
Parameters:
-

<static> setStatus(status, callback)

+

setStatus(status, callback)

@@ -4185,7 +5075,7 @@

<static>
-

Set the status for the article

+ Set the status for the article
@@ -4197,31 +5087,31 @@

<static>

Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
status @@ -4230,77 +5120,79 @@
Parameters:

The new status to be set (draft, waiting, published)

The new status to be set (draft, waiting, published)
callback -Function +function

function(Boolean), called when the source has been set

function(Boolean), called when the source has been set
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 216 -
- - - - - - - - + @@ -4313,7 +5205,7 @@
Parameters:
-

<static> setTags(tags, save, callback)

+

setTags(tags, save, callback)

@@ -4321,7 +5213,7 @@

<static> se
-

Set tags for the article

+ Set tags for the article
@@ -4333,31 +5225,31 @@

<static> se

Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
tags @@ -4366,21 +5258,21 @@
Parameters:

List of tags that should be set

List of tags that should be set
save @@ -4389,77 +5281,79 @@
Parameters:

Set to true to force save once the tags are updated

Set to true to force save once the tags are updated
callback -Function +function

function(Boolean), called when tags have been set

function(Boolean), called when tags have been set
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 77 -
- - - - - - - - + @@ -4472,7 +5366,7 @@
Parameters:
-

<static> startApp(name, options, callback)

+

startApp(name, options, callback)

@@ -4480,7 +5374,7 @@

<static> s
-

Start the given app

+ Start the given app
@@ -4492,31 +5386,31 @@

<static> s

Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
name @@ -4525,21 +5419,21 @@
Parameters:

Name of the app from settings.php

Name of the app from settings.php
options @@ -4548,77 +5442,79 @@
Parameters:

Options for initializing the app

Options for initializing the app
callback -Function +function

function(Boolean), called after app is started

function(Boolean), called after app is started
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 25 -
- - - - - - - - + @@ -4631,7 +5527,7 @@
Parameters:
-

<static> stopApp(name)

+

stopApp(name)

@@ -4639,7 +5535,7 @@

<static> st
-

Stop the given app

+ Stop the given app
@@ -4651,31 +5547,31 @@

<static> st

Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + - +
NameTypeDescription
name @@ -4684,54 +5580,56 @@
Parameters:

Name of the app from settings.php

Name of the app from settings.php
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - ArticleCommunicator.js, line 37 -
- - - - - - - - + @@ -4743,29 +5641,107 @@
Parameters:
+ - - + - + + + - +
+ + - + +
+
+
+ +
+ -
+ + + + + -
- Documentation generated by JSDoc 3.2.0-dev on Thu Feb 20 2014 15:58:35 GMT+0100 (CET) -
+ + + + + + + + + + - - + \ No newline at end of file diff --git a/doc/ArticleCommunicator.js.html b/doc/ArticleCommunicator.js.html index 17a043a..15d10f6 100644 --- a/doc/ArticleCommunicator.js.html +++ b/doc/ArticleCommunicator.js.html @@ -1,337 +1,443 @@ + - - JSDoc: Source: ArticleCommunicator.js - - - - - - + + DocStrap Source: ArticleCommunicator.js + + + + + + - -
- -

Source: ArticleCommunicator.js

- +
+ + +
+ + +
+ +
+ + + +

Source: ArticleCommunicator.js

+
+
+
/* global AppAPI: true */
 
+/* jshint maxstatements:44 */
 
-    
-    
-
-
/* global AppAPI: true */
-/**
- * This class is used for communicating with the article, typically setting and getting values of metadata or in the article content itself.
- *
- * @class
- * @classdesc Functions for talking with the DrPublish article object. Accessed through AppAPI.Article
- */
-var ArticleCommunicator = {
-
-	/**
-	 * Give focus to yourself
-	 *
-	 * @param {Function} callback function(Boolean), called as the app gets focus
-	 */
-	focusApp: function(callback) {
-		AppAPI.request("app-focus", {}, callback);
-	},
-	/**
-	 * Start the given app
-	 *
-	 * @param {String} name Name of the app from settings.php
-	 * @param {Object} options Options for initializing the app
-	 * @param {Function} callback function(Boolean), called after app is started
-	 */
-	startApp: function(name, options, callback) {
-		AppAPI.request("app-start", {
-			app: name,
-			option: options
-		}, callback);
-	},
-
-	/**
-	 * Stop the given app
-	 *
-	 * @param {String} name Name of the app from settings.php
-	 */
-	stopApp: function(name) {
-		AppAPI.request("app-stop", {
-			app: name
-		});
-	},
-
-	/**
-	 * Get the id of the article currently edited
-	 *
-	 * @param {Function} callback function(Int), id of the current article
-	 */
-	getId: function(callback) {
-		AppAPI.request('article-id-get', null, callback);
-	},
-
-	/**
-	 * Clear the meta information summary
-	 *
-	 * @param {Function} callback function(Boolean), called when meta data has been cleared
-	 */
-	clearMetaInfo: function(callback) {
-		AppAPI.request("article-metainfo-clear", null, callback);
-	},
-
-	/**
-	 * Get tags used in the article
-	 *
-	 * @param {Function} callback function([Object Tag]), array with tags connected to an article
-	 */
-	getTags: function(callback) {
-		AppAPI.request("article-tags-get", null, callback);
-	},
-
-	/**
-	 * Set tags for the article
-	 *
-	 * @param {Array} tags List of tags that should be set
-	 * @param {Boolean} save Set to true to force save once the tags are updated
-	 * @param {Function} callback function(Boolean), called when tags have been set
-	 */
-	setTags: function(tags, save, callback) {
-		AppAPI.request('article-tags-set', {
+AppAPI.Article = (function() {
+    "use strict";
+
+    /**
+     * This class is used for communicating with the article, typically setting and getting values of metadata or in the article content itself.
+     *
+     * @class
+     * @classdesc Functions for talking with the DrPublish article object. Accessed through AppAPI.Article
+     * @exports AppAPI/Article
+     */
+    var ArticleCommunicator = function() {
+        this.DEBUG = false;
+    };
+
+    /**
+     * Give focus to yourself
+     *
+     * @param {Function} callback function(Boolean), called as the app gets focus
+     */
+    ArticleCommunicator.prototype.focusApp = function(callback) {
+        AppAPI.request("app-focus", {}, callback);
+    };
+    /**
+     * Start the given app
+     *
+     * @param {String} name Name of the app from settings.php
+     * @param {Object} options Options for initializing the app
+     * @param {Function} callback function(Boolean), called after app is started
+     */
+    ArticleCommunicator.prototype.startApp = function(name, options, callback) {
+        AppAPI.request("app-start", {
+            app: name,
+            option: options
+        }, callback);
+    };
+
+    /**
+     * Stop the given app
+     *
+     * @param {String} name Name of the app from settings.php
+     */
+    ArticleCommunicator.prototype.stopApp = function(name) {
+        AppAPI.request("app-stop", {
+            app: name
+        });
+    };
+
+    /**
+     * Get the id of the article currently edited
+     *
+     * @param {Function} callback function(Int), id of the current article
+     */
+    ArticleCommunicator.prototype.getId = function(callback) {
+        AppAPI.request('article-id-get', null, callback);
+    };
+
+    /**
+     * Clear the meta information summary
+     *
+     * @param {Function} callback function(Boolean), called when meta data has been cleared
+     */
+    ArticleCommunicator.prototype.clearMetaInfo = function(callback) {
+        AppAPI.request("article-metainfo-clear", null, callback);
+    };
+
+    /**
+     * Get tags used in the article
+     *
+     * @param {Function} callback function([Object Tag]), array with tags connected to an article
+     */
+    ArticleCommunicator.prototype.getTags = function(callback) {
+        AppAPI.request("article-tags-get", null, callback);
+    };
+
+    /**
+     * Retrieve custom meta value for the article
+     *
+     * @param {String} name Name of the custom meta value
+     * @param {Function} callback function(Object), the parameter is an object containing the given custom meta value
+     */
+    ArticleCommunicator.prototype.getCustomMeta = function(name, callback) {
+        AppAPI.request('article-custom-meta-get', {
+            name: name
+        }, callback);
+    };
+
+    /**
+     * Set custom meta value for the article
+     *
+     * @param {String} name Name of the meta value
+     * @param {Object} value Value to set
+     * @param {Function} callback function()
+     */
+    ArticleCommunicator.prototype.setCustomMeta = function(name, value, callback) {
+        AppAPI.request('article-custom-meta-set', {
+            name: name,
+            value: value
+        }, callback);
+    };
+
+    /**
+     * Set tags for the article
+     *
+     * @param {Array} tags List of tags that should be set
+     * @param {Boolean} save Set to true to force save once the tags are updated
+     * @param {Function} callback function(Boolean), called when tags have been set
+     */
+    ArticleCommunicator.prototype.setTags = function(tags, save, callback) {
+        AppAPI.request('article-tags-set', {
             save: save,
-			tags: tags
-		}, callback);
-	},
-
-	/**
-	 * Add tag for the article
-	 *
-	 * @param {String} tag Tag to be added
+            tags: tags
+        }, callback);
+    };
+
+    /**
+     * Add tag for the article
+     *
+     * @param {String} tag Tag to be added
      * @param {Function} errorFunction called if error
-	 * @param {Function} callback function(Boolean), called when tag has been set
-	 */
-	addTag: function(tag, errorFunction, callback) {
-		AppAPI.request('article-tags-add', {
-			tag: tag,
+     * @param {Function} callback function(Boolean), called when tag has been set
+     */
+    ArticleCommunicator.prototype.addTag = function(tag, errorFunction, callback) {
+        AppAPI.request('article-tags-add', {
+            tag: tag,
             onError: errorFunction
-		}, callback);
-	},
-
-	/**
-	 * Remove tag from article
-	 *
-	 * @param {String} tag Tag to remove
-	 * @param {Function} callback function(Boolean), called when tag has been removed
-	 */
-	removeTag: function(tag, callback) {
-		AppAPI.request('article-tags-remove', {
-			tag: tag
-		}, callback);
-	},
-
-	/**
-	 * Get the selected categories
-	 *
-	 * @param {Function} callback function([String]), array with category ids
-	 */
-	getSelectedCategories: function(callback) {
-		AppAPI.request('article-categories-selected-get', null, callback);
-	},
-
-	/**
-	 * Save the currently selected categories
-	 *
-	 * @param {Function} callback function(Boolean), called when categories has been saved
-	 */
-	saveCategories: function(callback) {
-		this.getSelectedCategories(function(categories) {
-			this.setCategories(categories, callback);
-		});
-	},
-
-	/**
-	 * Set selected categories
-	 *
-	 * @param {Array} categories List of category IDs that should be set
-	 * @param {Function} callback function(Boolean), called when categories have been set
-	 */
-	setCategories: function(categories, callback) {
-		AppAPI.request('article-categories-selected-set', {
-			categories: categories
-		}, callback);
-	},
-
-	/**
-	 * Add the given categories to the list of categories
-	 *
-	 * @param {Array} categories List of category IDs to add
-	 * @param {Function} callback function(Boolean), called when the categories have been set
-	 */
-	addCategories: function(categories, callback) {
-
-		AppAPI.request('article-categories-add', {
-			categories: categories
-		}, callback);
-	},
-
-	/**
-	 * Remove the given categories from the list of categories
-	 *
-	 * @param {Array} categories List of category IDs to remove
-	 * @param {Function} callback function(Boolean), called when the categories have been removed
-	 */
-	removeCategories: function(categories, callback) {
-		AppAPI.request('article-categories-remove', {
-			categories: categories
-		}, callback);
-	},
-
-	/**
-	 * Set the main category of the current article
-	 *
-	 * @param {Number} category The ID of the category to set as the main category
-	 * @param {Function} callback function(Boolean), called when the main category has been set
-	 */
-	setMainCategory: function(category, callback) {
-		AppAPI.request('article-categories-main-set', {
-			category: category
-		}, callback);
-	},
-
-	/**
-	 * Get the source set for the article
-	 *
-	 * @param {Function} callback function(String), name of the source
-	 */
-	getSource: function(callback) {
-
-		AppAPI.request('article-source-get', null, callback);
-	},
-
-	/**
-	 * Set the source for the article
-	 *
-	 * @param {String} value The new value to be set as source
-	 * @param {Function} callback function(Boolean), called when the source has been set
-	 */
-	setSource: function(value, callback) {
-		AppAPI.request('article-source-set', {
-			source: value
-		}, callback);
-	},
-
-	/**
-	 * Get the status for the article
-	 *
-	 * @param {Function} callback function(String), current status
-	 */
-	getStatus: function(callback) {
-		AppAPI.request('article-status-get', null, callback);
-	},
-
-	/**
-	 * Set the status for the article
-	 *
-	 * @param {String} status The new status to be set (draft, waiting, published)
-	 * @param {Function} callback function(Boolean), called when the source has been set
-	 */
-	setStatus: function(status, callback) {
-		AppAPI.request('article-status-set', {
-			status: status
-		}, callback);
-	},
-
-	/**
-	 * Get the published-date
-	 *
-	 * @param {Function} callback function(String), current published datetime
-	 */
-	getPublishedDatetime: function(callback) {
-		AppAPI.request('article-published-get', null, callback);
-	},
-
-	/**
-	 * Set the published-date
-	 *
-	 * @param {String} published Date to be set (YYYY-MM-DD HH:MM:SS)
-	 * @param {Function} callback function(Boolean), called when done
-	 */
-	setPublishedDatetime: function(published, callback) {
-		AppAPI.request('article-published-set', {
-			published: published
-		}, callback);
-	},
-
-	/**
-	 * Get the authors set in the article
-	 *
-	 * @param {Function} callback function([String]), currently set authors
-	 */
-	getAuthors: function(callback) {
-		AppAPI.request('article-authors-get', null, callback);
-	},
-
-	/**
-	 * Set authors for the article
-	 *
-	 * @param {Array} authors List of authors that should be set
-	 * @param {Function} callback function(Boolean), called when it has been set
-	 */
-	setAuthors: function(authors, callback) {
-		AppAPI.request('article-authors-set', {
-			authors: authors
-		}, callback);
-	},
-
-	/**
-	 * Add the given authors to the list of authors
-	 *
-	 * @param {Array} authors List of authors to add
-	 * @param {Function} callback function(Boolean), called when it has been set
-	 */
-	addAuthors: function(authors, callback) {
-		AppAPI.request('article-authors-add', {
-			authors: authors
-		}, callback);
-	},
-
-	/**
-	 * Remove the given authors from the list of authors
-	 *
-	 * @param {Array} authors List of authors to remove
-	 * @param {Function} callback function([String]), author list as it is after the authors has been removed
-	 */
-	removeAuthors: function(authors, callback) {
-		AppAPI.request('article-authors-remove', {
-			authors: authors
-		}, callback);
-	},
+        }, callback);
+    };
+
+    /**
+     * Remove tag from article
+     *
+     * @param {String} tag Tag to remove
+     * @param {Function} callback function(Boolean), called when tag has been removed
+     */
+    ArticleCommunicator.prototype.removeTag = function(tag, callback) {
+        AppAPI.request('article-tags-remove', {
+            tag: tag
+        }, callback);
+    };
+
+    /**
+     * Get the selected categories
+     *
+     * @param {Function} callback function([String]), array with category ids
+     */
+    ArticleCommunicator.prototype.getSelectedCategories = function(callback) {
+        AppAPI.request('article-categories-selected-get', null, callback);
+    };
+
+    /**
+     * Save the currently selected categories
+     *
+     * @param {Function} callback function(Boolean), called when categories has been saved
+     */
+    ArticleCommunicator.prototype.saveCategories = function(callback) {
+        this.getSelectedCategories(function(categories) {
+            this.setCategories(categories, callback);
+        });
+    };
+
+    /**
+     * Set selected categories
+     *
+     * @param {Array} categories List of category IDs that should be set
+     * @param {Function} callback function(Boolean), called when categories have been set
+     */
+    ArticleCommunicator.prototype.setCategories = function(categories, callback) {
+        AppAPI.request('article-categories-selected-set', {
+            categories: categories
+        }, callback);
+    };
+
+    /**
+     * Add the given categories to the list of categories
+     *
+     * @param {Array} categories List of category IDs to add
+     * @param {Function} callback function(Boolean), called when the categories have been set
+     */
+    ArticleCommunicator.prototype.addCategories = function(categories, callback) {
+
+        AppAPI.request('article-categories-add', {
+            categories: categories
+        }, callback);
+    };
+
+    /**
+     * Remove the given categories from the list of categories
+     *
+     * @param {Array} categories List of category IDs to remove
+     * @param {Function} callback function(Boolean), called when the categories have been removed
+     */
+    ArticleCommunicator.prototype.removeCategories = function(categories, callback) {
+        AppAPI.request('article-categories-remove', {
+            categories: categories
+        }, callback);
+    };
+
+    /**
+     * Set the main category of the current article
+     *
+     * @param {Number} category The ID of the category to set as the main category
+     * @param {Function} callback function(Boolean), called when the main category has been set
+     */
+    ArticleCommunicator.prototype.setMainCategory = function(category, callback) {
+        AppAPI.request('article-categories-main-set', {
+            category: category
+        }, callback);
+    };
+
+    /**
+     * Get the source set for the article
+     *
+     * @param {Function} callback function(String), name of the source
+     */
+    ArticleCommunicator.prototype.getSource = function(callback) {
+
+        AppAPI.request('article-source-get', null, callback);
+    };
+
+    /**
+     * Set the source for the article
+     *
+     * @param {String} value The new value to be set as source
+     * @param {Function} callback function(Boolean), called when the source has been set
+     */
+    ArticleCommunicator.prototype.setSource = function(value, callback) {
+        AppAPI.request('article-source-set', {
+            source: value
+        }, callback);
+    };
+
+    /**
+     * Get the status for the article
+     *
+     * @param {Function} callback function(String), current status
+     */
+    ArticleCommunicator.prototype.getStatus = function(callback) {
+        AppAPI.request('article-status-get', null, callback);
+    };
+
+    /**
+     * Set the status for the article
+     *
+     * @param {String} status The new status to be set (draft, waiting, published)
+     * @param {Function} callback function(Boolean), called when the source has been set
+     */
+    ArticleCommunicator.prototype.setStatus = function(status, callback) {
+        AppAPI.request('article-status-set', {
+            status: status
+        }, callback);
+    };
+
+    /**
+     * Get the published-date
+     *
+     * @param {Function} callback function(String), current published datetime
+     */
+    ArticleCommunicator.prototype.getPublishedDatetime = function(callback) {
+        AppAPI.request('article-published-get', null, callback);
+    };
+
+    /**
+     * Set the published-date
+     *
+     * @param {String} published Date to be set (YYYY-MM-DD HH:MM:SS)
+     * @param {Function} callback function(Boolean), called when done
+     */
+    ArticleCommunicator.prototype.setPublishedDatetime = function(published, callback) {
+        AppAPI.request('article-published-set', {
+            published: published
+        }, callback);
+    };
+
+    /**
+     * Get the authors set in the article
+     *
+     * @param {Function} callback function([String]), currently set authors
+     */
+    ArticleCommunicator.prototype.getAuthors = function(callback) {
+        AppAPI.request('article-authors-get', null, callback);
+    };
+
+    /**
+     * Set authors for the article
+     *
+     * @param {Array} authors List of authors that should be set
+     * @param {Function} callback function(Boolean), called when it has been set
+     */
+    ArticleCommunicator.prototype.setAuthors = function(authors, callback) {
+        AppAPI.request('article-authors-set', {
+            authors: authors
+        }, callback);
+    };
+
+    /**
+     * Add the given authors to the list of authors
+     *
+     * @param {Array} authors List of authors to add
+     * @param {Function} callback function(Boolean), called when it has been set
+     */
+    ArticleCommunicator.prototype.addAuthors = function(authors, callback) {
+        AppAPI.request('article-authors-add', {
+            authors: authors
+        }, callback);
+    };
+
+    /**
+     * Remove the given authors from the list of authors
+     *
+     * @param {Array} authors List of authors to remove
+     * @param {Function} callback function([String]), author list as it is after the authors has been removed
+     */
+    ArticleCommunicator.prototype.removeAuthors = function(authors, callback) {
+        AppAPI.request('article-authors-remove', {
+            authors: authors
+        }, callback);
+    };
 
     /**
      * Get the dossiers set in the article
      *
      * @param {Function} callback function([Object Dossiers]), current dossiers
      */
-    getDossiers: function(callback) {
+    ArticleCommunicator.prototype.getDossiers = function(callback) {
         AppAPI.request('article-dossiers-get', null, callback);
-    },
+    };
 
     /**
      * Add the given dossiers to the list of dossiers
      *
      * @param {Array} dossiers List of dossiers to add
-	 * @param {Function} callback function(Boolean), called when it has been set
+     * @param {Function} callback function(Boolean), called when it has been set
      */
-    addDossiers: function(dossiers, callback) {
+    ArticleCommunicator.prototype.addDossiers = function(dossiers, callback) {
         AppAPI.request('article-dossiers-add', {
             dossiers: dossiers
         }, callback);
-    },
+    };
+
+    /**
+     * Set the keyword-list on the article
+     *
+     * @param {Array} keywords List of keywords to add
+     * @param {Function} callback Function to call when keywords have been set
+     */
+    ArticleCommunicator.prototype.setKeywords = function(keywords, callback) {
+        AppAPI.request('article-keywords-set', {
+            keywords: keywords
+        }, callback);
+    };
+
+    /**
+     * Get the current set of keywords on the article
+     *
+     * @param {Function} callback Function to call with the result
+     */
+    ArticleCommunicator.prototype.getKeywords = function(callback) {
+        AppAPI.request('article-keywords-get', null, callback);
+    };
 
     /**
      * Remove the given dossiers from the list of dossiers
@@ -339,126 +445,226 @@ 

Source: ArticleCommunicator.js

* @param {Array} dossiers List of authors to remove * @param {Function} callback function([Object Dossiers]), current dossiers */ - removeDossiers: function(dossiers, callback) { + ArticleCommunicator.prototype.removeDossiers = function(dossiers, callback) { AppAPI.request('article-dossiers-remove', { dossiers: dossiers }, callback); - }, - - /** - * Gets the current article content - * - * @param {Function} callback function(Object Content) - */ - getCurrentContent: function(callback) { - AppAPI.request('article-content-get', null, callback); - }, - - /** - * Updates current article content - * - * @param {String} content The new content for the article - * @param {Function} callback function(Boolean), called when it has been set - */ - setCurrentContent: function(content, callback) { - AppAPI.request('article-content-set', { - content: content - }, callback); - }, - - /** - * Get the article type of the current article - * - * @param {Function} callback function(Int) - */ - getArticletypeId: function(callback) { - AppAPI.request('article-type-get', null, callback); - }, - - /** - * Set the article type of the current article - * - * @param {Number} articletypeId The new article type of the article - * @param {Function} callback function(Boolean), called when it has been set - */ - setArticletypeId: function(articletypeId, callback) { - AppAPI.request('article-type-set', { - articletype: articletypeId - }, callback); - }, - - /** - * Maximize the app view - * - * @param {String} title Title to give the maximized view - * @param {function} onClose Function to call when the window is closed/minimized - */ - maximizeAppWindow: function(title, onClose) { - var event = 'editor-pane-close-' + new Date().getTime(); - - AppAPI.request('editor-pane-maximize', { - title : title, - event : event - }); - AppAPI.eventListeners.removeAll(event); - AppAPI.eventListeners.add(event, onClose); - }, - - /** - * Restore the app pane to the default size - * - * @param {function} callback Callback to call after everything is done - */ - restoreAppWindow: function(callback) { - AppAPI.request('restore-app-window', {}, callback); - }, - - /** - * Get the current byline - * - * @param {function} callback function(String), xml string with the current byline - */ - getByline: function(callback) { + }; + + /** + * Gets the current article content + * + * @param {Function} callback function(Object Content) + */ + ArticleCommunicator.prototype.getCurrentContent = function(callback) { + AppAPI.request('article-content-get', null, callback); + }; + + /** + * Updates current article content + * + * @param {String} content The new content for the article + * @param {Function} callback function(Boolean), called when it has been set + */ + ArticleCommunicator.prototype.setCurrentContent = function(content, callback) { + AppAPI.request('article-content-set', { + content: content + }, callback); + }; + + /** + * Get the article type of the current article + * + * @param {Function} callback function(Int) + */ + ArticleCommunicator.prototype.getArticletypeId = function(callback) { + AppAPI.request('article-type-get', null, callback); + }; + + /** + * Set the article type of the current article + * + * @param {Number} articletypeId The new article type of the article + * @param {Function} callback function(Boolean), called when it has been set + */ + ArticleCommunicator.prototype.setArticletypeId = function(articletypeId, callback) { + AppAPI.request('article-type-set', { + articletype: articletypeId + }, callback); + }; + + /** + * Maximize the app view + * + * @param {String} title Title to give the maximized view + * @param {function} onClose Function to call when the window is closed/minimized + */ + ArticleCommunicator.prototype.maximizeAppWindow = function(title, onClose) { + var event = 'editor-pane-close-' + new Date().getTime(); + + AppAPI.request('editor-pane-maximize', { + title : title, + event : event + }); + AppAPI.eventListeners.removeAll(event); + AppAPI.eventListeners.add(event, onClose); + }; + + /** + * Restore the app pane to the default size + * + * @param {function} callback Callback to call after everything is done + */ + ArticleCommunicator.prototype.restoreAppWindow = function(callback) { + AppAPI.request('restore-app-window', {}, callback); + }; + + /** + * Get the current byline + * + * @param {function} callback function(String), xml string with the current byline + */ + ArticleCommunicator.prototype.getByline = function(callback) { AppAPI.request("article-byline-get", null, callback); - }, - - /** - * Set the byline - * - * @param {String} byline XML version of byline to use - * @param {Boolean} save If true, force save after updating byline information - * @param {Function} callback function(Boolean), called when it has been set - */ - setByline: function(byline, save, callback) { + }; + + /** + * Set the byline + * + * @param {String} byline XML version of byline to use + * @param {Boolean} save If true, force save after updating byline information + * @param {Function} callback function(Boolean), called when it has been set + */ + ArticleCommunicator.prototype.setByline = function(byline, save, callback) { AppAPI.request('article-byline-set', { - save: save, - byline: byline + save: save, + byline: byline + }, callback); + }; + + /** + * Set geolocation + * + * @param {Object} geolocations The location to set + * @param {Function} callback function(Boolean), called when it has been set + */ + ArticleCommunicator.prototype.setGeolocations = function(geolocations, callback) { + AppAPI.request('article-geolocations-set', { + geolocations: geolocations }, callback); - } + }; + + /** + * Get geolocation + * + * @param {Function} callback function(Object), retrieves the currently set geo location + */ + ArticleCommunicator.prototype.getGeolocations = function(callback) { + AppAPI.request("article-geolocations-get", null, callback); + }; + + return new ArticleCommunicator(); + +})(); +
+
+
+ + + + + +
+ +
+
+ + + + DocStrap Copyright © 2012-2014 The contributors to the JSDoc3 and DocStrap projects. + +
+ + + Documentation generated by JSDoc 3.2.2 + on Tue Dec 9th 2014 using the DocStrap template. + +
+
+ + +
+
+ +
+ + + + + + -
- + + -
-
- Documentation generated by JSDoc 3.2.1 on Fri Nov 01 2013 12:31:00 GMT+0100 (CET) -
+ + - - diff --git a/doc/AH5Communicator.html b/doc/Editor.html similarity index 54% rename from doc/AH5Communicator.html rename to doc/Editor.html index 930ead5..c7561b2 100644 --- a/doc/AH5Communicator.html +++ b/doc/Editor.html @@ -1,134 +1,155 @@ + - - JSDoc: Class: AH5Communicator - - - - - - - + + Documentation Module: AppAPI/Editor - - -
- -

Class: AH5Communicator

- - + + + + + +
+ + +
+ + +
+ +
+ + + +

Module: AppAPI/Editor

- +

- AH5Communicator + AppAPI/Editor

-

Functions for talking with the AH5 editor. Accessed through AppAPI.Editor

+
Functions for talking with the AH5 editor. Accessed through AppAPI.Editor
-
+
- + -
-

new AH5Communicator()

- - -
-
- - -
-

This will be used by editor apps to communicate with the editor

+
This will be used by editor apps to communicate with the editor -

Should be used like this:

+Should be used like this: -

AppAPI.Editor.insert('string');

-
- +AppAPI.Editor.insert('string');
+ - - - - - - - -
- - - - +
+ - - - - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 12 -
- - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - -
+
+ + + + + + - - - - - - - +

Methods

- +
-

<static> addClasses(id, classes, callback)

+

addClasses(id, classes, callback)

@@ -136,7 +157,7 @@

<static> -

Add new classes to an element

+ Add new classes to an element

@@ -148,31 +169,31 @@

<static> Parameters:

- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
id @@ -181,21 +202,21 @@
Parameters:

Id of the element

Id of the element
classes @@ -204,21 +225,21 @@
Parameters:

Array of class names

Array of class names
callback @@ -227,54 +248,56 @@
Parameters:

function(Boolean)

function(Boolean)
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 266 -
- - - - - - - - + @@ -287,7 +310,7 @@
Parameters:
-

<static> clear(callback)

+

clear(callback)

@@ -295,7 +318,7 @@

<static> clea
-

Clears the editor contents

+ Clears the editor contents
@@ -307,58 +330,87 @@

<static> clea

Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + - +
NameTypeDescription
callback -Function +function

function(Boolean)

function(Boolean)
+
- - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + @@ -368,26 +420,137 @@
Parameters:
+ + + + +
+

deleteElementById(id, callback)

+ +
+
+
+ Delete an element in the article +
+ + -
Source:
-
  • - AH5Communicator.js, line 205 -
+
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
id + + +String + + + + Id of the element
callback + + +function + + + + function(Boolean), called after deletion is done
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ - + @@ -400,7 +563,7 @@
Parameters:
-

<static> getActiveEditor(callback)

+

getActiveEditor(callback)

@@ -408,7 +571,7 @@

<static> <
-

Get name of current active editor

+ Get name of current active editor
@@ -420,31 +583,31 @@

<static> <
Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + - +
NameTypeDescription
callback @@ -453,54 +616,56 @@
Parameters:

function(String)

function(String)
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 18 -
- - - - - - - - + @@ -513,7 +678,7 @@
Parameters:
-

<static> getCategories(callback)

+

getCategories(callback)

@@ -521,7 +686,7 @@

<static> -

Get all categories

+ Get all categories

@@ -533,87 +698,89 @@

<static> Parameters:

- +
- + + + - - - + - + - + - + + + - - - - + + - +
NameTypeDescription
callback -Function +function

function([Object Category]), list of Category objects with id, name and pid

function([Object Category]), list of Category objects with id, name and pid
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 151 -
- - - - - - - - + @@ -626,7 +793,7 @@
Parameters:
-

<static> getEditorType(callback)

+

getEditorType(callback)

@@ -634,7 +801,7 @@

<static> -

Retrieves the type of editor that currently has focus

+ Retrieves the type of editor that currently has focus

@@ -646,31 +813,31 @@

<static> Parameters:

- +
- + + + - - - + - + - + - + + + - - - - + + - +
NameTypeDescription
callback @@ -679,54 +846,56 @@
Parameters:

function(String)

function(String)
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 104 -
- - - - - - - - + @@ -739,7 +908,7 @@
Parameters:
-

<static> getHTMLById(id, callback)

+

getHTMLById(id, callback)

@@ -747,7 +916,7 @@

<static> -

Get HTML code of an element

+ Get HTML code of an element

@@ -759,31 +928,31 @@

<static> Parameters:

- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
id @@ -792,21 +961,21 @@
Parameters:

The element id

The element id
callback @@ -815,54 +984,56 @@
Parameters:

function(String), html content of the element

function(String), html content of the element
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 128 -
- - - - - - - - + @@ -875,7 +1046,7 @@
Parameters:
-

<static> getHTMLBySelector(selector, callback)

+

getHTMLBySelector(selector, callback)

@@ -883,7 +1054,7 @@

<static>
-

Get HTML code of all elements that match the selector

+ Get HTML code of all elements that match the selector
@@ -895,31 +1066,31 @@

<static>
Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
selector @@ -928,21 +1099,21 @@
Parameters:

The CSS selector

The CSS selector
callback @@ -951,54 +1122,56 @@
Parameters:

function([String]), html content of matching elements

function([String]), html content of matching elements
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 140 -
- - - - - - - - + @@ -1011,7 +1184,7 @@
Parameters:
-

<static> getParentCategories(category, callback)

+

getParentCategories(category, callback)

@@ -1019,7 +1192,7 @@

<stati
-

Returns all the parent categories of the given category

+ Returns all the parent categories of the given category
@@ -1031,31 +1204,31 @@

<stati
Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
category @@ -1064,77 +1237,79 @@
Parameters:

The category to find parents of

The category to find parents of
callback -Function +function

function([Object Category]), array of parent Category objects

function([Object Category]), array of parent Category objects
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 161 -
- - - - - - - - + @@ -1147,7 +1322,7 @@
Parameters:
-

<static> getParentIds(id, selector, callback)

+

getParentIds(id, selector, callback)

@@ -1155,7 +1330,7 @@

<static> -

Returns all the parent elements that match the selector

+ Returns all the parent elements that match the selector

@@ -1167,31 +1342,31 @@

<static> Parameters:

- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
id @@ -1200,21 +1375,21 @@
Parameters:

Id of element to find parents of

Id of element to find parents of
selector @@ -1223,77 +1398,79 @@
Parameters:

Selector to filter parent elements with

Selector to filter parent elements with
callback -Function +function

function([String]), array of ids

function([String]), array of ids
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 172 -
- - - - - - - - + @@ -1306,7 +1483,7 @@
Parameters:
-

<static> getTagType(id, callback)

+

getTagType(id, callback)

@@ -1314,7 +1491,7 @@

<static> -

Get information about the given tagtype

+ Get information about the given tagtype @@ -1326,31 +1503,31 @@

<static> Parameters:

- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
id @@ -1359,77 +1536,79 @@
Parameters:

The element id

The element id
callback -Function +function

function(Object Tagtype), tagtype object with id, name and config object

function(Object Tagtype), tagtype object with id, name and config object
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 194 -
- - - - - - - - + @@ -1442,7 +1621,7 @@
Parameters:
-

<static> getTagTypes(callback)

+

getTagTypes(callback)

@@ -1450,7 +1629,7 @@

<static> -

Retrieve information about all tagtypes

+ Retrieve information about all tagtypes @@ -1462,87 +1641,89 @@

<static> Parameters:

- +
- + + + - - - + - + - + - + + + - - - - + + - +
NameTypeDescription
callback -Function +function

function([Object Tagtype]), array of tagtypes with id, name and config object

function([Object Tagtype]), array of tagtypes with id, name and config object
- - - -
- - - - - +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 184 -
- - - - - - - -
+ @@ -1555,7 +1736,7 @@
Parameters:
-

<static> initMenu(menus, callback)

+

initMenu(menus, callback)

@@ -1563,9 +1744,9 @@

<static> i
-

Initialize pre registered menus

+ Initialize pre registered menus -

Available options are: simplePluginMenu, editContext, deleteButton, floatButtons

+Available options are: simplePluginMenu, editContext, deleteButton, floatButtons
@@ -1577,31 +1758,31 @@

<static> i

Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
menus @@ -1610,77 +1791,79 @@
Parameters:

Array of menu names

Array of menu names
callback -Function +function

function(Boolean)

function(Boolean)
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 325 -
- - - - - - - - + @@ -1693,7 +1876,7 @@
Parameters:
-

<static> insertElement(element, options, callback)

+

insertElement(element, options, callback)

@@ -1701,10 +1884,10 @@

<static> -

Insert an element into the editor

+ Insert an element into the editor -

Note that the HTML of the element is what will be transferred, and nothing else! -The element will be given the class dp-app-element, and given a unique ID (if none is present)

+Note that the HTML of the element is what will be transferred, and nothing else! +The element will be given the class dp-app-element, and given a unique ID (if none is present) @@ -1716,31 +1899,31 @@

<static> Parameters:

- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
element @@ -1749,21 +1932,21 @@
Parameters:

The element that should be inserted

The element that should be inserted
options @@ -1772,77 +1955,79 @@
Parameters:

(can be omitted) Options object, supports option 'select' - set to true to automatically select the inserted element

(can be omitted) Options object, supports option 'select' - set to true to automatically select the inserted element
callback -Function +function

function(String), id of the newly inserted element

function(String), id of the newly inserted element
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 231 -
- - - - - - - - + @@ -1855,7 +2040,7 @@
Parameters:
-

<static> insertString(string, callback)

+

insertString(string, callback)

@@ -1863,7 +2048,7 @@

<static> -

Insert a string into the editor

+ Insert a string into the editor @@ -1875,31 +2060,31 @@

<static> Parameters:

- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
string @@ -1908,77 +2093,79 @@
Parameters:

The string that should be inserted

The string that should be inserted
callback -Function +function

function(String), id of the newly inserted element if it has one

function(String), id of the newly inserted element if it has one
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 215 -
- - - - - - - - + @@ -1991,7 +2178,7 @@
Parameters:
-

<static> markAsActive(id, callback)

+

markAsActive(id, callback)

@@ -1999,7 +2186,7 @@

<static> -

Mark an element as currently selected (green border with default styling)

+ Mark an element as currently selected (green border with default styling) @@ -2011,31 +2198,31 @@

<static> Parameters:

- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
id @@ -2044,21 +2231,21 @@
Parameters:

Id of the element

Id of the element
callback @@ -2067,54 +2254,56 @@
Parameters:

function(Boolean)

function(Boolean)
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 279 -
- - - - - - - - + @@ -2127,7 +2316,7 @@
Parameters:
-

<static> registerMenuAction(action, callback)

+

registerMenuAction(action, callback)

@@ -2135,8 +2324,8 @@

<static
-

Registers/Modifies a context menu items for a app element -The object send should have the following structure

+ Registers/Modifies a context menu items for a app element +The object send should have the following structure
@@ -2148,31 +2337,31 @@

<static
Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
action @@ -2181,21 +2370,21 @@
Parameters:

The action object

The action object
callback @@ -2204,54 +2393,56 @@
Parameters:

function()

function()
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 41 -
- - - - - - - - + @@ -2261,17 +2452,18 @@
Parameters:
Example
-
AppAPI.Editor.registerMenuAction({
-     label: 'label in the menu',
-     icon: '[Optional] url to possible icon image',
-     trigger: '[Optional] css selector, only show menu element when this matches the element',
+    
AppAPI.Editor.registerMenuAction({
+     label: 'label in the menu',
+     icon: '[Optional] url to possible icon image',
+     trigger: '[Optional] css selector, only show menu element when this matches the element',
      callback: function(id, clickedElementId) {
-         // callback function
-         // first parameter is id of the app element
-         // second paramter is id of closest element to the trigger element that has an id
-         //      in code: $(event.triggerElement).closest('[id]').attr('id');						
+         // callback function
+         // first parameter is id of the app element
+         // second paramter is id of closest element to the trigger element that has an id
+         //      in code: $(event.triggerElement).closest('[id]').attr('id');						
      }
-})
+})
+ @@ -2279,7 +2471,7 @@
Example
-

<static> registerMenuActionGroup(group, callback)

+

registerMenuActionGroup(group, callback)

@@ -2287,8 +2479,8 @@

<s
-

Registers/Modifies a group of items to in the context menu -The object send should have the following structure

+ Registers/Modifies a group of items to in the context menu +The object send should have the following structure
@@ -2300,31 +2492,31 @@

<s
Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
group @@ -2333,21 +2525,21 @@
Parameters:

The action object

The action object
callback @@ -2356,54 +2548,56 @@
Parameters:

function()

function()
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 72 -
- - - - - - - - + @@ -2413,24 +2607,25 @@
Parameters:
Example
-
AppAPI.Editor.registerMenuActionGroup({
-     label: 'label for the group in the menu',
-     icon: '[Optional] url to possible icon image',
+    
AppAPI.Editor.registerMenuActionGroup({
+     label: 'label for the group in the menu',
+     icon: '[Optional] url to possible icon image',
      actions: [
          {
-             label: 'label for the action #1',
+             label: 'label for the action #1',
              callback: function(id, clickedElementId) {
-                 // same as for registerMenuAction
+                 // same as for registerMenuAction
              }
          },
          {
-             label: 'label for the action #2',
+             label: 'label for the action #2',
              callback: function(id, clickedElementId) {
-                 // same as for registerMenuAction
+                 // same as for registerMenuAction
              }
          }
      ]
-})
+})
+ @@ -2438,7 +2633,7 @@
Example
-

<static> removeClasses(id, classes, callback)

+

removeClasses(id, classes, callback)

@@ -2446,7 +2641,7 @@

<static> -

Remove classes from the element an element in the article

+ Remove classes from the element an element in the article @@ -2458,31 +2653,31 @@

<static> Parameters:

- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
id @@ -2491,21 +2686,21 @@
Parameters:

Id of the element

Id of the element
classes @@ -2514,21 +2709,21 @@
Parameters:

Array of class names

Array of class names
callback @@ -2537,54 +2732,56 @@
Parameters:

function(Boolean)

function(Boolean)
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 252 -
- - - - - - - - + @@ -2597,7 +2794,7 @@
Parameters:
-

<static> replaceElementById(id, element, callback)

+

replaceElementById(id, element, callback)

@@ -2605,7 +2802,7 @@

<static
-

Replace an element in the article

+ Replace an element in the article
@@ -2617,31 +2814,31 @@

<static
Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
id @@ -2650,21 +2847,21 @@
Parameters:

Id of the element

Id of the element
element @@ -2673,21 +2870,21 @@
Parameters:

The new element

The new element
callback @@ -2696,54 +2893,56 @@
Parameters:

function(Boolean), called after replacement is done

function(Boolean), called after replacement is done
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 115 -
- - - - - - - - + @@ -2756,7 +2955,7 @@
Parameters:
-

<static> setAttributeById(id, attribute, value, callback)

+

setAttributeById(id, attribute, value, callback)

@@ -2764,7 +2963,7 @@

<static>
-

Sets the attribute of the element with the given ID to value

+ Sets the attribute of the element with the given ID to value
@@ -2776,31 +2975,31 @@

<static>
Parameters:
- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + + - - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
id @@ -2809,21 +3008,21 @@
Parameters:

The ID of the element to set the attribute on

The ID of the element to set the attribute on
attribute @@ -2832,21 +3031,21 @@
Parameters:

The attribute to set

The attribute to set
value @@ -2855,77 +3054,79 @@
Parameters:

What to set the attribute to

What to set the attribute to
callback -Function +function

function(Boolean)

function(Boolean)
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 293 -
- - - - - - - - + @@ -2938,7 +3139,7 @@
Parameters:
-

<static> setStyleById(id, attribute, value, callback)

+

setStyleById(id, attribute, value, callback)

@@ -2946,7 +3147,7 @@

<static> -

Sets a style of the element with the given ID to value

+ Sets a style of the element with the given ID to value @@ -2958,31 +3159,31 @@

<static> Parameters:

- +
- + + + - - - + - + - + - + + + - - - - + + + - - + - + + + - - - - + + + - - + - + + + - - - - + + + - - + - + + + - - - - + + - +
NameTypeDescription
id @@ -2991,21 +3192,21 @@
Parameters:

The ID of the element to set the attribute on

The ID of the element to set the attribute on
attribute @@ -3014,21 +3215,21 @@
Parameters:

The style attribute to set

The style attribute to set
value @@ -3037,77 +3238,79 @@
Parameters:

What to set the attribute to

What to set the attribute to
callback -Function +function

function(Boolean)

function(Boolean)
+
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - -
Source:
-
  • - AH5Communicator.js, line 309 -
- - - - - - - - + @@ -3119,29 +3322,107 @@
Parameters:
+ - - + - + + + - +
+ + - + +
+
+
+ +
+ -
+ + + + + -
- Documentation generated by JSDoc 3.2.0-dev on Thu Feb 20 2014 15:58:35 GMT+0100 (CET) -
+ + + + + + + + + + - - + \ No newline at end of file diff --git a/doc/Listeners.js.html b/doc/Listeners.js.html index c707069..ffe9dcf 100644 --- a/doc/Listeners.js.html +++ b/doc/Listeners.js.html @@ -1,83 +1,159 @@ + - - JSDoc: Source: Listeners.js - - - - - - + + DocStrap Source: Listeners.js + + + + + + +
+ + +
+ + +
+ +
+ +

Source: Listeners.js

-
-
-
/**
- * Will hold a list of listeners that are created and should be notified on events
- *
+
+
+
/* global AppAPI: true */
+/**
  * @example
- * AppAPI.addListeners({
- *  afterCreated: function() {
- *      AppAPI.Article.setSource('Ny Times');
- *  },
- *  pluginElementSelected: function() {
- *      alert('You cliked me!');
- *  },
- *  beforeSave: function() {
- *      if (!articleIsAwesome()) {
+ * AppAPI.on('afterCreate', function() {
+ *     AppAPI.Article.setSource('Ny Times');
+ * });
+ * AppAPI.on('beforeSave', function() {
+ *     if (!articleIsAwesome()) {
  *          return false;
- *      }
- *  }
+ *     }
  * });
  *
  * @description
- * Used for event handling in the App API. The only function an app developer needs to care about it the 'addListeners' event, and you can see an example of it down bellow.
  *
- * If an event function returns false (as in the beforeSave example) the event will be stopped. This works for all events, but only makes sense for the before* events.
+ * 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 'beforSave' example given bellow. 
+ *
+ * Other apps can also supply their own events using the AppAPI.emit(...) function. Documention on these events are up to each app to create.
  *
  * *Available events are:*
  *
+ *  `addCategory`
+ *  > _triggered after a category has been added to the article_
+ *
+ *  `addTag`
+ *  > _triggered after a tag had been added to the article_
+ *
+ *  `appPaneMaximized`
+ *  > _triggered when the app pane is maximized_
+ *
+ *  `appPaneRestored`
+ *  > _triggered when the app pane is restored to its' original size_
+ *
  *  `appAuthenticated`
+ *  > _triggered when an app has been authenticated_
+ *
+ *  `changedCustomMeta`
+ *  > _triggered when a custom meta property is changed/set, parameter is an object with property name and value_
+ *
+ *  `receivedFocus`
+ *  > _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._
  *
- *  `afterCreated`
+ *  `afterCreate`
  *
- *  `afterDeleted`
+ *  `beforeDelete`
  *
- *  `afterLoaded`
+ *  `afterDelete`
  *
- *  `afterPublished`
+ *  `afterLoad`
+ *
+ *  `afterPublish`
  *
  *  `afterSave`
  *
- *  `beforeCreated`
+ *  `beforeCreate`
  *
- *  `beforeLoaded`
+ *  `beforeLoad`
  *
  *  `beforePreview`
  *
  *  `beforeSave`
  *
- *  `beforePublished`
+ *  `beforePublish`
+ *
+ *  `editorFocus` 
+ *  > _triggered when an editor gets focus_
+ *
+ *  `editorUnfocus` 
+ *  > _triggered when an editor loses focus_
  *
- *  `editorFocus`
+ *  `editorsLostFocus` 
+ *  > _triggered when all editors loses focus_
  *
  *  `editorReady`
  *
  *  `modifiedContent`
  *
+ *  `elementRemoved`
+ *  > _triggered when a plugin element from the current plugin is removed, receives an object with element id as a parameter_
+ *
  *  `pluginElementClicked`
  *
  *  `pluginElementSelected`
@@ -85,25 +161,27 @@ 

Source: Listeners.js

* `pluginElementDeselected` */ function Listeners () { - this._listeners = []; + "use strict"; + this._listeners = {}; } /** - * Adds several listeners - * - * @param {Object} events A list of callbacks that should be called on events - * @returns {Object} A dictionary of events => listener ID for later removal + * @deprecated Use AppAPI.on(...) instead */ -Listeners.prototype.addAll = function(events) { - - var out = {}; - for (var event in events) { - if (events.hasOwnProperty(event)) { - out[event] = this.add(event, events[event]); +Listeners.prototype.addAll = function(listeners) { + "use strict"; + var createCallback = function(callback) { + return function(data) { + callback(data.data); + }; + }; + for (var eventName in listeners) { + if (listeners.hasOwnProperty(eventName)) { + var callback = listeners[eventName]; + var callWrapper = createCallback(callback); + AppAPI.on(eventName, callWrapper); } - } - - return out; + } }; /** @@ -113,14 +191,14 @@

Source: Listeners.js

* @param {Function} callback Function to call when an even of the type is received */ Listeners.prototype.add = function(event, callback) { + "use strict"; if (this._listeners[event] === undefined) { this._listeners[event] = []; } - var index = this._listeners[event].length; - this._listeners[event][index] = callback; - return index; + this._listeners[event].push(callback); + return this._listeners[event].length - 1; }; /** @@ -130,6 +208,7 @@

Source: Listeners.js

* @param {Function} index The index of the event handler to remove */ Listeners.prototype.remove = function(event, index) { + "use strict"; if (this._listeners[event] === undefined || this._listeners[event][index] === undefined) { return; @@ -147,6 +226,7 @@

Source: Listeners.js

* @param {String} event Event type to remove handlers for (!event for all) */ Listeners.prototype.removeAll = function(event) { + "use strict"; if (!event) { this._listeners = []; } else { @@ -161,6 +241,7 @@

Source: Listeners.js

* @param {Object} data The event data */ Listeners.prototype.notify = function(event, data) { + "use strict"; var returnValue = true; if (this._listeners[event] !== undefined) { jQuery.each(this._listeners[event], function(i, e) { @@ -171,7 +252,7 @@

Source: Listeners.js

if (r === false) { returnValue = false; } - + } else if (e(data) === false) { returnValue = false; } @@ -180,26 +261,105 @@

Source: Listeners.js

} return returnValue; }; -
-
-
+
+
+
+ + + + + +
+ +
+
+ + + + DocStrap Copyright © 2012-2014 The contributors to the JSDoc3 and DocStrap projects. + +
+ + + Documentation generated by JSDoc 3.2.2 + on Tue Dec 9th 2014 using the DocStrap template. + +
+
+ + +
+
+ +
+ + + + + + - - + + -
-
- Documentation generated by JSDoc 3.2.1 on Fri Nov 01 2013 12:31:00 GMT+0100 (CET) -
+ + - - diff --git a/doc/global.html b/doc/global.html index 2042e88..23c03b0 100644 --- a/doc/global.html +++ b/doc/global.html @@ -1,93 +1,143 @@ + - - JSDoc: Global - - - - - - - + + Documentation Global - - -
- -

Global

- - + + + + + +
+ + +
+ + +
+ +
+ + + +

Global

- +

-
+
+ - - +
- - - - - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + +
- +
+ + + + + + - - - - - - - +

Methods

- +
@@ -99,49 +149,76 @@

Listeners -

Used for event handling in the App API. The only function an app developer needs to care about it the 'addListeners' event, and you can see an example of it down bellow.

+ 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 'beforSave' example given bellow. + +Other apps can also supply their own events using the AppAPI.emit(...) function. Documention on these events are up to each app to create. + +*Available events are:* + + `addCategory` + > _triggered after a category has been added to the article_ + + `addTag` + > _triggered after a tag had been added to the article_ + + `appPaneMaximized` + > _triggered when the app pane is maximized_ + + `appPaneRestored` + > _triggered when the app pane is restored to its' original size_ + + `appAuthenticated` + > _triggered when an app has been authenticated_ + + `changedCustomMeta` + > _triggered when a custom meta property is changed/set, parameter is an object with property name and value_ -

If an event function returns false (as in the beforeSave example) the event will be stopped. This works for all events, but only makes sense for the before* events.

+ `receivedFocus` + > _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._ -

Available events are:

+ `afterCreate` -

appPaneMaximized

+ `beforeDelete` -

appPaneRestored

+ `afterDelete` -

appAuthenticated

+ `afterLoad` -

afterCreated

+ `afterPublish` -

afterDeleted

+ `afterSave` -

afterLoaded

+ `beforeCreate` -

afterPublished

+ `beforeLoad` -

afterSave

+ `beforePreview` -

beforeCreated

+ `beforeSave` -

beforeLoaded

+ `beforePublish` -

beforePreview

+ `editorFocus` + > _triggered when an editor gets focus_ -

beforeSave

+ `editorUnfocus` + > _triggered when an editor loses focus_ -

beforePublished

+ `editorsLostFocus` + > _triggered when all editors loses focus_ -

editorFocus

+ `editorReady` -

editorReady

+ `modifiedContent` -

modifiedContent

+ `elementRemoved` + > _triggered when a plugin element from the current plugin is removed, receives an object with element id as a parameter_ -

pluginElementClicked

+ `pluginElementClicked` -

pluginElementSelected

+ `pluginElementSelected` -

pluginElementDeselected

+ `pluginElementDeselected`

@@ -153,39 +230,40 @@

Listeners - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - -
Source:
-
  • - Listeners.js, line 64 -
- - - - - - - - + @@ -195,48 +273,122 @@

ListenersExample

-
AppAPI.addListeners({
- afterCreated: function() {
-     AppAPI.Article.setSource('Ny Times');
- },
- pluginElementSelected: function() {
-     alert('You cliked me!');
- },
- beforeSave: function() {
-     if (!articleIsAwesome()) {
+    
AppAPI.on('afterCreate', function() {
+    AppAPI.Article.setSource('Ny Times');
+});
+AppAPI.on('beforeSave', function() {
+    if (!articleIsAwesome()) {
          return false;
-     }
- }
-});
+ } +});
+ + - - + - + + + + + +

+ +
+ +
+ + +
+
+
+ +
+
+ +
+ + + + + + - - + + -
-
- Documentation generated by JSDoc 3.2.0-dev on Thu Feb 20 2014 15:58:35 GMT+0100 (CET) -
+ + - - + \ No newline at end of file diff --git a/doc/img/glyphicons-halflings-white.png b/doc/img/glyphicons-halflings-white.png new file mode 100644 index 0000000000000000000000000000000000000000..3bf6484a29d8da269f9bc874b25493a45fae3bae GIT binary patch literal 8777 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 B7G?kd literal 0 HcmV?d00001 diff --git a/doc/img/glyphicons-halflings.png b/doc/img/glyphicons-halflings.png new file mode 100644 index 0000000000000000000000000000000000000000..a9969993201f9cee63cf9f49217646347297b643 GIT binary patch literal 12799 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 literal 0 HcmV?d00001 diff --git a/doc/index.html b/doc/index.html index 3a3a9a9..dc513ca 100644 --- a/doc/index.html +++ b/doc/index.html @@ -1,110 +1,275 @@ + - - JSDoc: Index - - - - - - + + Documentation Index + + + + + + +
+ -

+
+ +
+ +
+ + + Index + + - -
-

How does the API work?

-

The apps are loaded directly in iframes (i.e. the src= of the iframe points directly to the URL as given in the DrPublish config) and all communication between the app and DrPublish is sent using postMessage (a standardized method for cross-domain frame communication).

+ + + + + + + +
+

How does the API work?

+

The apps are loaded directly in iframes (i.e. the src= of the iframe points directly to the URL as given in the DrPublish config) and all communication between the app and DrPublish is sent using postMessage (a standardized method for cross-domain frame communication).

PostMessage works by one side listening for incoming messages, and determining whether to act upon that message or not depending on its origin host, its origin frame and its contents. In DrPublish, these binding are written in js/classes/binds/*.js, and are mapped through js/classes/controller/AppEvents.js, which also handles delegation of events from DrPublish to apps. On the app side, the files AppAPI.js, AH5Communicator.js and ArticleCommunicator.js provide functions for sending and recieving all the supported postMessage calls without the caller having to know what is being done.

-

Behind the scenes, the API files wrap the incoming parameters in a JSON object, adds on the name of sending app and what method on the remote side it wants to call, and send this over postMessage using a thin jQuery PM wrapper.

-

DrPublish then determines which function should be called, executes it, wraps its response in a JSON object, and returns it to the sending app. The app then receives this reply, and sends the received data to a callback (if any is specified).

-

So how do I get started?

-

Take a look at the example app to see how to get started. There you will see an example of how to write the authentication code required to get the app started, and a few simple examples of sending data between the app and DrPublish.

- -

When you're bored of that you can look through the method listings avaiable on the right and that is hopefully enough to set you on the right track to create any app you want.

- +

When you're bored of that you can look through the method listings avaiable on the right and that is hopefully enough to set you on the right track to create any app you want.

+

Costum configuration

+

Apps can ask for and specify a customized configuration object. The API function to retrieve the configuration option is AppAPI.getConfiguration, and you can find documentation on that in the AppAPI module.

+

To specify the format of the configuration object the App needs to provide an URL where other applications (in most cases DrPublish's App Admin tool) can recieve an JSON schema describing the desired configuration setup. In case of DrPublish this URL is then registered alongside the URL to the app in the Publication configuration.

+

A simple example JSON schema for an image app could look like:

+
{
+    "search": {
+        "type": "string",
+        "title": "Default Search",
+        "required": true
+    },
+    "images": {
+        "type": "array",
+        "title": "Image Sizes",
+        "items": {
+            "type": "object",
+            "title": "Image Size",
+            "properties": {
+                "name": {
+                    "type": "string",
+                    "title": "name",
+                    "required": true
+                },
+                "filter": {
+                    "type": "string",
+                    "title": "Filter",
+                    "enum": [
+                        "grayscale",
+                        "sepia",
+                        "none"
+                    ]
+                },
+                "height": {
+                    "type": "integer",
+                    "title": "Height"
+                }
+            }
+        }
+    }
+}

Authentication explained

-

When an app is loaded DrPublish send an encrypted token to the app, this is done so the app can check that it is actually being loaded by a DrPublish instance with a valid user logged in. Apps should always verify this token, otherwise this security aspect dissappears. Conversely, apps also have to authenticate themselves to DrPublish before they are allowed to access the API. The iframe that contains them are hidden until this has been done. If a app does not authenticate itself within 60 seconds of being loaded, it is killed.

+

This two-way authentication provides enhanced security both for DrPublish (it won't load unauthorized apps) and for the user (apps may only be accessed through DrPublish).

+

The authentication works by defining a shared secret between DrPublish and the app on a per-install basis.

+

So, to take the authentication process step by step:

+

The authentication process in detail

+
    +
  1. The DrPublish frontend sends a request to the DrPublish backend for a URL for the app with an encrypted authentication token
  2. +
  3. The backend creates a JSON object with various data (DrPublish host, logged in user, active publication, timestamp, app name) + a large salt
  4. +
  5. The backend encrypts this with both the app's scheme + host + port and the shared secret, and returns the encrypted string and the initialization vector to the DrPublish frontend
  6. +
  7. The DrPublish frontend creates a new iframe with the src received from the backend (this includes two extra parameters, auth and iv, which represent the encrypted authentication token and the initialization vector)
  8. +
  9. The DrPublish frontend blocks all postMessage calls from that iframe until it has sent a postMessage with type "app-loaded" that contains the app name, the app's authentication token and the app's IV
  10. +
  11. The app's frontend recieves the incoming DrPublish token and sends it to its' backend to ensure that it can be decrypted and that it has not expired
  12. +
  13. If the token is invalid, the app kills itself.
  14. +
  15. If the token is valid, the app's frontend gets an encrypted token from the app's backend to prove its identity to DrPublish
  16. +
  17. The app frontend then sends a "app-loaded" postMessage call to DrPublish containing app name, token (called a signature) and IV
  18. +
  19. The DrPublish frontend sends this signature + IV to its' backend for verification
  20. +
  21. The DrPublish backend decrypts the token, checks the time and returns true or false
  22. +
  23. The DrPublish frontend either allows the app access to the API, or kills it depending on the response from the backend
  24. +
+

OBS: Only the initial load of the app is authenticated! This means that the app should somehow store the fact that the user was authenticated, and only allow access to other parts of the app (think AJAX requests and such) if the app was first accessed with a valid DrPublish token.

+

What about debugging?

+

It just so happens that we did a lot of debugging while setting this up, and to be nice, we've left the debugging code in there. All you need to do to enable it is to set the AppAPI.DEBUG flag to TRUE; +If you then open up your browser JS console, you will see output detailing everything interesting that is happening under the bonnet. +Note especially warnings and errors since these indicate that something of special interest has happened.

+

Documentation Generation

+

Documentation has been generated using jsdoc and the supplied jsdoc.json file

+
-

This two-way authentication provides enhanced security both for DrPublish (it won't load unauthorized apps) and for the user (apps may only be accessed through DrPublish).

-

The authentication works by defining a shared secret between DrPublish and the app on a per-install basis.

-

So, to take the authentication process step by step:

-

The authentication process in detail

-
  1. The DrPublish frontend sends a request to the DrPublish backend for a URL for the app with an encrypted authentication token
  2. The backend creates a JSON object with various data (DrPublish host, logged in user, active publication, timestamp, app name) + a large salt
  3. The backend encrypts this with both the app's scheme + host + port and the shared secret, and returns the encrypted string and the initialization vector to the DrPublish frontend
  4. The DrPublish frontend creates a new iframe with the src received from the backend (this includes two extra parameters, auth and iv, which represent the encrypted authentication token and the initialization vector)
  5. The DrPublish frontend blocks all postMessage calls from that iframe until it has sent a postMessage with type "app-loaded" that contains the app name, the app's authentication token and the app's IV
  6. The app's frontend recieves the incoming DrPublish token and sends it to its' backend to ensure that it can be decrypted and that it has not expired
  7. If the token is invalid, the app kills itself.
  8. If the token is valid, the app's frontend gets an encrypted token from the app's backend to prove its identity to DrPublish
  9. The app frontend then sends a "app-loaded" postMessage call to DrPublish containing app name, token (called a signature) and IV
  10. The DrPublish frontend sends this signature + IV to its' backend for verification
  11. The DrPublish backend decrypts the token, checks the time and returns true or false
  12. The DrPublish frontend either allows the app access to the API, or kills it depending on the response from the backend
-

OBS: Only the initial load of the app is authenticated! This means that the app should somehow store the fact that the user was authenticated, and only allow access to other parts of the app (think AJAX requests and such) if the app was first accessed with a valid DrPublish token.

-

What about debugging?

+
-

It just so happens that we did a lot of debugging while setting this up, and to be nice, we've left the debugging code in there. All you need to do to enable it is to set the AppAPI.DEBUG flag to TRUE; -If you then open up your browser JS console, you will see output detailing everything interesting that is happening under the bonnet. -Note especially warnings and errors since these indicate that something of special interest has happened.

+
+ +
-

Documentation Generation

+ +
+
+
+ +
+
-

Documentation has been generated using jsdoc and the supplied conf.json file

- +
+ + + + + + - - + + -
-
- Documentation generated by JSDoc 3.2.0-dev on Thu Feb 20 2014 15:58:35 GMT+0100 (CET) -
+ + - - + \ No newline at end of file diff --git a/doc/module-AppApi.html b/doc/module-AppApi.html new file mode 100644 index 0000000..1c6c68c --- /dev/null +++ b/doc/module-AppApi.html @@ -0,0 +1,4422 @@ + + + + + + Documentation Module: AppApi + + + + + + + + + +
+ + +
+ + +
+ +
+ + + +

Module: AppApi

+
+ +
+

+ AppApi +

+ +
The basic API object
+ +
+ +
+
+ + + + +
Namespace for all public DrPublish methods available from apps.
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + +

Methods

+ +
+ +
+

<private> __loadArticleRevision(id, callback)

+ + +
+
+ + +
+ Loads an old revision of an article +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
id + + +Number + + + + The id of the revision to load
callback + + +function + + + + The function to call when the new revision has been loaded
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

addListeners()

+ + +
+
+ + + + + + + + + + +
+ + + + + + + + + +
Deprecated:
+ +
+
    +
  • Use AppAPI.on(...) instead
  • +
+
+ + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

callExtendedApi(group, name, data, action)

+ + +
+
+ + +
+ Call the extended AppAPI +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
group + + +String + + + + Group name for functionality to call
name + + +String + + + + Name of the specific function to call
data + + +Object + + + + Data object to pass as parameter to the api call
action + + +function + + + + function(Object) Function to recieve the API response, parameter is the response from the API call
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

clearRequiredActionCounter(callback)

+ + +
+
+ + +
+ Clear the counter of actions required by the user, used to tell the user that the plugin requires input of some kind +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
callback + + +function + + + + function(Object) function to call once the counter has been cleared
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

convertDomToHTML(dom) → {String}

+ + +
+
+ + +
+ Generates proper html code to represent the dom element. This is NOT an asynchronous function +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
dom + + +Object + + + + The dom node to convert
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Returns:
+ + +
+ The html code +
+ + + +
+
+ Type +
+
+ +String + + +
+
+ + + + + +
+ + + +
+

<private> create()

+ + +
+
+ + +
+ Create a new instance of the Api class +
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

createEmbeddedObject(typeId, callback)

+ + +
+
+ + +
+ Create an embedded object of the given type +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
typeId + + +Number + + + + Type Id of the embedded object to create
callback + + +function + + + + function(embeddedObjectId) called once the object has been created, first parameter is the new embedded object id
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

createTag(tag, callback)

+ + +
+
+ + +
+ Creates a new tag +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
tag + + +String + + + + JSON object with the tag to create, must contain tagTypeId and name properties
callback + + +function + + + + function(Boolean)
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

decreaseRequiredActionCounter(callback)

+ + +
+
+ + +
+ Decrease the counter of actions required by the user, used to tell the user that the plugin requires input of some kind +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
callback + + +function + + + + function(Object) function to call once the counter has been decrease, returns current counter value
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

doDirectAuthentication(signature, iv)

+ + +
+
+ + +
+ Directly authenticates with the DrPublish API with the given +signature and iv +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
signature + + +String + + + + Signature to send
iv + + +String + + + + Iv to send
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

doStandardAuthentication(url)

+ + +
+
+ + +
+ Performs authentication to DrPublish by sending a GET request +to the given URL (or ajax.php?do=authenticate-app if nothing +else is specified), and using .signature and .iv from the response +object as the authentication reply to the DrPublish API +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
url + + +String + + + + Url to call, default is 'ajax.php?do=authentication-app'
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

emit(name, data)

+ + +
+
+ + +
+ Emits an event to DrPublish, and possibly other apps +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +String + + + + Name of the event
data + + +String + + + + Data object to send with the event
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

extendApi(group, name, action)

+ + +
+
+ + +
+ Extends the AppAPI with custom functionality that other apps can use +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
group + + +String + + + + Group name for functionality to add
name + + +String + + + + Name of the specific function to add
action + + +function + + + + function(Object) Function to call when the API is invoked, recieves one parameter as given in AppAPI.callExtendedApi and return value is passed back to the caller
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

generateArticleUrl(id, callback)

+ + +
+
+ + +
+ Generates an url to a published article +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
id + + +String + + + + The id of the article to generate url for
callback + + +function + + + + function(String), where the parameter is the generated url
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

getAppName() → {String}

+ + +
+
+ + +
+ Get the name of the loaded app +
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
Returns:
+ + +
+ The name of the app, or false if it couldn't be detected +
+ + + +
+
+ Type +
+
+ +String + + +
+
+ + + + + +
+ + + +
+

getConfiguration(callback)

+ + +
+
+ + +
+ Get configuration information about the app +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
callback + + +function + + + + function(Object)
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

getCurrentUser(callback)

+ + +
+
+ + +
+ Gets logged in user +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
callback + + +function + + + + function(Object)
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

getEmbeddedObjectTypes(callback)

+ + +
+
+ + +
+ Get information about the available embedded object types +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
callback + + +function + + + + 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'}`
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

giveFocus(pluginName, argument, start)

+ + +
+
+ + +
+ Gives focus to another plugin +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
pluginName + + +String + + + + The name of the plugin to recieve focus
argument + + +Object + + + + Optional option argument to pass along to the plugin recieving focus
start + + +Boolean + + + + Flag to decide if the plugin should be started if it has not been loaded previously, default true
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

hide()

+ + +
+
+ + +
+ Hide the plugin, so it is no longer visible on the list of open plugins +
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

hideLoader()

+ + +
+
+ + +
+ Hide the loader +
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

increaseRequiredActionCounter(callback)

+ + +
+
+ + +
+ Increase the counter of actions required by the user, used to tell the user that the plugin requires input of some kind +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
callback + + +function + + + + function(Object) function to call once the counter has been increased, returns the new counter value
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

on(name, callback)

+ + +
+
+ + +
+ 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. +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +String + + + + Name of the event
callback + + +function + + + + function(Object) Function to call when the event is triggered. Recieves one data object parameter of the form {source: , data: }
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

openTagCreationDialog(tag, callback)

+ + +
+
+ + +
+ Creates a new tag +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
tag + + +String + + + + The tag to create
callback + + +function + + + + function(Boolean)
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

reloadIframe()

+ + +
+
+ + +
+ Reloads the app's iframe +
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

request(callSpec, data, callback)

+ + +
+
+ + +
+ 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 +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
callSpec + + +String + + + + What do you want to call?
data + + +Object + + + + The data attached to the request
callback + + +function + + + + The function to call upon return
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

searchDrLib(data, callback)

+ + +
+
+ + +
+ Sends a query to DrLib +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
data + + +Object + + + + 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
callback + + +function + + + + function(Boolean)
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
Example
+ +
AppAPI.searchDrLib({
+     query: 'articles.json?q=awesome',
+     secure: true,
+     success: function(data) {
+         data.items.forEach(doStuffWithArticle);
+     },
+     error: function(data) {
+         console.warn('something went wrong');
+     }
+})
+ + + +
+ + + +
+

setAppName(name)

+ + +
+
+ + +
+ Set the name of the app +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
name + + +String + + + + The name of the app
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

setConfiguration(config, options, callback)

+ + +
+
+ + +
+ Set configuration information about the app +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
config + + +Object + + + + The configuration object to save
options + + +Object + + + + Object, can have three keys. + 'onlyPublication' (boolean) If true the configuration is set for the current publication only + 'success' (function) Called if the configuration was saved successfully + 'error' (function) Called if there was an error, recieves and error object as first parameter
callback + + +function + + + + function()
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

setRequiredActionCounter(count, callback)

+ + +
+
+ + +
+ Set the counter of actions required by the user, used to tell the user that the plugin requires input of some kind +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
count + + +Number + + + + The value to set the counter to
callback + + +function + + + + function(Object) function to call once the counter has been cleared
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

showErrorMsg(msg)

+ + +
+
+ + +
+ Show error-message to the user +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
msg + + +String + + + + Message to be displayed
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

showInfoMsg(msg)

+ + +
+
+ + +
+ Show info-message to the user +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
msg + + +String + + + + Message to be displayed
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

showLoader(msg)

+ + +
+
+ + +
+ Show the loader +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
msg + + +String + + + + Message to display in progress loader
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ + + +
+

showWarningMsg(msg)

+ + +
+
+ + +
+ Show warning-message to the user +
+ + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
msg + + +String + + + + Message to be displayed
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + +
+ +
+ + + + + +
+ +
+ + + + +
+ +
+ +
+ + +
+
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/doc/modules.list.html b/doc/modules.list.html new file mode 100644 index 0000000..d02863a --- /dev/null +++ b/doc/modules.list.html @@ -0,0 +1,242 @@ + + + + + + Documentation Modules + + + + + + + + + +
+ + +
+ + +
+ +
+ + + +

Modules

+
+ +
+

+ +

+ +
+ +
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ + +
+
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/doc/scripts/URI.js b/doc/scripts/URI.js new file mode 100644 index 0000000..91b01ee --- /dev/null +++ b/doc/scripts/URI.js @@ -0,0 +1,1429 @@ +/*! + * URI.js - Mutating URLs + * + * Version: 1.8.3 + * + * Author: Rodney Rehm + * Web: http://medialize.github.com/URI.js/ + * + * Licensed under + * MIT License http://www.opensource.org/licenses/mit-license + * GPL v3 http://opensource.org/licenses/GPL-3.0 + * + */ +(function(root, factory) { + // https://github.com/umdjs/umd/blob/master/returnExports.js + if (typeof exports === 'object') { + // Node + module.exports = factory(require('./punycode'), require('./IPv6'), require('./SecondLevelDomains')); + } else if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['./punycode', './IPv6', './SecondLevelDomains'], factory); + } else { + // Browser globals (root is window) + root.URI = factory(root.punycode, root.IPv6, root.SecondLevelDomains); + } +}(this, function(punycode, IPv6, SLD) { + "use strict"; + + function URI(url, base) { + // Allow instantiation without the 'new' keyword + if (!(this instanceof URI)) { + return new URI(url, base); + } + if (url === undefined) { + if (typeof location !== 'undefined') { + url = location.href + ""; + } else { + url = ""; + } + } + this.href(url); + // resolve to base according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#constructor + if (base !== undefined) { + return this.absoluteTo(base); + } + return this; + }; + var p = URI.prototype; + var hasOwn = Object.prototype.hasOwnProperty; + + function escapeRegEx(string) { + // https://github.com/medialize/URI.js/commit/85ac21783c11f8ccab06106dba9735a31a86924d#commitcomment-821963 + return string.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); + } + + function isArray(obj) { + return String(Object.prototype.toString.call(obj)) === "[object Array]"; + } + + function filterArrayValues(data, value) { + var lookup = {}; + var i, length; + if (isArray(value)) { + for (i = 0, length = value.length; i < length; i++) { + lookup[value[i]] = true; + } + } else { + lookup[value] = true; + } + for (i = 0, length = data.length; i < length; i++) { + if (lookup[data[i]] !== undefined) { + data.splice(i, 1); + length--; + i--; + } + } + return data; + } + URI._parts = function() { + return { + protocol: null, + username: null, + password: null, + hostname: null, + urn: null, + port: null, + path: null, + query: null, + fragment: null, + // state + duplicateQueryParameters: URI.duplicateQueryParameters + }; + }; + // state: allow duplicate query parameters (a=1&a=1) + URI.duplicateQueryParameters = false; + // static properties + URI.protocol_expression = /^[a-z][a-z0-9-+-]*$/i; + URI.idn_expression = /[^a-z0-9\.-]/i; + URI.punycode_expression = /(xn--)/i; + // well, 333.444.555.666 matches, but it sure ain't no IPv4 - do we care? + URI.ip4_expression = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/; + // credits to Rich Brown + // source: http://forums.intermapper.com/viewtopic.php?p=1096#1096 + // specification: http://www.ietf.org/rfc/rfc4291.txt + URI.ip6_expression = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/; + // gruber revised expression - http://rodneyrehm.de/t/url-regex.html + URI.find_uri_expression = /\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/ig; + // http://www.iana.org/assignments/uri-schemes.html + // http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers#Well-known_ports + URI.defaultPorts = { + http: "80", + https: "443", + ftp: "21", + gopher: "70", + ws: "80", + wss: "443" + }; + // allowed hostname characters according to RFC 3986 + // ALPHA DIGIT "-" "." "_" "~" "!" "$" "&" "'" "(" ")" "*" "+" "," ";" "=" %encoded + // I've never seen a (non-IDN) hostname other than: ALPHA DIGIT . - + URI.invalid_hostname_characters = /[^a-zA-Z0-9\.-]/; + // encoding / decoding according to RFC3986 + + function strictEncodeURIComponent(string) { + // see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/encodeURIComponent + return encodeURIComponent(string).replace(/[!'()*]/g, escape).replace(/\*/g, "%2A"); + } + URI.encode = strictEncodeURIComponent; + URI.decode = decodeURIComponent; + URI.iso8859 = function() { + URI.encode = escape; + URI.decode = unescape; + }; + URI.unicode = function() { + URI.encode = strictEncodeURIComponent; + URI.decode = decodeURIComponent; + }; + URI.characters = { + pathname: { + encode: { + // RFC3986 2.1: For consistency, URI producers and normalizers should + // use uppercase hexadecimal digits for all percent-encodings. + expression: /%(24|26|2B|2C|3B|3D|3A|40)/ig, + map: { + // -._~!'()* + "%24": "$", + "%26": "&", + "%2B": "+", + "%2C": ",", + "%3B": ";", + "%3D": "=", + "%3A": ":", + "%40": "@" + } + }, + decode: { + expression: /[\/\?#]/g, + map: { + "/": "%2F", + "?": "%3F", + "#": "%23" + } + } + }, + reserved: { + encode: { + // RFC3986 2.1: For consistency, URI producers and normalizers should + // use uppercase hexadecimal digits for all percent-encodings. + expression: /%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/ig, + map: { + // gen-delims + "%3A": ":", + "%2F": "/", + "%3F": "?", + "%23": "#", + "%5B": "[", + "%5D": "]", + "%40": "@", + // sub-delims + "%21": "!", + "%24": "$", + "%26": "&", + "%27": "'", + "%28": "(", + "%29": ")", + "%2A": "*", + "%2B": "+", + "%2C": ",", + "%3B": ";", + "%3D": "=" + } + } + } + }; + URI.encodeQuery = function(string) { + return URI.encode(string + "").replace(/%20/g, '+'); + }; + URI.decodeQuery = function(string) { + return URI.decode((string + "").replace(/\+/g, '%20')); + }; + URI.recodePath = function(string) { + var segments = (string + "").split('/'); + for (var i = 0, length = segments.length; i < length; i++) { + segments[i] = URI.encodePathSegment(URI.decode(segments[i])); + } + return segments.join('/'); + }; + URI.decodePath = function(string) { + var segments = (string + "").split('/'); + for (var i = 0, length = segments.length; i < length; i++) { + segments[i] = URI.decodePathSegment(segments[i]); + } + return segments.join('/'); + }; + // generate encode/decode path functions + var _parts = { + 'encode': 'encode', + 'decode': 'decode' + }; + var _part; + var generateAccessor = function(_group, _part) { + return function(string) { + return URI[_part](string + "").replace(URI.characters[_group][_part].expression, function(c) { + return URI.characters[_group][_part].map[c]; + }); + }; + }; + for (_part in _parts) { + URI[_part + "PathSegment"] = generateAccessor("pathname", _parts[_part]); + } + URI.encodeReserved = generateAccessor("reserved", "encode"); + URI.parse = function(string, parts) { + var pos, t; + if (!parts) { + parts = {}; + } + // [protocol"://"[username[":"password]"@"]hostname[":"port]"/"?][path]["?"querystring]["#"fragment] + // extract fragment + pos = string.indexOf('#'); + if (pos > -1) { + // escaping? + parts.fragment = string.substring(pos + 1) || null; + string = string.substring(0, pos); + } + // extract query + pos = string.indexOf('?'); + if (pos > -1) { + // escaping? + parts.query = string.substring(pos + 1) || null; + string = string.substring(0, pos); + } + // extract protocol + if (string.substring(0, 2) === '//') { + // relative-scheme + parts.protocol = ''; + string = string.substring(2); + // extract "user:pass@host:port" + string = URI.parseAuthority(string, parts); + } else { + pos = string.indexOf(':'); + if (pos > -1) { + parts.protocol = string.substring(0, pos); + if (parts.protocol && !parts.protocol.match(URI.protocol_expression)) { + // : may be within the path + parts.protocol = undefined; + } else if (parts.protocol === 'file') { + // the file scheme: does not contain an authority + string = string.substring(pos + 3); + } else if (string.substring(pos + 1, pos + 3) === '//') { + string = string.substring(pos + 3); + // extract "user:pass@host:port" + string = URI.parseAuthority(string, parts); + } else { + string = string.substring(pos + 1); + parts.urn = true; + } + } + } + // what's left must be the path + parts.path = string; + // and we're done + return parts; + }; + URI.parseHost = function(string, parts) { + // extract host:port + var pos = string.indexOf('/'); + var bracketPos; + var t; + if (pos === -1) { + pos = string.length; + } + if (string[0] === "[") { + // IPv6 host - http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-04#section-6 + // I claim most client software breaks on IPv6 anyways. To simplify things, URI only accepts + // IPv6+port in the format [2001:db8::1]:80 (for the time being) + bracketPos = string.indexOf(']'); + parts.hostname = string.substring(1, bracketPos) || null; + parts.port = string.substring(bracketPos + 2, pos) || null; + } else if (string.indexOf(':') !== string.lastIndexOf(':')) { + // IPv6 host contains multiple colons - but no port + // this notation is actually not allowed by RFC 3986, but we're a liberal parser + parts.hostname = string.substring(0, pos) || null; + parts.port = null; + } else { + t = string.substring(0, pos).split(':'); + parts.hostname = t[0] || null; + parts.port = t[1] || null; + } + if (parts.hostname && string.substring(pos)[0] !== '/') { + pos++; + string = "/" + string; + } + return string.substring(pos) || '/'; + }; + URI.parseAuthority = function(string, parts) { + string = URI.parseUserinfo(string, parts); + return URI.parseHost(string, parts); + }; + URI.parseUserinfo = function(string, parts) { + // extract username:password + var pos = string.indexOf('@'); + var firstSlash = string.indexOf('/'); + var t; + // authority@ must come before /path + if (pos > -1 && (firstSlash === -1 || pos < firstSlash)) { + t = string.substring(0, pos).split(':'); + parts.username = t[0] ? URI.decode(t[0]) : null; + t.shift(); + parts.password = t[0] ? URI.decode(t.join(':')) : null; + string = string.substring(pos + 1); + } else { + parts.username = null; + parts.password = null; + } + return string; + }; + URI.parseQuery = function(string) { + if (!string) { + return {}; + } + // throw out the funky business - "?"[name"="value"&"]+ + string = string.replace(/&+/g, '&').replace(/^\?*&*|&+$/g, ''); + if (!string) { + return {}; + } + var items = {}; + var splits = string.split('&'); + var length = splits.length; + var v, name, value; + for (var i = 0; i < length; i++) { + v = splits[i].split('='); + name = URI.decodeQuery(v.shift()); + // no "=" is null according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#collect-url-parameters + value = v.length ? URI.decodeQuery(v.join('=')) : null; + if (items[name]) { + if (typeof items[name] === "string") { + items[name] = [items[name]]; + } + items[name].push(value); + } else { + items[name] = value; + } + } + return items; + }; + URI.build = function(parts) { + var t = ""; + if (parts.protocol) { + t += parts.protocol + ":"; + } + if (!parts.urn && (t || parts.hostname)) { + t += '//'; + } + t += (URI.buildAuthority(parts) || ''); + if (typeof parts.path === "string") { + if (parts.path[0] !== '/' && typeof parts.hostname === "string") { + t += '/'; + } + t += parts.path; + } + if (typeof parts.query === "string" && parts.query) { + t += '?' + parts.query; + } + if (typeof parts.fragment === "string" && parts.fragment) { + t += '#' + parts.fragment; + } + return t; + }; + URI.buildHost = function(parts) { + var t = ""; + if (!parts.hostname) { + return ""; + } else if (URI.ip6_expression.test(parts.hostname)) { + if (parts.port) { + t += "[" + parts.hostname + "]:" + parts.port; + } else { + // don't know if we should always wrap IPv6 in [] + // the RFC explicitly says SHOULD, not MUST. + t += parts.hostname; + } + } else { + t += parts.hostname; + if (parts.port) { + t += ':' + parts.port; + } + } + return t; + }; + URI.buildAuthority = function(parts) { + return URI.buildUserinfo(parts) + URI.buildHost(parts); + }; + URI.buildUserinfo = function(parts) { + var t = ""; + if (parts.username) { + t += URI.encode(parts.username); + if (parts.password) { + t += ':' + URI.encode(parts.password); + } + t += "@"; + } + return t; + }; + URI.buildQuery = function(data, duplicates) { + // according to http://tools.ietf.org/html/rfc3986 or http://labs.apache.org/webarch/uri/rfc/rfc3986.html + // being »-._~!$&'()*+,;=:@/?« %HEX and alnum are allowed + // the RFC explicitly states ?/foo being a valid use case, no mention of parameter syntax! + // URI.js treats the query string as being application/x-www-form-urlencoded + // see http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type + var t = ""; + var unique, key, i, length; + for (key in data) { + if (hasOwn.call(data, key) && key) { + if (isArray(data[key])) { + unique = {}; + for (i = 0, length = data[key].length; i < length; i++) { + if (data[key][i] !== undefined && unique[data[key][i] + ""] === undefined) { + t += "&" + URI.buildQueryParameter(key, data[key][i]); + if (duplicates !== true) { + unique[data[key][i] + ""] = true; + } + } + } + } else if (data[key] !== undefined) { + t += '&' + URI.buildQueryParameter(key, data[key]); + } + } + } + return t.substring(1); + }; + URI.buildQueryParameter = function(name, value) { + // http://www.w3.org/TR/REC-html40/interact/forms.html#form-content-type -- application/x-www-form-urlencoded + // don't append "=" for null values, according to http://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#url-parameter-serialization + return URI.encodeQuery(name) + (value !== null ? "=" + URI.encodeQuery(value) : ""); + }; + URI.addQuery = function(data, name, value) { + if (typeof name === "object") { + for (var key in name) { + if (hasOwn.call(name, key)) { + URI.addQuery(data, key, name[key]); + } + } + } else if (typeof name === "string") { + if (data[name] === undefined) { + data[name] = value; + return; + } else if (typeof data[name] === "string") { + data[name] = [data[name]]; + } + if (!isArray(value)) { + value = [value]; + } + data[name] = data[name].concat(value); + } else { + throw new TypeError("URI.addQuery() accepts an object, string as the name parameter"); + } + }; + URI.removeQuery = function(data, name, value) { + var i, length, key; + if (isArray(name)) { + for (i = 0, length = name.length; i < length; i++) { + data[name[i]] = undefined; + } + } else if (typeof name === "object") { + for (key in name) { + if (hasOwn.call(name, key)) { + URI.removeQuery(data, key, name[key]); + } + } + } else if (typeof name === "string") { + if (value !== undefined) { + if (data[name] === value) { + data[name] = undefined; + } else if (isArray(data[name])) { + data[name] = filterArrayValues(data[name], value); + } + } else { + data[name] = undefined; + } + } else { + throw new TypeError("URI.addQuery() accepts an object, string as the first parameter"); + } + }; + URI.commonPath = function(one, two) { + var length = Math.min(one.length, two.length); + var pos; + // find first non-matching character + for (pos = 0; pos < length; pos++) { + if (one[pos] !== two[pos]) { + pos--; + break; + } + } + if (pos < 1) { + return one[0] === two[0] && one[0] === '/' ? '/' : ''; + } + // revert to last / + if (one[pos] !== '/') { + pos = one.substring(0, pos).lastIndexOf('/'); + } + return one.substring(0, pos + 1); + }; + URI.withinString = function(string, callback) { + // expression used is "gruber revised" (@gruber v2) determined to be the best solution in + // a regex sprint we did a couple of ages ago at + // * http://mathiasbynens.be/demo/url-regex + // * http://rodneyrehm.de/t/url-regex.html + return string.replace(URI.find_uri_expression, callback); + }; + URI.ensureValidHostname = function(v) { + // Theoretically URIs allow percent-encoding in Hostnames (according to RFC 3986) + // they are not part of DNS and therefore ignored by URI.js + if (v.match(URI.invalid_hostname_characters)) { + // test punycode + if (!punycode) { + throw new TypeError("Hostname '" + v + "' contains characters other than [A-Z0-9.-] and Punycode.js is not available"); + } + if (punycode.toASCII(v).match(URI.invalid_hostname_characters)) { + throw new TypeError("Hostname '" + v + "' contains characters other than [A-Z0-9.-]"); + } + } + }; + p.build = function(deferBuild) { + if (deferBuild === true) { + this._deferred_build = true; + } else if (deferBuild === undefined || this._deferred_build) { + this._string = URI.build(this._parts); + this._deferred_build = false; + } + return this; + }; + p.clone = function() { + return new URI(this); + }; + p.valueOf = p.toString = function() { + return this.build(false)._string; + }; + // generate simple accessors + _parts = { + protocol: 'protocol', + username: 'username', + password: 'password', + hostname: 'hostname', + port: 'port' + }; + generateAccessor = function(_part) { + return function(v, build) { + if (v === undefined) { + return this._parts[_part] || ""; + } else { + this._parts[_part] = v; + this.build(!build); + return this; + } + }; + }; + for (_part in _parts) { + p[_part] = generateAccessor(_parts[_part]); + } + // generate accessors with optionally prefixed input + _parts = { + query: '?', + fragment: '#' + }; + generateAccessor = function(_part, _key) { + return function(v, build) { + if (v === undefined) { + return this._parts[_part] || ""; + } else { + if (v !== null) { + v = v + ""; + if (v[0] === _key) { + v = v.substring(1); + } + } + this._parts[_part] = v; + this.build(!build); + return this; + } + }; + }; + for (_part in _parts) { + p[_part] = generateAccessor(_part, _parts[_part]); + } + // generate accessors with prefixed output + _parts = { + search: ['?', 'query'], + hash: ['#', 'fragment'] + }; + generateAccessor = function(_part, _key) { + return function(v, build) { + var t = this[_part](v, build); + return typeof t === "string" && t.length ? (_key + t) : t; + }; + }; + for (_part in _parts) { + p[_part] = generateAccessor(_parts[_part][1], _parts[_part][0]); + } + p.pathname = function(v, build) { + if (v === undefined || v === true) { + var res = this._parts.path || (this._parts.urn ? '' : '/'); + return v ? URI.decodePath(res) : res; + } else { + this._parts.path = v ? URI.recodePath(v) : "/"; + this.build(!build); + return this; + } + }; + p.path = p.pathname; + p.href = function(href, build) { + var key; + if (href === undefined) { + return this.toString(); + } + this._string = ""; + this._parts = URI._parts(); + var _URI = href instanceof URI; + var _object = typeof href === "object" && (href.hostname || href.path); + // window.location is reported to be an object, but it's not the sort + // of object we're looking for: + // * location.protocol ends with a colon + // * location.query != object.search + // * location.hash != object.fragment + // simply serializing the unknown object should do the trick + // (for location, not for everything...) + if (!_URI && _object && Object.prototype.toString.call(href) !== "[object Object]") { + href = href.toString(); + } + if (typeof href === "string") { + this._parts = URI.parse(href, this._parts); + } else if (_URI || _object) { + var src = _URI ? href._parts : href; + for (key in src) { + if (hasOwn.call(this._parts, key)) { + this._parts[key] = src[key]; + } + } + } else { + throw new TypeError("invalid input"); + } + this.build(!build); + return this; + }; + // identification accessors + p.is = function(what) { + var ip = false; + var ip4 = false; + var ip6 = false; + var name = false; + var sld = false; + var idn = false; + var punycode = false; + var relative = !this._parts.urn; + if (this._parts.hostname) { + relative = false; + ip4 = URI.ip4_expression.test(this._parts.hostname); + ip6 = URI.ip6_expression.test(this._parts.hostname); + ip = ip4 || ip6; + name = !ip; + sld = name && SLD && SLD.has(this._parts.hostname); + idn = name && URI.idn_expression.test(this._parts.hostname); + punycode = name && URI.punycode_expression.test(this._parts.hostname); + } + switch (what.toLowerCase()) { + case 'relative': + return relative; + case 'absolute': + return !relative; + // hostname identification + case 'domain': + case 'name': + return name; + case 'sld': + return sld; + case 'ip': + return ip; + case 'ip4': + case 'ipv4': + case 'inet4': + return ip4; + case 'ip6': + case 'ipv6': + case 'inet6': + return ip6; + case 'idn': + return idn; + case 'url': + return !this._parts.urn; + case 'urn': + return !!this._parts.urn; + case 'punycode': + return punycode; + } + return null; + }; + // component specific input validation + var _protocol = p.protocol; + var _port = p.port; + var _hostname = p.hostname; + p.protocol = function(v, build) { + if (v !== undefined) { + if (v) { + // accept trailing :// + v = v.replace(/:(\/\/)?$/, ''); + if (v.match(/[^a-zA-z0-9\.+-]/)) { + throw new TypeError("Protocol '" + v + "' contains characters other than [A-Z0-9.+-]"); + } + } + } + return _protocol.call(this, v, build); + }; + p.scheme = p.protocol; + p.port = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (v !== undefined) { + if (v === 0) { + v = null; + } + if (v) { + v += ""; + if (v[0] === ":") { + v = v.substring(1); + } + if (v.match(/[^0-9]/)) { + throw new TypeError("Port '" + v + "' contains characters other than [0-9]"); + } + } + } + return _port.call(this, v, build); + }; + p.hostname = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (v !== undefined) { + var x = {}; + URI.parseHost(v, x); + v = x.hostname; + } + return _hostname.call(this, v, build); + }; + // compound accessors + p.host = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (v === undefined) { + return this._parts.hostname ? URI.buildHost(this._parts) : ""; + } else { + URI.parseHost(v, this._parts); + this.build(!build); + return this; + } + }; + p.authority = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (v === undefined) { + return this._parts.hostname ? URI.buildAuthority(this._parts) : ""; + } else { + URI.parseAuthority(v, this._parts); + this.build(!build); + return this; + } + }; + p.userinfo = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (v === undefined) { + if (!this._parts.username) { + return ""; + } + var t = URI.buildUserinfo(this._parts); + return t.substring(0, t.length - 1); + } else { + if (v[v.length - 1] !== '@') { + v += '@'; + } + URI.parseUserinfo(v, this._parts); + this.build(!build); + return this; + } + }; + p.resource = function(v, build) { + var parts; + if (v === undefined) { + return this.path() + this.search() + this.hash(); + } + parts = URI.parse(v); + this._parts.path = parts.path; + this._parts.query = parts.query; + this._parts.fragment = parts.fragment; + this.build(!build); + return this; + }; + // fraction accessors + p.subdomain = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + // convenience, return "www" from "www.example.org" + if (v === undefined) { + if (!this._parts.hostname || this.is('IP')) { + return ""; + } + // grab domain and add another segment + var end = this._parts.hostname.length - this.domain().length - 1; + return this._parts.hostname.substring(0, end) || ""; + } else { + var e = this._parts.hostname.length - this.domain().length; + var sub = this._parts.hostname.substring(0, e); + var replace = new RegExp('^' + escapeRegEx(sub)); + if (v && v[v.length - 1] !== '.') { + v += "."; + } + if (v) { + URI.ensureValidHostname(v); + } + this._parts.hostname = this._parts.hostname.replace(replace, v); + this.build(!build); + return this; + } + }; + p.domain = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (typeof v === 'boolean') { + build = v; + v = undefined; + } + // convenience, return "example.org" from "www.example.org" + if (v === undefined) { + if (!this._parts.hostname || this.is('IP')) { + return ""; + } + // if hostname consists of 1 or 2 segments, it must be the domain + var t = this._parts.hostname.match(/\./g); + if (t && t.length < 2) { + return this._parts.hostname; + } + // grab tld and add another segment + var end = this._parts.hostname.length - this.tld(build).length - 1; + end = this._parts.hostname.lastIndexOf('.', end - 1) + 1; + return this._parts.hostname.substring(end) || ""; + } else { + if (!v) { + throw new TypeError("cannot set domain empty"); + } + URI.ensureValidHostname(v); + if (!this._parts.hostname || this.is('IP')) { + this._parts.hostname = v; + } else { + var replace = new RegExp(escapeRegEx(this.domain()) + "$"); + this._parts.hostname = this._parts.hostname.replace(replace, v); + } + this.build(!build); + return this; + } + }; + p.tld = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (typeof v === 'boolean') { + build = v; + v = undefined; + } + // return "org" from "www.example.org" + if (v === undefined) { + if (!this._parts.hostname || this.is('IP')) { + return ""; + } + var pos = this._parts.hostname.lastIndexOf('.'); + var tld = this._parts.hostname.substring(pos + 1); + if (build !== true && SLD && SLD.list[tld.toLowerCase()]) { + return SLD.get(this._parts.hostname) || tld; + } + return tld; + } else { + var replace; + if (!v) { + throw new TypeError("cannot set TLD empty"); + } else if (v.match(/[^a-zA-Z0-9-]/)) { + if (SLD && SLD.is(v)) { + replace = new RegExp(escapeRegEx(this.tld()) + "$"); + this._parts.hostname = this._parts.hostname.replace(replace, v); + } else { + throw new TypeError("TLD '" + v + "' contains characters other than [A-Z0-9]"); + } + } else if (!this._parts.hostname || this.is('IP')) { + throw new ReferenceError("cannot set TLD on non-domain host"); + } else { + replace = new RegExp(escapeRegEx(this.tld()) + "$"); + this._parts.hostname = this._parts.hostname.replace(replace, v); + } + this.build(!build); + return this; + } + }; + p.directory = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (v === undefined || v === true) { + if (!this._parts.path && !this._parts.hostname) { + return ''; + } + if (this._parts.path === '/') { + return '/'; + } + var end = this._parts.path.length - this.filename().length - 1; + var res = this._parts.path.substring(0, end) || (this._parts.hostname ? "/" : ""); + return v ? URI.decodePath(res) : res; + } else { + var e = this._parts.path.length - this.filename().length; + var directory = this._parts.path.substring(0, e); + var replace = new RegExp('^' + escapeRegEx(directory)); + // fully qualifier directories begin with a slash + if (!this.is('relative')) { + if (!v) { + v = '/'; + } + if (v[0] !== '/') { + v = "/" + v; + } + } + // directories always end with a slash + if (v && v[v.length - 1] !== '/') { + v += '/'; + } + v = URI.recodePath(v); + this._parts.path = this._parts.path.replace(replace, v); + this.build(!build); + return this; + } + }; + p.filename = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (v === undefined || v === true) { + if (!this._parts.path || this._parts.path === '/') { + return ""; + } + var pos = this._parts.path.lastIndexOf('/'); + var res = this._parts.path.substring(pos + 1); + return v ? URI.decodePathSegment(res) : res; + } else { + var mutatedDirectory = false; + if (v[0] === '/') { + v = v.substring(1); + } + if (v.match(/\.?\//)) { + mutatedDirectory = true; + } + var replace = new RegExp(escapeRegEx(this.filename()) + "$"); + v = URI.recodePath(v); + this._parts.path = this._parts.path.replace(replace, v); + if (mutatedDirectory) { + this.normalizePath(build); + } else { + this.build(!build); + } + return this; + } + }; + p.suffix = function(v, build) { + if (this._parts.urn) { + return v === undefined ? '' : this; + } + if (v === undefined || v === true) { + if (!this._parts.path || this._parts.path === '/') { + return ""; + } + var filename = this.filename(); + var pos = filename.lastIndexOf('.'); + var s, res; + if (pos === -1) { + return ""; + } + // suffix may only contain alnum characters (yup, I made this up.) + s = filename.substring(pos + 1); + res = (/^[a-z0-9%]+$/i).test(s) ? s : ""; + return v ? URI.decodePathSegment(res) : res; + } else { + if (v[0] === '.') { + v = v.substring(1); + } + var suffix = this.suffix(); + var replace; + if (!suffix) { + if (!v) { + return this; + } + this._parts.path += '.' + URI.recodePath(v); + } else if (!v) { + replace = new RegExp(escapeRegEx("." + suffix) + "$"); + } else { + replace = new RegExp(escapeRegEx(suffix) + "$"); + } + if (replace) { + v = URI.recodePath(v); + this._parts.path = this._parts.path.replace(replace, v); + } + this.build(!build); + return this; + } + }; + p.segment = function(segment, v, build) { + var separator = this._parts.urn ? ':' : '/'; + var path = this.path(); + var absolute = path.substring(0, 1) === '/'; + var segments = path.split(separator); + if (typeof segment !== 'number') { + build = v; + v = segment; + segment = undefined; + } + if (segment !== undefined && typeof segment !== 'number') { + throw new Error("Bad segment '" + segment + "', must be 0-based integer"); + } + if (absolute) { + segments.shift(); + } + if (segment < 0) { + // allow negative indexes to address from the end + segment = Math.max(segments.length + segment, 0); + } + if (v === undefined) { + return segment === undefined ? segments : segments[segment]; + } else if (segment === null || segments[segment] === undefined) { + if (isArray(v)) { + segments = v; + } else if (v || (typeof v === "string" && v.length)) { + if (segments[segments.length - 1] === "") { + // empty trailing elements have to be overwritten + // to prefent results such as /foo//bar + segments[segments.length - 1] = v; + } else { + segments.push(v); + } + } + } else { + if (v || (typeof v === "string" && v.length)) { + segments[segment] = v; + } else { + segments.splice(segment, 1); + } + } + if (absolute) { + segments.unshift(""); + } + return this.path(segments.join(separator), build); + }; + // mutating query string + var q = p.query; + p.query = function(v, build) { + if (v === true) { + return URI.parseQuery(this._parts.query); + } else if (v !== undefined && typeof v !== "string") { + this._parts.query = URI.buildQuery(v, this._parts.duplicateQueryParameters); + this.build(!build); + return this; + } else { + return q.call(this, v, build); + } + }; + p.addQuery = function(name, value, build) { + var data = URI.parseQuery(this._parts.query); + URI.addQuery(data, name, value === undefined ? null : value); + this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters); + if (typeof name !== "string") { + build = value; + } + this.build(!build); + return this; + }; + p.removeQuery = function(name, value, build) { + var data = URI.parseQuery(this._parts.query); + URI.removeQuery(data, name, value); + this._parts.query = URI.buildQuery(data, this._parts.duplicateQueryParameters); + if (typeof name !== "string") { + build = value; + } + this.build(!build); + return this; + }; + p.addSearch = p.addQuery; + p.removeSearch = p.removeQuery; + // sanitizing URLs + p.normalize = function() { + if (this._parts.urn) { + return this.normalizeProtocol(false).normalizeQuery(false).normalizeFragment(false).build(); + } + return this.normalizeProtocol(false).normalizeHostname(false).normalizePort(false).normalizePath(false).normalizeQuery(false).normalizeFragment(false).build(); + }; + p.normalizeProtocol = function(build) { + if (typeof this._parts.protocol === "string") { + this._parts.protocol = this._parts.protocol.toLowerCase(); + this.build(!build); + } + return this; + }; + p.normalizeHostname = function(build) { + if (this._parts.hostname) { + if (this.is('IDN') && punycode) { + this._parts.hostname = punycode.toASCII(this._parts.hostname); + } else if (this.is('IPv6') && IPv6) { + this._parts.hostname = IPv6.best(this._parts.hostname); + } + this._parts.hostname = this._parts.hostname.toLowerCase(); + this.build(!build); + } + return this; + }; + p.normalizePort = function(build) { + // remove port of it's the protocol's default + if (typeof this._parts.protocol === "string" && this._parts.port === URI.defaultPorts[this._parts.protocol]) { + this._parts.port = null; + this.build(!build); + } + return this; + }; + p.normalizePath = function(build) { + if (this._parts.urn) { + return this; + } + if (!this._parts.path || this._parts.path === '/') { + return this; + } + var _was_relative; + var _was_relative_prefix; + var _path = this._parts.path; + var _parent, _pos; + // handle relative paths + if (_path[0] !== '/') { + if (_path[0] === '.') { + _was_relative_prefix = _path.substring(0, _path.indexOf('/')); + } + _was_relative = true; + _path = '/' + _path; + } + // resolve simples + _path = _path.replace(/(\/(\.\/)+)|\/{2,}/g, '/'); + // resolve parents + while (true) { + _parent = _path.indexOf('/../'); + if (_parent === -1) { + // no more ../ to resolve + break; + } else if (_parent === 0) { + // top level cannot be relative... + _path = _path.substring(3); + break; + } + _pos = _path.substring(0, _parent).lastIndexOf('/'); + if (_pos === -1) { + _pos = _parent; + } + _path = _path.substring(0, _pos) + _path.substring(_parent + 3); + } + // revert to relative + if (_was_relative && this.is('relative')) { + if (_was_relative_prefix) { + _path = _was_relative_prefix + _path; + } else { + _path = _path.substring(1); + } + } + _path = URI.recodePath(_path); + this._parts.path = _path; + this.build(!build); + return this; + }; + p.normalizePathname = p.normalizePath; + p.normalizeQuery = function(build) { + if (typeof this._parts.query === "string") { + if (!this._parts.query.length) { + this._parts.query = null; + } else { + this.query(URI.parseQuery(this._parts.query)); + } + this.build(!build); + } + return this; + }; + p.normalizeFragment = function(build) { + if (!this._parts.fragment) { + this._parts.fragment = null; + this.build(!build); + } + return this; + }; + p.normalizeSearch = p.normalizeQuery; + p.normalizeHash = p.normalizeFragment; + p.iso8859 = function() { + // expect unicode input, iso8859 output + var e = URI.encode; + var d = URI.decode; + URI.encode = escape; + URI.decode = decodeURIComponent; + this.normalize(); + URI.encode = e; + URI.decode = d; + return this; + }; + p.unicode = function() { + // expect iso8859 input, unicode output + var e = URI.encode; + var d = URI.decode; + URI.encode = strictEncodeURIComponent; + URI.decode = unescape; + this.normalize(); + URI.encode = e; + URI.decode = d; + return this; + }; + p.readable = function() { + var uri = this.clone(); + // removing username, password, because they shouldn't be displayed according to RFC 3986 + uri.username("").password("").normalize(); + var t = ''; + if (uri._parts.protocol) { + t += uri._parts.protocol + '://'; + } + if (uri._parts.hostname) { + if (uri.is('punycode') && punycode) { + t += punycode.toUnicode(uri._parts.hostname); + if (uri._parts.port) { + t += ":" + uri._parts.port; + } + } else { + t += uri.host(); + } + } + if (uri._parts.hostname && uri._parts.path && uri._parts.path[0] !== '/') { + t += '/'; + } + t += uri.path(true); + if (uri._parts.query) { + var q = ''; + for (var i = 0, qp = uri._parts.query.split('&'), l = qp.length; i < l; i++) { + var kv = (qp[i] || "").split('='); + q += '&' + URI.decodeQuery(kv[0]).replace(/&/g, '%26'); + if (kv[1] !== undefined) { + q += "=" + URI.decodeQuery(kv[1]).replace(/&/g, '%26'); + } + } + t += '?' + q.substring(1); + } + t += uri.hash(); + return t; + }; + // resolving relative and absolute URLs + p.absoluteTo = function(base) { + var resolved = this.clone(); + var properties = ['protocol', 'username', 'password', 'hostname', 'port']; + var basedir, i, p; + if (this._parts.urn) { + throw new Error('URNs do not have any generally defined hierachical components'); + } + if (this._parts.hostname) { + return resolved; + } + if (!(base instanceof URI)) { + base = new URI(base); + } + for (i = 0, p; p = properties[i]; i++) { + resolved._parts[p] = base._parts[p]; + } + properties = ['query', 'path']; + for (i = 0, p; p = properties[i]; i++) { + if (!resolved._parts[p] && base._parts[p]) { + resolved._parts[p] = base._parts[p]; + } + } + if (resolved.path()[0] !== '/') { + basedir = base.directory(); + resolved._parts.path = (basedir ? (basedir + '/') : '') + resolved._parts.path; + resolved.normalizePath(); + } + resolved.build(); + return resolved; + }; + p.relativeTo = function(base) { + var relative = this.clone(); + var properties = ['protocol', 'username', 'password', 'hostname', 'port']; + var common, _base, _this, _base_diff, _this_diff; + if (this._parts.urn) { + throw new Error('URNs do not have any generally defined hierachical components'); + } + if (!(base instanceof URI)) { + base = new URI(base); + } + if (this.path()[0] !== '/' || base.path()[0] !== '/') { + throw new Error('Cannot calculate common path from non-relative URLs'); + } + // determine common sub path + common = URI.commonPath(relative.path(), base.path()); + // no relation if there's nothing in common + if (!common || common === '/') { + return relative; + } + // relative paths don't have authority + for (var i = 0, p; p = properties[i]; i++) { + relative._parts[p] = null; + } + _base = base.directory(); + _this = this.directory(); + // base and this are on the same level + if (_base === _this) { + relative._parts.path = './' + relative.filename(); + return relative.build(); + } + _base_diff = _base.substring(common.length); + _this_diff = _this.substring(common.length); + // this is a descendant of base + if (_base + '/' === common) { + if (_this_diff) { + _this_diff += '/'; + } + relative._parts.path = './' + _this_diff + relative.filename(); + return relative.build(); + } + // this is a descendant of base + var parents = '../'; + var _common = new RegExp('^' + escapeRegEx(common)); + var _parents = _base.replace(_common, '/').match(/\//g).length - 1; + while (_parents--) { + parents += '../'; + } + relative._parts.path = relative._parts.path.replace(_common, parents); + return relative.build(); + }; + // comparing URIs + p.equals = function(uri) { + var one = this.clone(); + var two = new URI(uri); + var one_map = {}; + var two_map = {}; + var checked = {}; + var one_query, two_query, key; + one.normalize(); + two.normalize(); + // exact match + if (one.toString() === two.toString()) { + return true; + } + // extract query string + one_query = one.query(); + two_query = two.query(); + one.query(""); + two.query(""); + // definitely not equal if not even non-query parts match + if (one.toString() !== two.toString()) { + return false; + } + // query parameters have the same length, even if they're permutated + if (one_query.length !== two_query.length) { + return false; + } + one_map = URI.parseQuery(one_query); + two_map = URI.parseQuery(two_query); + for (key in one_map) { + if (hasOwn.call(one_map, key)) { + if (!isArray(one_map[key])) { + if (one_map[key] !== two_map[key]) { + return false; + } + } else { + if (!isArray(two_map[key])) { + return false; + } + // arrays can't be equal if they have different amount of content + if (one_map[key].length !== two_map[key].length) { + return false; + } + one_map[key].sort(); + two_map[key].sort(); + for (var i = 0, l = one_map[key].length; i < l; i++) { + if (one_map[key][i] !== two_map[key][i]) { + return false; + } + } + } + checked[key] = true; + } + } + for (key in two_map) { + if (hasOwn.call(two_map, key)) { + if (!checked[key]) { + // two contains a parameter not present in one + return false; + } + } + } + return true; + }; + // state + p.duplicateQueryParameters = function(v) { + this._parts.duplicateQueryParameters = !! v; + return this; + }; + return URI; +})); \ No newline at end of file diff --git a/doc/scripts/bootstrap-dropdown.js b/doc/scripts/bootstrap-dropdown.js new file mode 100644 index 0000000..d04da5d --- /dev/null +++ b/doc/scripts/bootstrap-dropdown.js @@ -0,0 +1,169 @@ +/* ============================================================ + * bootstrap-dropdown.js v2.3.2 + * http://getbootstrap.com/2.3.2/javascript.html#dropdowns + * ============================================================ + * Copyright 2013 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================ */ + + +!function ($) { + + "use strict"; // jshint ;_; + + + /* DROPDOWN CLASS DEFINITION + * ========================= */ + + var toggle = '[data-toggle=dropdown]' + , Dropdown = function (element) { + var $el = $(element).on('click.dropdown.data-api', this.toggle) + $('html').on('click.dropdown.data-api', function () { + $el.parent().removeClass('open') + }) + } + + Dropdown.prototype = { + + constructor: Dropdown + + , toggle: function (e) { + var $this = $(this) + , $parent + , isActive + + if ($this.is('.disabled, :disabled')) return + + $parent = getParent($this) + + isActive = $parent.hasClass('open') + + clearMenus() + + if (!isActive) { + if ('ontouchstart' in document.documentElement) { + // if mobile we we use a backdrop because click events don't delegate + $('