1 /* plugin.js is part of Aloha Editor project http://aloha-editor.org
  2  *
  3  * Aloha Editor is a WYSIWYG HTML5 inline editing library and editor. 
  4  * Copyright (c) 2010-2012 Gentics Software GmbH, Vienna, Austria.
  5  * Contributors http://aloha-editor.org/contribution.php 
  6  * 
  7  * Aloha Editor is free software; you can redistribute it and/or
  8  * modify it under the terms of the GNU General Public License
  9  * as published by the Free Software Foundation; either version 2
 10  * of the License, or any later version.
 11  *
 12  * Aloha Editor is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15  * GNU General Public License for more details.
 16  *
 17  * You should have received a copy of the GNU General Public License
 18  * along with this program; if not, write to the Free Software
 19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 20  * 
 21  * As an additional permission to the GNU GPL version 2, you may distribute
 22  * non-source (e.g., minimized or compacted) forms of the Aloha-Editor
 23  * source code without the copy of the GNU GPL normally required,
 24  * provided you include this license notice and a URL through which
 25  * recipients can access the Corresponding Source.
 26  */
 27 define([
 28 	'aloha/core',
 29 	'jquery',
 30 	'util/class',
 31 	'aloha/pluginmanager',
 32 	'aloha/console'
 33 ], function (
 34 	Aloha,
 35 	jQuery,
 36 	Class,
 37 	PluginManager,
 38 	console
 39 ) {
 40 	"use strict";
 41 
 42 	/**
 43  44 	 * Gets the original object from the editable. If the editable is an input or textarea,
 45 	 * aloha creates a editable div, but sometimes we need the original object and not the div
 46 	 * created by aloha.
 47 	 * @param {jQuery} editableElement
 48 	 * @returns {jQuery}
 49 	 */
 50 	function getEditableOriginalObj(editableElement) {
 51 		var editable = Aloha.getEditableById(editableElement.attr('id'));
 52 
 53 		return editable ? editable.originalObj : editableElement;
 54 	}
 55 
 56 	/**
 57 	 * Abstract Plugin Object
 58 	 * @namespace Aloha
 59 	 * @class Plugin
 60 	 * @constructor
 61 	 * @param {String} pluginPrefix unique plugin prefix
 62 	 */
 63 	var Plugin = Class.extend({
 64 
 65 		name: null,
 66 
 67 		/**
 68 		 * contains the plugin's default settings object
 69 		 * @cfg {Object} default settings for the plugin
 70 		 */
 71 		defaults: {},
 72 
 73 		/**
 74 		 * contains the plugin's settings object
 75 		 * @cfg {Object} settings the plugins settings stored in an object
 76 		 */
 77 		settings: {},
 78 
 79 		/**
 80 		 * Names of other plugins which must be loaded in order for this plugin to
 81 		 * function.
 82 		 * @cfg {Array}
 83 		 */
 84 		dependencies: [],
 85 
 86 		_constructor: function (name) {
 87 			/**
 88 			 * Settings of the plugin
 89 			 */
 90 			if (typeof name !== "string") {
 91 				console.error('Cannot initialise unnamed plugin, skipping');
 92 			} else {
 93 				this.name = name;
 94 			}
 95 		},
 96 
 97 		/**
 98 		 * @return true if dependencies satisfied, false otherwise
 99 		 */
100 		checkDependencies: function () {
101 			var plugin = this;
102 			var satisfied = true;
103 			jQuery.each(plugin.dependencies, function (i, dependency) {
104 				if (!Aloha.isPluginLoaded(dependency.toString())) {
105 					satisfied = false;
106 					console.error('plugin.' + plugin.name,
107 							'Required plugin "' + dependency + '" not found.');
108 					return false;
109 				}
110 			});
111 			return satisfied;
112 		},
113 
114 		/**
115 		 * Init method of the plugin. Called from Aloha Core to initialize this plugin
116 		 * @return void
117 		 * @hide
118 		 */
119 		init: function () {},
120 
121 		/**
122 		 * Get the configuration settings for an editable obj.
123 		 * Handles both conf arrays or conf objects
124 		 * <ul>
125 		 * <li>Array configuration parameters are:
126 		 * <pre>
127 		 * "list": {
128 		 *		config : [ 'b', 'h1' ],
129 		 *		editables : {
130 		 *			'#title'	: [ ],
131 		 *			'div'		: [ 'b', 'i' ],
132 		 *			'.article'	: [ 'h1' ]
133 		 *		}
134 		 *	}
135 		 * </pre>
136 		 *
137 		 * The hash keys of the editables are css selectors. For a
138 		 *
139 		 * <pre>
140 		 *  <div class="article">content</div>
141 		 * </pre>
142 		 *
143 		 *  the selectors 'div' and '.article' match and the returned configuration is
144 		 *
145 		 * <pre>
146 		 *  [ 'b', 'i', 'h1']
147 		 * </pre>
148 		 *
149 150 		 * The '#title' object would return an empty configuration.
151 		 *
152 		 * <pre>
153 		 *  [ ]
154 		 * </pre>
155 		 *
156 		 *  All other objects would get the 'config' configuration. If config is not set
157 		 * the plugin default configuration is returned.
158 		 *
159 		 * <pre>
160 		 *  [ 'b', 'h1']
161 		 * </pre></li>
162 		 * <li>Object configuration parameters are :
163 		 * <pre>
164 		 *	"image": {
165 		 *		config : { 'img': { 'max_width': '50px',
166 		 *		'max_height': '50px' }},
167 		 *		editables : {
168 		 *			'#title': {},
169 		 *			'div': {'img': {}},
170 		 *			'.article': {'img': { 'max_width': '150px',
171 		 *			'max_height': '150px' }}
172 		 *		}
173 		 *	}
174 		 * </pre>
175 		 *  The '#title' object would return an empty configuration.<br/>
176 		 *  The 'div' object would return the default configuration.<br/>
177 		 *  the '.article' would return :
178 		 *  <pre>
179 		 *		{'img': { 'max_width': '150px',
180 		 *		'max_height': '150px' }}
181 		 *  </pre>
182 		 * </li>
183 		 *
184 		 * @param {jQuery} obj jQuery object of an Editable Object
185 		 * @return {Array} config A Array with configuration entries
186 		 */
187 		getEditableConfig: function (obj) {
188 			var configObj = null,
189 				configSpecified = false,
190 				that = this;
191 
192 			if (this.settings.editables) {
193 				// When editable is an input or textarea we need the original object.
194 				obj = getEditableOriginalObj(obj);
195 
196 				// check if the editable's selector matches and if so add its configuration to object configuration
197 				jQuery.each(this.settings.editables, function (selector, selectorConfig) {
198 					var k;
199 					if (obj.is(selector)) {
200 						configSpecified = true;
201 						if (selectorConfig instanceof Array) {
202 							configObj = [];
203 							configObj = jQuery.merge(configObj, selectorConfig);
204 						} else if (typeof selectorConfig === "object") {
205 							configObj = {};
206 							configObj['aloha-editable-selector'] = selector;
207 							for (k in selectorConfig) {
208 								if (selectorConfig.hasOwnProperty(k)) {
209 									if (selectorConfig[k] instanceof Array) {
210 										//configObj[k] = [];
211 										//configObj[k] = jQuery.extend(true, configObj[k], that.config[k], selectorConfig[k]);
212 										configObj[k] = selectorConfig[k];
213 									} else if (typeof selectorConfig[k] === "object") {
214 										configObj[k] = {};
215 										configObj[k] = jQuery.extend(true, configObj[k], that.config[k], selectorConfig[k]);
216 									} else {
217 										configObj[k] = selectorConfig[k];
218 									}
219 								}
220 							}
221 						} else {
222 							configObj = selectorConfig;
223 						}
224 					}
225 				});
226 			}
227 
228 			// fall back to default configuration
229 			if (!configSpecified) {
230 				if (typeof this.settings.config === 'undefined' || !this.settings.config) {
231 					configObj = this.config;
232 				} else {
233 					configObj = this.settings.config;
234 				}
235 			}
236 
237 			return configObj;
238 		},
239 
240 		/**
241 		 * Make the given jQuery object (representing an editable) clean for saving
242 		 * @param obj jQuery object to make clean
243 		 * @return void
244 		 */
245 		makeClean: function (obj) {},
246 
247 		/**
248 		 * Make a system-wide unique id out of a plugin-wide unique id by prefixing it with the plugin prefix
249 		 * @param id plugin-wide unique id
250 		 * @return system-wide unique id
251 252 		 * @hide
253 		 * @deprecated
254 		 */
255 		getUID: function (id) {
256 			console.deprecated('plugin', 'getUID() is deprecated. Use plugin.name instead.');
257 			return this.name;
258 		},
259 
260 		/**
261 		 * Return string representation of the plugin, which is the prefix
262 		 * @return name
263 		 * @hide
264 		 * @deprecated
265 		 */
266 		toString: function () {
267 			return this.name;
268 		},
269 
270 		/**
271 		 * Log a plugin message to the logger
272 		 * @param level log level
273 		 * @param message log message
274 		 * @return void
275 		 * @hide
276 		 * @deprecated
277 		 */
278 		log: function (level, message) {
279 			console.deprecated('plugin', 'log() is deprecated. Use Aloha.console instead.');
280 			console.log(level, this, message);
281 		}
282 	});
283 
284 	/**
285 	 * Static method used as factory to create plugins.
286 	 * 
287 	 * @param {String} pluginName name of the plugin
288 	 * @param {Object} definition definition of the plugin, should have at least an "init" and "destroy" method.
289 	 */
290 	Plugin.create = function (pluginName, definition) {
291 
292 		var pluginInstance = new (Plugin.extend(definition))(pluginName);
293 		pluginInstance.settings = jQuery.extendObjects(true, pluginInstance.defaults, Aloha.settings[pluginName]);
294 		PluginManager.register(pluginInstance);
295 
296 		return pluginInstance;
297 	};
298 
299 	return Plugin;
300 });
301