/* * file: DEdit.js * * @BEGINLICENSE * Copyright 2010 Brook Novak (email : brooknovak@seaweed-editor.com) * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * @ENDLICENSE */ /** * @namespace The debug namespace will be removed in release builds. */ debug = {}; /** * Asserts a condition. If a condition fails a alert box shows and an exception is thrown. * * @param {Boolean} cond A condition * * @param {String} msg An optional message * * @throws {Error} if a condition fails */ debug.assert = function(cond, msg) { try { if (!cond) throw new Error("Assertion failed" + (msg ? ": " + msg : "")); } catch (e) { var fullMsg = e.message + (e.stack ? "\nstack:\n" + e.stack : ""); alert(fullMsg); throw e; } } debug.close = function(){ debug.stop = true; if (typeof _debugConsole != "undefined" && _debugConsole) { _debugConsole.parentNode.removeChild(_debugConsole); _debugConsole = null; } } debug.stop = false; /** * Prints a message to a debug console. * * @param {String} msg A message to print. */ debug.print = function(msg){ if (debug.stop) return; if (window.console && console.log) { console.log(msg); } else if (window.opera && window.opera.postError){ window.opera.postError(msg); } else { // Setup debug console if (typeof _debugConsole == "undefined" || !_debugConsole) { _debugConsole = document.createElement("div"); _debugConsole.style.backgroundColor = "#444444"; _debugConsole.style.position = "fixed"; _debugConsole.style.border = "2px solid #000000"; _debugConsole.style.width = "320px"; _debugConsole.style.height = "174px"; _debugConsole.style.zIndex = "9999"; _debugConsole.style.top = "0"; _debugConsole.style.left = "0"; _debugConsole.innerHTML = '
* Enqueue's an intialization function to be invoked during the DEdit API initialization phase (after DOM is ready). *
** If a module (script) needs to be initialized before usage and depends on the document DOM state to be ready - * or should only be initialized when the API is explicitely been asked to be initialized, or initialization code * depends on a public API interface then use this function (at most once per module). *
* NOTE: All internals will be loaded upon execution of the initialization code, therefore there is no need to * delcare dependancies (@DEPENDS or via this method) for usage of internals within initialization code. * * @param {String} moduleName The name of the module (script file name without extension). * * @param {Function} init An optional initialization method. If the initialization code depends on * other modules' public interfaces, then specify the module names as additional arguments to this call. */ function $enqueueInit(moduleName, init){ // @DEBUG ON debug.assert(de.m ? true : false, "Attempted to enqueue initializor function after API has initialized"); for (var i in de.m) { // Integrity check debug.assert(de.m[i].name != moduleName, 'An initializor is already registered under the name "' + moduleName + '"'); } // @DEBUG OFF // Discover dependancies (declared as extra arguments) var dependancies = Array.prototype.slice.call(arguments); dependancies.splice(0, 2); // Store the initializor for the module de.m.push({ name: moduleName, init: init, depends: dependancies }); }; /** * Adds/suppliments all members to a target object from a source object. * If the target object has a member that is also contained in source, it will * be overridden with the source member. * * Leaves the source object in tact. * * @param {Object} target The destination object * * @param {Object} source The source object * * @param {Boolean} override (Optional) True to override existing members on conflicts, * false skip conflicts. Defaults to true * * @return {Object} The target object */ function $extend(target, source, override) { if (override !== false) override = true; for (var mem in source) { if (override || typeof target[mem] == "undefined") target[mem] = source[mem]; } return target; } /** * Create a hash map of booleans from a comma separated set of keys. * @param {String} str A comma separated set of keys. White spaces are not truncated * @return {Object} A lookup map */ function $createLookupMap(str){ var arr = str.split(","); var map = {}; for (var i in arr) { map[arr[i]] = true; } return map; } /** * Shorthand for document.createElement * @param {String} tag The element name * @return {Element} A new element */ function $createElement(tag) { return document.createElement(tag); } // @DEBUG ON // MSHTML Does not provide Node type constants. // Therefore declare them explicitely. This is only needed in the debug version // since the release version replaces them with actual values // NOTE: This may cause other scripts confusion!! If they test for the presence of // the node object and assume it is an actual node class! if (typeof Node == "undefined") { Node = {_DE_DEBUG_CREATED : true}; } if (typeof Node.ELEMENT_NODE == "undefined") { $extend(Node, { // @REPLACE Node.ELEMENT_NODE 1 ELEMENT_NODE : 1, // @REPLACE Node.ATTRIBUTE_NODE 2 ATTRIBUTE_NODE : 2, // @REPLACE Node.TEXT_NODE 3 TEXT_NODE : 3, // @REPLACE Node.CDATA_SECTION_NODE 4 CDATA_SECTION_NODE : 4, // @REPLACE Node.ENTITY_REFERENCE_NODE 5 ENTITY_REFERENCE_NODE : 5, // @REPLACE Node.ENTITY_NODE 6 ENTITY_NODE : 6, // @REPLACE Node.PROCESSING_INSTRUCTION_NODE 7 PROCESSING_INSTRUCTION_NODE : 7, // @REPLACE Node.COMMENT_NODE 8 COMMENT_NODE : 8, // @REPLACE Node.DOCUMENT_NODE 9 DOCUMENT_NODE : 9, // @REPLACE Node.DOCUMENT_TYPE_NODE 10 DOCUMENT_TYPE_NODE : 10, // @REPLACE Node.DOCUMENT_FRAGMENT_NODE 11 DOCUMENT_FRAGMENT_NODE : 11, // @REPLACE Node.NOTATION_NODE 12 NOTATION_NODE : 12 }); } // @DEBUG OFF /* * This Bootloader was auto-generated on 27/02/2010 14:18:11 * @author Brook Novak Copyright 2010 Brook Novak (email : brooknovak@seaweed-editor.com) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ (function() { var baseScripts=["collections/DoublyLinkedList.js","MVC.js","Platform.js","UndoMan.js","Util.js"]; var dependantScripts=["Changes.js","Clipboard.js","ContainerNormalization.js","Cursor.js","Doc.js","Error.js","events/Events.js","events/Mouse.js","FormatEnvironment.js","Fragment.js","OperationManager.js","events/Keyboard.js","Selection.js","Spell.js","Typing.js","actions/TextAlignAction.js","actions/SplitContainerAction.js","actions/RemoveTextAction.js","actions/RemoveDOMAction.js","actions/PromoteItemAction.js","actions/ModifyTableAction.js","actions/ItemizeAction.js","actions/InsertTextAction.js","actions/InsertHTMLAction.js","actions/IndentAction.js","actions/FormatAction.js","actions/DemoteItemAction.js","actions/CreateTableAction.js","actions/ChangeContainerAction.js","actions/BlockQuoteAction.js","DTDUtil.js","Viewport.js","WhitespaceUtil.js"]; var thisFilename="DEdit.js"; /* * file: Bootstrapper.js * * @BEGINLICENSE * Copyright 2010, Brook Jesse Novak, All rights reserved * @ENDLICENSE */ /********************************************************************************************************************** * @author Brook Novak * * Assumes: * - Core.js is prepended(or loaded). * - An array named "baseScripts" exists with all relative paths of scripts to load first in the given order. * - An array named "dependantScripts" exists with all relative paths of scripts to load after the base scripts. * - A string named "thisFilename" exists, set to the filename of this file, which is contained in the libraries TDL. * - That this script is encapsulated in an anonymous function (To avoid polluting global scope) **********************************************************************************************************************/ // Mimic the addHandler method in the events module to make available before the events module script is even available var eventHandlers = []; de.events.addHandler = function(eventSource, eventName, handler) { // will be overridden eventHandlers.push(arguments); } // Override the onready function (declared in Core)- so that all callbacks are invoked once // the window.onload occurs AND all scripts are loaded var onReadyCallbacks = [], origReady = de.onready; de.onready = function(handler) { onReadyCallbacks.push(handler); } /** * @namespace * The bootstrap namespace. */ bootstrap = { /** * A list of all laoded module names * @type [String] */ loadedModules : [], /** * For all scripts in the API you must invoke this function to register the script when the script is first executed. * * @param {String} name The name of module that is loaded. * The Module name is the relative path without the file extension (.js), * and directory separators are replaced with period-symbols. */ provides : function(name) { // debug.println("Loaded: " + name); this.loadedModules.push(name); // First Phase: base-script loading if (baseScripts.length > 0) { // A base script is loaded - remove it baseScripts.shift(); if (baseScripts.length > 0) { // More base scripts to load // Load the next base script loadScript(baseURL + baseScripts[0]); } else { // Finished download base scripts // Pull in remaining API source files asynchronously for (var i in dependantScripts) { loadScript(baseURL + dependantScripts[i]); } } } else { // Second phase: dependant-script loading // A dependant script is loaded. // Get relative path for registered module var registeredPath = name.replace(/\./g,"/").toLowerCase() + ".js"; // Remove include path for the registered module for (var i = 0; i < dependantScripts.length; i++) { if (dependantScripts[i].toLowerCase() == registeredPath) { dependantScripts.splice(i, 1); break; } } if (dependantScripts.length == 0) { // All scripts loaded? // Schedule finishing-up code on another event to let the last script load setTimeout(function() { // Add all registered events... for (var i in eventHandlers) { var args = eventHandlers[i]; var eventSource = (args.length > 0) ? args[0] : null, eventName = (args.length > 1) ? args[1] : null, handler = (args.length > 2) ? args[2] : null; _addHandler(eventSource, eventName, handler); } // Add all on-ready funcs for (var i in onReadyCallbacks) { origReady(onReadyCallbacks[i]); // Fires instantly is onload already occured } de.onready = origReady; }, 1); } } } }; // Determine the base URL of the library. var baseURL; var libcoreRegExp = new RegExp("(^|[\\/\\\\])" + thisFilename.replace(/\./g,"\\.") + "(\\?|$)"); var scriptElements = document.getElementsByTagName("script"); for (var i in scriptElements) { var src = scriptElements[i].src; if (src && src.match(libcoreRegExp)) { baseURL = src; i = src.lastIndexOf("/"); if (i == -1) i = src.lastIndexOf("\\"); baseURL = (i == -1) ? "" : src.substring(0, i + 1); break; } } if (!baseURL) throw new Error("Unable to import library: could not discover DEdit libhome"); // Pull in API base source files first, once this is done the rest of the api source will be pulled in loadScript(baseURL + baseScripts[0]); function loadScript(scriptSrc){ // gets document head element var docHead = document.getElementsByTagName('head')[0]; if (docHead) { // creates a new script tag var scriptEl = document.createElement('script'); // adds src and type attribute to script tag scriptEl.setAttribute('src', scriptSrc); scriptEl.setAttribute('type', 'text/javascript'); // append the script tag to document head element docHead.appendChild(scriptEl); } } })();