1 /* core.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 
 29 [
 30 	'jquery',
 31 	'aloha/pluginmanager'
 32 ],
 33 
 34 function ( jQuery, PluginManager ) {
 35 	"use strict";
 36 
 37 	//----------------------------------------
 38 	// Private variables
 39 	//----------------------------------------
 40 
 41 	/**
 42 	 * Base Aloha Object
 43 	 * @namespace Aloha
 44 	 * @class Aloha The Aloha base object, which contains all the core functionality
 45 	 * @singleton
 46 	 */
 47 	jQuery.extend(true, Aloha, {
 48 
 49 		/**
 50 		 * The Aloha Editor Version we are using
 51 		 * It should be set by us and updated for the particular branch
 52 		 * @property
 53 		 */
 54 		version: '${version}',
 55 
 56 		/**
 57 		 * Array of editables that are managed by Aloha
 58 		 * @property
 59 		 * @type Array
 60 		 */
 61 		editables: [],
 62 
 63 		/**
 64 		 * The currently active editable is referenced here
 65 		 * @property
 66 		 * @type Aloha.Editable
 67 		 */
 68 		activeEditable: null,
 69 
 70 		/**
 71 		 * settings object, which will contain all Aloha settings
 72 		 * @cfg {Object} object Aloha's settings
 73 		 */
 74 		settings: {},
 75 		
 76 		/**
 77 		 * defaults object, which will contain all Aloha defaults
 78 		 * @cfg {Object} object Aloha's settings
 79 		 */
 80 		defaults: {},
 81 		
 82 		/**
 83 		 * Namespace for ui components
 84 		 */
 85 		ui: {},
 86 		
 87 		/**
 88 		 * This represents the name of the users OS. Could be:
 89 		 * 'Mac', 'Linux', 'Win', 'Unix', 'Unknown'
 90 		 * @property
 91 		 * @type string
 92 		 */
 93 		OSName: 'Unknown',
 94 
 95         /**
 96          * Which stage is the aloha init process at?
 97          * @property
 98  99          * @type string
100          */
101         stage: 'loadingAloha',
102 
103         /**
104          * A list of loaded plugin names. Available after the
105          * "loadPlugins" stage.
106          *
107          * @property
108          * @type array
109          * @internal
110          */
111         loadedPlugins: [],
112 
113 		/**
114 		 * Maps names of plugins (link) to the base URL (../plugins/common/link).
115 		 */
116 		_pluginBaseUrlByName: {},
117 
118 		/**
119 		 * Initialize the initialization process
120 		 */
121 		init: function () {
122 			// Load & Initialise
123 			Aloha.stage = 'initAloha';
124 			Aloha.initAloha(function(){
125 				Aloha.stage = 'initPlugins';
126 				Aloha.initPlugins(function(){
127 					Aloha.stage = 'initGui';
128 					Aloha.initGui(function(){
129 						Aloha.stage = 'alohaReady';
130 						Aloha.trigger('aloha-ready');
131 					});
132 				});
133 			});
134 		},
135 
136 		/**
137 		 * Returns list of loaded plugins (without Bundle name)
138 		 *
139 		 * @return array
140 		 */
141 		getLoadedPlugins: function() {
142 			return this.loadedPlugins;
143 		},
144 
145 		/**
146 		 * Returns true if a certain plugin is loaded, false otherwise.
147 		 */
148 		isPluginLoaded: function(pluginName) {
149 			var found = false;
150 			jQuery.each(this.loadedPlugins, function() {
151 				if (pluginName.toString() === this.toString()) {
152 					found = true;
153 				}
154 			});
155 			return found;
156 		},
157 
158 		/**
159 		 * Initialise Aloha
160 		 */
161 		initAloha: function(next){
162 			// check browser version on init
163 			// this has to be revamped, as
164 			if (jQuery.browser.webkit && parseFloat(jQuery.browser.version) < 532.5 || // Chrome/Safari 4
165 				jQuery.browser.mozilla && parseFloat(jQuery.browser.version) < 1.9 || // FF 3.5
166 				jQuery.browser.msie && jQuery.browser.version < 7 || // IE 7
167 				jQuery.browser.opera && jQuery.browser.version < 11 ) { // right now, Opera needs some work
168 				if (window.console && window.console.log) {
169 					window.console.log( 'Your browser is not supported.' );
170 				}
171 			}
172 
173 			// register the body click event to blur editables
174 			jQuery('html').mousedown(function(e) {
175 				// This is a hack to prevent a click into a modal dialog from blurring the editable.
176 				if (Aloha.activeEditable && !jQuery(".aloha-dialog").is(':visible') && !Aloha.eventHandled) {
177 					Aloha.activeEditable.blur();
178 					Aloha.activeEditable = null;
179 				}
180 			}).mouseup(function(e) {
181 				Aloha.eventHandled = false;
182 			});
183 			
184 			// Initialise the base path to the aloha files
185 			Aloha.settings.base = Aloha.getAlohaUrl();
186 
187 			// initialize the Log
188 			Aloha.Log.init();
189 
190 			// initialize the error handler for general javascript errors
191 192 			if ( Aloha.settings.errorhandling ) {
193 				window.onerror = function (msg, url, linenumber) {
194 					Aloha.Log.error(Aloha, 'Error message: ' + msg + '\nURL: ' + url + '\nLine Number: ' + linenumber);
195 					// TODO eventually add a message to the message line?
196 					return true;
197 				};
198 			}
199 
200 			// OS detection
201 			if (navigator.appVersion.indexOf('Win') != -1) {
202 				Aloha.OSName = 'Win';
203 			}
204 			if (navigator.appVersion.indexOf('Mac') != -1) {
205 				Aloha.OSName = 'Mac';
206 			}
207 			if (navigator.appVersion.indexOf('X11') != -1) {
208 				Aloha.OSName = 'Unix';
209 			}
210 			if (navigator.appVersion.indexOf('Linux') != -1) {
211 				Aloha.OSName = 'Linux';
212 			}
213 
214 			try {
215 				// this will disable browsers image resizing facilities
216 				// disable resize handles
217 				var supported;
218 				try {
219 					supported = document.queryCommandSupported( 'enableObjectResizing' );
220 				} catch ( e ) {
221 					supported = false;
222 					Aloha.Log.log( 'enableObjectResizing is not supported.' );
223 				}
224 				
225 				if ( supported ) {
226 					document.execCommand( 'enableObjectResizing', false, false);
227 					Aloha.Log.log( 'enableObjectResizing disabled.' );
228 				}
229 			} catch (e) {
230 				Aloha.Log.error( e, 'Could not disable enableObjectResizing' );
231 				// this is just for others, who will not support disabling enableObjectResizing
232 			}
233 			// Forward
234 			next();
235 		},
236 
237 		/**
238 		 * Loads plugins Aloha
239 		 * @return void
240 		 */
241 		initPlugins: function (next) {
242 			PluginManager.init(next, this.getLoadedPlugins());
243 		},
244 
245 		/**
246 		 * Loads GUI components
247 		 * @return void
248 		 */
249 		initGui: function (next) {
250 			
251 			Aloha.RepositoryManager.init();
252 
253 			// activate registered editables
254 			for (var i = 0, editablesLength = Aloha.editables.length; i < editablesLength; i++) {
255 				if ( !Aloha.editables[i].ready ) {
256 					Aloha.editables[i].init();
257 				}
258 			}
259 
260 			// Forward
261 			next();
262 		},
263 
264 		/**
265 		 * Activates editable and deactivates all other Editables
266 		 * @param {Editable} editable the Editable to be activated
267 		 * @return void
268 269 		 */
270 		activateEditable: function (editable) {
271 
272 			// blur all editables, which are currently active
273 			for (var i = 0, editablesLength = Aloha.editables.length; i < editablesLength; i++) {
274 				if (Aloha.editables[i] != editable && Aloha.editables[i].isActive) {
275 					Aloha.editables[i].blur();
276 				}
277 			}
278 
279 			Aloha.activeEditable = editable;
280 		},
281 
282 		/**
283 		 * Returns the current Editable
284 		 * @return {Editable} returns the active Editable
285 		 */
286 		getActiveEditable: function() {
287 			return Aloha.activeEditable;
288 		},
289 
290 		/**
291 		 * deactivated the current Editable
292 		 * @return void
293 		 */
294 		deactivateEditable: function () {
295 
296 			if ( typeof Aloha.activeEditable === 'undefined' || Aloha.activeEditable === null ) {
297 				return;
298 			}
299 
300 			// blur the editable
301 			Aloha.activeEditable.blur();
302 			Aloha.activeEditable = null;
303 		},
304 
305 		/**
306 		 * Gets an editable by an ID or null if no Editable with that ID registered.
307 		 * @param {string} id the element id to look for.
308 		 * @return {Aloha.Editable} editable
309 		 */
310 		getEditableById: function (id) {
311 
312 			// if the element is a textarea than route to the editable div
313 			if (jQuery('#'+id).get(0).nodeName.toLowerCase() === 'textarea' ) {
314 				id = id + '-aloha';
315 			}
316 
317 			// serach all editables for id
318 			for (var i = 0, editablesLength = Aloha.editables.length; i < editablesLength; i++) {
319 				if (Aloha.editables[i].getId() == id) {
320 					return Aloha.editables[i];
321 				}
322 			}
323 
324 			return null;
325 		},
326 
327 		/**
328 		 * Checks wheater an object is a registered Aloha Editable.
329 		 * @param {jQuery} obj the jQuery object to be checked.
330 		 * @return {boolean}
331 		 */
332 		isEditable: function (obj) {
333 			for (var i=0, editablesLength = Aloha.editables.length; i < editablesLength; i++) {
334 				if ( Aloha.editables[i].originalObj.get(0) === obj ) {
335 					return true;
336 				}
337 			}
338 			return false;
339 		},
340 
341 		/**
342 		 * Logs a message to the console
343 		 * @param level Level of the log ("error", "warn" or "info", "debug")
344 		 * @param component Component that calls the log
345 		 * @param message log message
346 		 * @return void
347 		 * @hide
348 		 */
349 		log: function(level, component, message) {
350 			if (typeof Aloha.Log !== "undefined")
351 				Aloha.Log.log(level, component, message);
352 		},
353 		
354 		/**
355 		 * Register the given editable
356 		 * @param editable editable to register
357 		 * @return void
358 		 * @hide
359 		 */
360 		registerEditable: function (editable) {
361 			Aloha.editables.push(editable);
362 		},
363 
364 		/**
365 		 * Unregister the given editable. It will be deactivated and removed from editables.
366 		 * @param editable editable to unregister
367 		 * @return void
368 		 * @hide
369 		 */
370 		unregisterEditable: function (editable) {
371 			var id = jQuery.inArray(editable, Aloha.editables);
372 			if (id != -1) {
373 				Aloha.editables.splice(id, 1);
374 			}
375 		},
376 
377 		/**
378 		 * String representation
379 		 * @hide
380 		 */
381 		toString: function () {
382 			return 'Aloha';
383 		},
384 
385 		/**
386 		 * Check whether at least one editable was modified
387 		 * @method
388 		 * @return {boolean} true when at least one editable was modified, false if not
389 		 */
390 		isModified: function () {
391 			// check if something needs top be saved
392 			for (var i = 0; i < Aloha.editables.length; i++) {
393 				if (Aloha.editables[i].isModified && Aloha.editables[i].isModified()) {
394 					return true;
395 				}
396 			}
397 
398 			return false;
399 		},
400 
401 		/**
402 		 * Determines the Aloha Url
403 		 * Uses Aloha.settings.baseUrl if set.
404 		 * @method
405 		 * @return {String} alohaUrl
406 		 */
407 		getAlohaUrl: function( suffix ) {
408 			return Aloha.settings.baseUrl;
409 		},
410 
411 		/**
412 		 * Gets the plugin's url.
413 		 *
414 		 * @method
415 		 * @param {string} name The name with which the plugin was registered
416 		 *                      with.
417 		 * @return {string} The fully qualified url of this plugin.
418 		 */
419 		getPluginUrl: function (name) {
420 			var url;
421 
422 			if (name) {
423 				url = Aloha.settings._pluginBaseUrlByName[name];
424 				if(url) {
425 					//Check if url is absolute and attach base url if it is not
426 					if(!url.match("^(\/|http[s]?:).*")) {
427 						url = Aloha.getAlohaUrl() + '/' + url;
428 					}
429 				}
430 			}
431 			return url;
432 		}
433 
434 	});
435 
436 	return Aloha;
437 });
438