mozdev.org

Mozile (xhtml editing in your browser)    

resources:
Overview

interface.js

Summary

This extends "core.js" to include interface elements such as a toolbar, several popup dialogs, as well as configurable commands.

Version: 0.7

Author: James A. Overton


Class Summary
MozileCommand  
MozileCommandList  
MozileCommandSeparator  
MozileInterface  
MozileToolbar  

/* ***** BEGIN LICENSE BLOCK *****
 * Licensed under Version: MPL 1.1/GPL 2.0/LGPL 2.1
 * Full Terms at http://mozile.mozdev.org/license2.html
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is James A. Overton's code (james@overton.ca).
 *
 * The Initial Developer of the Original Code is James A. Overton.
 * Portions created by the Initial Developer are Copyright (C) 2005-2006
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *	James A. Overton <james@overton.ca>
 *
 * ***** END LICENSE BLOCK ***** */
 
/**  
 * @fileoverview This extends "core.js" to include interface elements such as a toolbar, several popup dialogs, as well as configurable commands.
 * @link http://mozile.mozdev.org 
 * @author James A. Overton <james@overton.ca>
 * @version 0.7
 */



/** 
 * An associative array containing entries for every save method available, the default method, and the user's custom method. This is a key-value array, where the key is the method name and the value is an array. All the value-arrays include the keys: value, label, function. 
 * @type Object
 */
MozileMediator.prototype.getSaveModules = function() {
 	if(!this._saveModules) {
 		this._saveModules = new Object();

			// Define the built in dialog save method.
		var dialog = new MozileModule("Dialog");
		dialog.setOption("label", "Save to Dialog");
		dialog.save = function() {
			mozile.getSourceInterface().show();
		}
		this.addSaveModule(dialog);
		this.setDefaultSaveModule(dialog);
		this.setSaveOption("default", "content", mozile.getOption("content"));
		this.setSaveOption("default", "format", mozile.getMode());
 	}
 	return this._saveModules;
}

/** 
 * Gets a module from the list by its name.
 * @param {String} name
 * @type MozileModule
 */
MozileMediator.prototype.getSaveModule = function(name) {
 	if(this.getSaveModules()[name]) return this.getSaveModules()[name];
 	else return undefined;
}

/** 
 * Gets a save option. First checks for the value in the given mode's array, then tries to set a defaultValue, then searches the mode's module's options, and finally returns mozile.getOption(key).
 * @param {String} mode Can be "default" or "custom" or "current". "Current searches "custom" first and "default" second, and then assigns any values to "custom".
 * @param {String} key 
 * @param defaultValue If there is no matching key for the given mode, the defaultValue will be assigned to that key.
 * @return The value if found or the defaultValue if given. Otherwise undefined.
 */
MozileMediator.prototype.getSaveOption = function(mode, key, defaultValue) {
	if(!this._saveOptions) this._saveOptions = new Object();
	if(mode == "default" || mode == "custom") {
		if(!this._saveOptions[mode]) this._saveOptions[mode] = new Object();
		if(this._saveOptions[mode][key] != undefined) return this._saveOptions[mode][key];
		else if (defaultValue != undefined)	return this.setSaveOption(mode, key,  defaultValue);
		else if (this._saveOptions[mode]["module"] && 
				this._saveOptions[mode]["module"].getOption(key) != undefined) 
					return this._saveOptions[mode]["module"].getOption(key);
		else return this.getOption(key);
	}
	else if (mode == "current") {
		if(this.getSaveOption("custom", key) != undefined) return this.getSaveOption("custom", key);
		else if(this.getSaveOption("default", key) != undefined) return this.getSaveOption("default", key);
		else if (defaultValue != undefined)	return this.setSaveOption("custom", key,  defaultValue);
		else return undefined;
	}
	else throw Error("Invalid save mode");
}

/** 
 * Sets a module from the list by its name.
 * @param {String} mode Can be "default" or "custom" or "current".
 * @param {String} key 
 * @param value The value to be assigned.
 * @return The value given.
 */
MozileMediator.prototype.setSaveOption = function(mode, key, value) {
	if(!this._saveOptions) this._saveOptions = new Object();
	if(mode == "default" || mode == "custom") {
		if(!this._saveOptions[mode]) this._saveOptions[mode] = new Object();
		this._saveOptions[mode][key] = value;
		return value;
	}
	else if (mode == "current") {
		if(this._saveOptions["custom"]) return this.setSaveOption("custom", key, value);
		else return this.setSaveOption("default", key, value);
	}
	else throw Error("Invalid save mode");
}

/** 
 * Sets the default save module.
 * @param {MozileModule} module
 * @type Void
 */
MozileMediator.prototype.useDefaultSaveOptions = function() {
	if(this._saveOptions["custom"]) this._saveOptions["custom"] = null;
}

/** 
 * Sets the default save module.
 * @param {MozileModule} module
 * @type MozileModule
 */
MozileMediator.prototype.setDefaultSaveModule = function(module) {
	this.setSaveOption("default", "module", module);
	return module;
}

/** 
 * Sets the custom save module.
 * @param {MozileModule} module
 * @type MozileModule
 */
MozileMediator.prototype.setCustomSaveModule = function(module) {
	this.setSaveOption("custom", "module", module);
	return module;
}

/** 
 * Adds a module to the modules list.
 * @param {MozileModule} module
 * @type MozileModule
 * @return The module object given.
 */
MozileMediator.prototype.addSaveModule = function(module) {
	if(module.getName()) this.getSaveModules()[module.getName()] = module;
	else throw Error("Invalid module.");
	return module;
}

/** 
 * An associative array containing all of the commands (but not the command lists) registered with this Mozile object. The keys are the id strings the commands, and values the command objects.
 * @type Object
 */
MozileMediator.prototype.getCommands = function() {
 	if(!this._commands) this._commands = new Object();
 	return this._commands;
}

/** 
 * Gets a command from the list by its id.
 * @param {String} id
 * @type MozileCommand
 */
MozileMediator.prototype.getCommand = function(id) {
 	if(this.getCommands()[id]) return this.getCommands()[id];
 	else return undefined;
}

/** 
 * Adds a command to the commands list.
 * @param {MozileCommand} command
 * @type MozileCommand
 * @return The command object given.
 */
MozileMediator.prototype.addCommand = function(command) {
	if(command.getId()) this.getCommands()[command.getId()] = command;
	else throw Error("Invalid command.");
	return command;
}

/** 
 * An array containing all of the keyboard shortcuts (accelerators) for Mozile commands. The keys are strings of the format "Control-Shift-F", while the values are the command objects.
 * @type Object
 */
MozileMediator.prototype.getAccelerators = function() {
 	if(!this._accelerators) this._accelerators = new Object();
 	return this._accelerators;
}

/** 
 * Gets a command from the list by its accelerator string.
 * @param {String} accel
 * @type MozileCommand
 */
MozileMediator.prototype.getAccelerator = function(accel) {
 	if(this.getAccelerators()[accel]) return this.getAccelerators()[accel];
 	else return undefined;
}

/** 
 * Adds an accelerator string and a command to the accelerator list.
 * @param {String} accel The accelerator string.
 * @param {MozileCommand} command
 * @type MozileCommand
 * @return The command object given.
 */
MozileMediator.prototype.addAccelerator = function(accel, command) {
	this.getAccelerators()[accel] = command;
	return command;
}




/** 
 * Gets Mozile's "About" interface box element. This interface describes Mozile. The interface is created if necessary.
 * @type MozileInterface
 */
MozileMediator.prototype.getAboutInterface = function() {
	if(!this._aboutInterface) {
		this._aboutInterface = new MozileInterface(this.getRoot()+"core/about.xml", "MozileAboutInterface: width=450px");
		this._aboutInterface.init = function() {
			document.getElementById("mozileVersion").value = mozile.getVersion();
		}
	}	
	return this._aboutInterface;
}

/** 
 * Gets Mozile's "Save As" interface box element. The interface is created if necessary.
 * @type MozileInterface
 */
MozileMediator.prototype.getSaveInterface = function() {
	if(!this._saveInterface) {
			// Save Interface
		this._saveInterface = new MozileInterface(this.getRoot()+"core/save.xml", "MozileSaveInterface: width=330px");
		
		
		/**** Define Save Interface Methods ****/

		/** Mozile Save Init -
		 * Initialize the Save interface. First, find the elements for the global variables, and then set them up.
		 * 
		 * @return Always true.
		 */	
		this._saveInterface.init = function() {
			this.savePreset = document.getElementById("mozileSavePresetList");
			this.saveContent = document.getElementById("mozileSaveContentList");
			this.saveFormat = document.getElementById("mozileSaveFormatList");
			this.saveMethod = document.getElementById("mozileSaveMethodList");
			
				// Clear save methods
			while(this.saveMethod.length) {
				this.saveMethod.removeChild(this.saveMethod.firstChild);
			}
			
			// Generate save method options
			var option;
			for(key in mozile.getSaveModules()) {
				option = document.createElement("option");
				option.setAttribute("value", mozile.getSaveModule(key).getName());
				option.appendChild(document.createTextNode(mozile.getSaveModule(key).getOption("label")));
				this.saveMethod.appendChild(option);
			}
			
			this.restore("current");
		}
		
		/** Mozile Method Fields -
		 * Show and hide various fields. Right now we only have one: mozileSaveURLBox.
		 * 
		 * @return Always true.
		 */	
		this._saveInterface.methodFields = function() {
			var urlBox = document.getElementById("mozileSaveURLBox");
			var url = document.getElementById("mozileSaveToURL");
			if(mozile.getSaveModule(this.saveMethod.value).getOption("showURL")) {
				urlBox.collapsed = false;
				if(url.value == "" || url.value == "undefined") url.value = mozile.getSaveModule(this.saveMethod.value).getOption("url");
			}
			else urlBox.collapsed = true;
		}
		
		/** Mozile Restore Default -
		 * Restore the page default settings, if they exist
		 * 
		 * @return Always true.
		 */	
		this._saveInterface.restore = function(mode) {
			if(mode == undefined) mode = this.savePreset.value;
			try {
				this.saveMethod.value = mozile.getSaveOption(mode, "module").getName();
				this.saveContent.value = mozile.getSaveOption(mode, "content");
				this.saveFormat.value = mozile.getSaveOption(mode, "format");
				document.getElementById("mozileSaveToURL").value = mozile.getSaveOption(mode, "url");
			}
			catch(e) {
				// fail silently
			}
			this.methodFields();
		}
		
		/** Mozile Save Changes -
		 * If there have been changes, set the "preset" menu to "custom" and store the changes.
		 * 
		 * @return Always true.
		 */	
		this._saveInterface.changed = function() {
			this.methodFields();
			this.storeCustom();
			this.savePreset.value = "custom";
		}
		
		/** Mozile Save Changes -
		 * When the "save" button is pressed, collect all the values that have been set,  and call Mozile.save().
		 * 
		 * @return Always true.
		 */	
		this._saveInterface.done = function() {
			if(this.savePreset.value == "default") {
				mozile.useDefaultSaveOptions();
			}
			else {
				this.storeCustom();
			}
			this.hide();
				// Tell the save module to prompt for more information (if possible).
			mozile.setSaveOption("current", "prompt", true);
			mozile.getSaveOption("current", "module").save();
			mozile.changesSaved = true;
		}
		
		/** Mozile Store Custom -
		 * Store the custom values of all the menus and fields.
		 * 
		 * @return Always true.
		 */	
		this._saveInterface.storeCustom = function() {
			mozile.setCustomSaveModule(mozile.getSaveModule(this.saveMethod.value));
			mozile.setSaveOption("custom", "content", this.saveContent.value);
			mozile.setSaveOption("custom", "format", this.saveFormat.value);
			if(mozile.getSaveModule(this.saveMethod.value).getOption("showURL")) {
				mozile.setSaveOption("custom", "url", document.getElementById("mozileSaveToURL").value);
			}
		}

	}	
	return this._saveInterface;
}

/** 
 * Gets Mozile's "Source" interface box element. This interface displays the source code for the document when the "Display" save method is used. The interface is created if necessary.
 * @type MozileInterface
 */
MozileMediator.prototype.getSourceInterface = function() {
	if(!this._sourceInterface) {
		this._sourceInterface = new MozileInterface(this.getRoot()+"core/source.xml", "MozileSourceInterface: width=80%");
		this._sourceInterface.init = function() {
			document.getElementById("mozileSourceContent").value = mozile.getSaveOption("current", "content");
			document.getElementById("mozileSourceFormat").value = mozile.getSaveOption("current", "format");
			document.getElementById("mozileSourceText").value = mozile.content();
		}
		this._sourceInterface.refresh = function() {
			var content = document.getElementById("mozileSourceContent").value;
			var format = document.getElementById("mozileSourceFormat").value;
			if(format == "XHTML") format = "XML";
			var text = eval("mozile."+ content +"To"+ format +"()");
			if(text) document.getElementById("mozileSourceText").value = text;
		}
	}	
	return this._sourceInterface;
}

/** 
 * Gets Mozile's "Message" interface box element. This interface shows the status and debugging messages that Mozile has collected. The interface is created if necessary.
 * @type MozileInterface
 */
MozileMediator.prototype.getMessageInterface = function() {
	if(!this._messageInterface) {
		this._messageInterface = new MozileInterface(this.getRoot()+"core/message.xml", "MozileMessageInterface: width=80%");
		this._messageInterface.init = function() {
			document.getElementById("mozileVersion").value = mozile.getVersion();
		}
		

/**** Debug Interface Configuration ****/

		/** Mozile Debug Init -
		 * Initializes the debugging dialog.
		 *
		 * @param event The event object which triggers the initialization.
		 * @return Always true.
		 */
		this._messageInterface.init = function() {
			this.reset();
		}
			
		/** Mozile Debug Reset -
		 * Clears the filter and rebuilds the bug list.
		 *
		 * @param event The event object which triggers the initialization.
		 * @return Always true.
		 */
		this._messageInterface.reset = function() {
			document.getElementById("mozileFilterText").value = "";
			document.getElementById("mozileFilterLevel").selectedIndex=0;
			this.filter();
		}
			
		/** Mozile Debug Clear -
		 * Clears the list and empties the mozileDebugArray.
		 *
		 * @param event The event object which triggers the initialization.
		 * @return Always true.
		 */
		this._messageInterface.clear = function() {
			mozileDebugList = new Array();
			this.reset();
		}
			
		/** Mozile Debug Filter -
		 * Rebuilds the bug list, filtering based on the content of the filterText input field.
		 *
		 * @return Always true.
		 */
		this._messageInterface.filter = function() {
			
			var selected = document.getElementById("mozileFilterLevel").value;
			var text = document.getElementById("mozileFilterText").value;
			
			//var mozileDebugList = mozileDebugList;
			var vbox = document.getElementById("mozileMessageBox");
			while(vbox.childNodes.length) {
				vbox.removeChild(vbox.firstChild);
			}
			var count = 0;	
			
			// Loop over all the bug entries
			for(var i=0; i < mozileDebugList.length; i++) {
				var bug = mozileDebugList[i];
					// If the selected value is "status", and this entry is not a "Status Message", then ignore it.
				if(selected == "status" && !bug[1]["Status Message"] ) continue;
					// if the selected level is lower, ignore this entry
				if(selected > bug[2]) continue;			
				
				var pattern = new RegExp(text, "i"); // case insensitive 
				var search = pattern.test(bug[0]) && pattern.test(bug[1]["File"]) && pattern.test(bug[1]["Function"]) && pattern.test(bug[3]);
				if(pattern.test(bug[0]) || pattern.test(bug[1]["File"]) || pattern.test(bug[1]["Function"]) || pattern.test(bug[3])) {
					count++;	
					vbox.appendChild(this.entry(mozileDebugList[i]));
				}
			}
			
			document.getElementById("mozileMessageCount").value="Showing "+count+" of "+mozileDebugList.length+" Messages";
		}
			
		/** Mozile Debug Entry -
		 * Create an entry for the debugging item, which consists of an hbox filled with description elements.
		 *
		 * @param bug The array for this bug entry.
		 * @return The empty node.
		 */
		this._messageInterface.entry = function(bug) {
			var hbox = document.createElementNS(XULNS, "hbox");
			hbox.setAttribute("class", "level"+bug[2]);
			hbox.setAttribute("align", "center");
			
			var datestamp = document.createElementNS(XULNS, "description");
			datestamp.setAttribute("class","datestamp");
			datestamp.setAttribute("value", bug[0]);
			hbox.appendChild(datestamp);
			
			var button = document.createElementNS(XULNS, "button");
			button.setAttribute("class","functionButton");
			button.setAttribute("type", "menu");
			button.setAttribute("image", mozile.getRoot()+"images/info.png");
			
			var menupopup = document.createElementNS(XULNS, "menupopup");
			var functions;
			for(key in bug[1]) {
				functions = document.createElementNS(XULNS, "description");
				functions.setAttribute("class","functions");
				functions.appendChild(document.createTextNode(key +" = "+ bug[1][key]));
				menupopup.appendChild(functions);
			}
			functions = document.createElementNS(XULNS, "description");
			functions.setAttribute("class","functions");
			functions.appendChild(document.createTextNode("Level = "+ bug[2]));
			menupopup.appendChild(functions);
			
			button.appendChild(menupopup);
			hbox.appendChild(button);
			
			var message = document.createElementNS(XULNS, "description");
			message.setAttribute("class","message");
			message.appendChild(document.createTextNode(bug[3]));
			hbox.appendChild(message);
			return hbox;
		}

	}	
	return this._messageInterface;
}





/**
 * Returns the root command list for the Mozile toolbar. Creates it if necessary.
 * @type MozileCommandList
 * @return The root command list for the toolbar.
 */
MozileMediator.prototype.getCommandList = function() {
	if(!this._commandList) {
		
		// Create base command list object, and populate it.
		this._commandList = new MozileCommandList("MozileCommandList: id=Mozile-RootList, label='Mozile Root List'");
		
		// Create the basic Mozile command list.
		var mozileList = this._commandList.createCommand("MozileCommandList: id=Mozile-firstList, label='Mozile First List', image='"+this.getRoot()+"images/Mozile-20.png', buttonPosition=0, menuPosition=0");
		
	
		var about = mozileList.createCommand("MozileCommand: id=Mozile-About, label='About Mozile', undoable=false");
		about.execute = function(event) {
			mozile.getAboutInterface().show();
		}
		
			// Accelerator List (Keyboard Shortcuts)
		var accel = mozileList.createCommand("MozileCommand: id=Mozile-Accelerators, label='Keyboard Shortcuts', undoable=false");
		accel.execute = function(event) {
			if(mozile.getOption("keyboardShortcuts")) {
				var message = "Mozile defines the following keyboard shortcuts:";
				var accels = mozile.getAccelerators();
				for(key in accels) {
					message = message +"\n"+ mozile.getAccelerator(key).getOption("label") +" => "+key;
				}
				alert(message);
			} 
			else {
				alert("Mozile keyboard shortcuts have been turned off.");
			}
		}
	
		var debug = mozileList.createCommand("MozileCommand: id=Mozile-Debug, label=Debug, undoable=false");
		debug.execute = function(event) {
			mozile.getMessageInterface().show();
		}
		
		var report = mozileList.createCommand("MozileCommand: id=Mozile-ReportBugs, label='Report a Bug', undoable=false");
		report.execute = function(event) {
			window.open("http://mozile.mozdev.org/bugs.html", "Mozile Bugs", "");
		}
		
		var home = mozileList.createCommand("MozileCommand: id=Mozile-Home, label='Mozile Home', undoable=false");
		home.execute = function(event) {
			window.open("http://mozile.mozdev.org", "Mozile Home", "");
		}
		
		var help = mozileList.createCommand("MozileCommand: id=Mozile-Help, label='Help', undoable=false");
		help.execute = function(event) {
			if(mozile.getRoot() == "chrome://mozile/content/") {
				if(mozile.isEnhanced()) mozile.setSharedData("clientRequest", "showHelp");
				else window.open("http://mozile.mozdev.org/0.7/docs/index.html", "Mozile Help", "");
			}
			else window.open(mozile.getRoot()+"docs/index.html", "Mozile Help", "");
		}
		
		var save = this._commandList.createCommand("MozileCommand: id=Mozile-Save, label=Save, tooltip='Save to a dialog', accelerator='Command-S', image='"+this.getRoot()+"images/filesave.png', undoable=false");
		save.execute = function(event) {
			mozile.save();
		}
	
		var saveAs = this._commandList.createCommand("MozileCommand: id=Mozile-SaveAs, label='Save As', tooltip='Save as...', accelerator='Command-Shift-S', image='"+this.getRoot()+"images/filesaveas.png', undoable=false");
		saveAs.execute = function(event) {
			mozile.saveAs();
		}

		this._commandList.createCommand("MozileCommandSeparator: id=Mozile-RootSeparator");
	}
	return this._commandList;
}


/** 
 * Creates a new MozileToolbar interface for the toolbar.
 * @type Element
 */
MozileMediator.prototype.getToolbar = function() {
	if(this.isExtension()) return null;
	if(!this._toolbar) {
		var element = document.createElementNS(XULNS, "hbox");
		element.setAttribute("id", "MozileToolbar");
		element.setAttribute("oncommand", "try { var command = event.originalTarget.getAttribute('oncommand'); if(!command || command=='') { var id = event.originalTarget.getAttribute('id'); mozile.executeCommand(id, event); } eval(command); } catch(e) { }");
		this._toolbar = new MozileToolbar(element, "MozileToolbar: id=MozileToolbar, position=topOfWindow");
		this._toolbar.init = function() {
			if(this.getElement().childNodes.length == 0) {
				this.getElement().appendChild(mozile.getCommandList().getBox());
			}
			if(mozile.getCommandList().updateBox()) {
				this.getElement().removeChild(this.getElement().firstChild);
				this.getElement().appendChild(mozile.getCommandList().getBox());
			}
		};
	}
	return this._toolbar;
}


/** 
 * Creates a new MozileToolbar interface for the statusbar.
 * @type Void
 */
MozileMediator.prototype.getStatusbar = function() {
	if(this.isExtension()) return null;
	if(!this._statusbar) {
		this._statusbar = new MozileToolbar(this.getRoot()+"core/status.xml", "MozileStatusbar: id=MozileStatusbar, position=bottomOfWindow");
	}
	return this._statusbar;
}

/** 
 * Hides the Mozile toolbar and statusbar.
 * @type Void
 */
MozileMediator.prototype.hideToolbars = function() {
	if(this.getToolbar()) this.getToolbar().hide();
	if(this.getStatusbar()) this.getStatusbar().hide();
	if(this.getToolbar() && this.getToolbar()._interval) {
		window.clearInterval(this.getToolbar()._interval);
		this.getToolbar()._interval = undefined;
	}
}

/** 
 * Shows (unhides) the Mozile toolbar. If this is the first time that the toolbar has been shown, then it does some initialization.
 * @type Void
 */
MozileMediator.prototype.showToolbars = function() {
	if(this.getToolbar()) this.getToolbar().show();
	if(this.getStatusbar()) this.getStatusbar().show();
	if(this.getToolbar() && !this.getToolbar()._interval) {
		this.getToolbar()._interval = window.setInterval("mozile.repositionToolbars()", mozile.getOption("defaultInterval"));
	}
}

/** 
 * Moves the toolbar and status bar.
 * @type Void
 */
MozileMediator.prototype.repositionToolbars = function() {
	if(this.getToolbar()) this.getToolbar().reposition();
	if(this.getStatusbar()) this.getStatusbar().reposition();
}

/**
 * Updates all of the commands in the commandList so that they will reflect the current selection. Unless forced, will only update if the node has changed.
 * @param {Boolean} forceUpdate. Optional.
 * @type Void
 */
MozileMediator.prototype.updateToolbars = function(forceUpdate) {
	var focusNode = window.getSelection().focusNode;
	if(this.getToolbar()) {
		if(forceUpdate) this.getCommandList().update();
		if(focusNode && focusNode != this._lastFocusNode) this.getCommandList().update();
	}
	this._lastFocusNode = focusNode;
}



/** Mozile - Save -
 * This function sets the Mozile.saveConfig property and calls the appropriate save function from Mozile Save List: either "default" or "custom". If neither exists, then it opens the Save As dialog.
 * 
 * @return Always true.
 */
MozileMediator.prototype.save = function() {
	this.setSaveOption("current", "prompt", false);
	this.getSaveOption("current", "module").save();
	this.changesSaved = true;
}


/** Mozile - Save As -
 * Opens Mozile's Save As dialog.
 * 
 * @return Always true.
 */
MozileMediator.prototype.saveAs = function() {
	mozile.getSaveInterface().show();
}




/** Mozile - Execute Command -
 * Calls the command() method of the command object corresponding to the given id.
 * 
 * @param id The id of the node which triggered the command. 
 * @param event The event which triggered this command. 
 * @return Always true.
 */
MozileMediator.prototype.executeCommand = function(id, event) {
	var f = new Array();
	f["File"] = "core/interface.js";
	f["Function"] = "Mozile.executeCommand()";
	this.debug(f,1,"Executing command "+ id +" "+ event);
	// Remove the "-Button" or "-Menuitem" part of the id, if there is one.
	var cleanId = /(.*)(\-Button|\-Menuitem)$/;
	var result = cleanId.exec(id);
	//alert(result);
	var commandId;
	if(result) commandId = result[1];
	else commandId = id;
	if(!this.getCommand(commandId)) return false;
	// If the command id is registered, call the command method of the corresponding command object.
	else {
		var command = this.getCommand(commandId);
		
		// If the keyCounter is not 0, then something has changed since the last command, so store the state.
		if(this.keyCounter != 0) this.storeState(command);
		
		// Execute the command
		result = command.execute(event);
		
		// If there is some result, and this is not an undo or redo command, store the state after the change.
		if(result && command.isUndoable()) this.storeState(command);
		this.updateToolbars(true);
		return true;
	}
}










/****  Mozile Command Object ****/
/** Mozile Command Object -
 * Creates a Mozile command object, which controls the button, menuitem, and code associated with a Mozile editing command.
 * <p>Configuration String format (particular command objects may have other options): "MozileCommandObject: id=CommandId, label='Command Label', tooltip='Command Tool Tip', image='/path/to/image.file', accesskey=C, accelerator='Command-C', undoable=true, buttonPosition=0, menuPosition=0, debugLevel=0"
 * <p>Accelerator format must follow this sequence: "Command-Meta-Control-Alt-Shift-Key". Mozile will check the UserAgent string for the browser, and replace "Command" with "Control" on Linux and Windows, or "Meta" on Macintosh. One of "Command", "Control" or "Meta" must be present, and "Key" is a single uppercase character.
 * @constructor
 * @param {String} configString A properly formatted configuration string.
 */
function MozileCommand(configString) {

	/**
	 * @private
	 * @type String
	 */
	this._configString = String(configString);

}

MozileCommand.prototype = new MozileComponent;
MozileCommand.prototype.constructor = MozileCommand;

/**
 * Gets the id for the module. Throws an error if none exists.
 * @type String
 */
MozileCommand.prototype.getId = function() {
	if(!this.getOption("id")) throw Error("Invalid configuration string.");
	return this.getOption("id");
}

/**
 * True if the command can be undone.
 * @type Boolean
 */
MozileCommand.prototype.isUndoable = function() {
	return this.getOption("undoable", true);
}

/**
 * @type XULElement
 */
MozileCommand.prototype.getButton = function() {
	if(!this._button) this._createButton();
	return this._button;
}

/**
 * @type XULElement
 */
MozileCommand.prototype.getMenuitem = function() {
	if(!this._menuitem) this._createMenuitem();
	return this._menuitem;
}

/**
 * Checks to see if the command is available in the current selection.
 * @type Boolean
 */
MozileCommand.prototype.isAvailable = function() {
	return true;
}

/**
 * Checks to see if the command is active in the current selection.
 * @type Boolean
 */
MozileCommand.prototype.isActive = function() {
	return false;
}

/**
 * Shows the button and menuitem.
 * @type Void
 */
MozileCommand.prototype.show = function() {
	if(mozile.getOption("hideInactiveCommands")) {
		if(this._button) this._button.setAttribute("collapsed", "false");
		if(this._menuitem) this._menuitem.setAttribute("collapsed", "false");
	}
	else {
		if(this._button) this._button.setAttribute("disabled", "false");
		if(this._menuitem) this._menuitem.setAttribute("disabled", "false");
	}
}

/**
 * Hides the button and menuitem.
 * @type Void
 */
MozileCommand.prototype.hide = function() {
	if(mozile.getOption("hideInactiveCommands")) {
		if(this._button) this._button.setAttribute("collapsed", "true");
		if(this._menuitem) this._menuitem.setAttribute("collapsed", "true");
	}
	else {
		if(this._button) this._button.setAttribute("disabled", "true");
		if(this._menuitem) this._menuitem.setAttribute("disabled", "true");
	}
}

/**
 * Updates the button and menuitem.
 * @type Void
 */
MozileCommand.prototype.update = function() {
	if(!this.isAvailable()) {
		this.hide();
		return;
	}
	this.show();

	var active = this.isActive();
	this.getButton().setAttribute("active", active);
	this.getMenuitem().setAttribute("checked", active);
}

/**
 * Executes the command.
 * @param {Event} event The event object which triggered the command.
 * @type Void
 */
MozileCommand.prototype.execute = function(event) {
	alert("Command "+ this.getId() +" executed by event "+ event);
}


/** 
 * Creates an XUL button element for this command.
 * @private
 * @type XULElement
 */
MozileCommand.prototype._createButton = function() {
	this._button = document.createElementNS(XULNS, "toolbarbutton");
	this._button.setAttribute("id", this.getId() +"-Button");
	this._button.setAttribute("class", "mozileButton");
	this._button.setAttribute("image", this.getOption("image"));
	this._button.setAttribute("label", this.getOption("label"));
	if(this.getOption("tooltip")) this._button.setAttribute("tooltiptext", this.getOption("tooltip"));
	return this._button;
}

/** 
 * Creates an XUL menuitem element for this command.
 * @private
 * @type XULElement
 */
MozileCommand.prototype._createMenuitem = function() {
	this._menuitem = document.createElementNS(XULNS, "menuitem");
	this._menuitem.setAttribute("id", this.getId() +"-Menuitem");
	this._menuitem.setAttribute("class", "mozileMenuitem");
	//this._menuitem.setAttribute("type", "checkbox");
	this._menuitem.setAttribute("label", this.getOption("label"));
	if(this.getOption("tooltip")) this._menuitem.setAttribute("tooltiptext", this.getOption("tooltip"));
	if(this.getOption("accesskey")) this._menuitem.setAttribute("accesskey", this.getOption("accesskey"));
	return this._menuitem;
}



/** 
 * A very simple command which does nothing except get displayed as a toolbarseparator or menuseparator.
 * @param {String} configString A properly formatted configuration string.
 */
function MozileCommandSeparator(configString) {

	/**
	 * @private
	 * @type String
	 */
	this._configString = String(configString);

}

MozileCommandSeparator.prototype = new MozileCommand();
MozileCommandSeparator.prototype.constructor = MozileCommandSeparator;


/**
 * True if the command can be undone.
 * @type Boolean
 */
MozileCommandSeparator.prototype.isUndoable = function() {
	return false;
}

/**
 * Overrides parent class and does nothing.
 * @type Void
 */
MozileCommandSeparator.prototype.update = function() { }

/** 
 * Creates an XUL separator element for this command.
 * @private
 * @type XULElement
 */
MozileCommandSeparator.prototype._createButton = function() {
	this._button = document.createElementNS(XULNS, "separator");
	this._button.setAttribute("id", this.getId() +"-Separator");
	this._button.setAttribute("class", "mozileSeparator");
	return this._button;
}

/** 
 * Creates an XUL menuseparator element for this command.
 * @private
 * @type XULElement
 */
MozileCommandSeparator.prototype._createMenuitem = function() {
	this._menuitem = document.createElementNS(XULNS, "menuseparator");
	this._menuitem.setAttribute("id", this.getId() +"-Menuseparator");
	this._menuitem.setAttribute("class", "mozileMenuseparator");
	return this._menuitem;
}




/** Mozile Command List Object -
 * Creates a Mozile command list object, inheriting from MozileCommand, which controls the box and menu associated with a group of Mozile editing commands.
 * @constructor
 * @param {String} configString A properly formatted configuration string.
 */
function MozileCommandList(configString) {

	/**
	 * @private
	 * @type String
	 */
	this._configString = String(configString);

	/**
	 * Holds references to the commands that have requested buttons, in the order they should be displayed.
	 * @private
	 * @type Array
	 */
	this._buttonArray = new Array();

	/**
	 * Holds references to the commands that have requested menuitems, in the order they should be displayed.
	 * @private
	 * @type Array
	 */
	this._menuArray = new Array();
	
}

MozileCommandList.prototype = new MozileCommand;
MozileCommandList.prototype.constructor = MozileCommandList;

/**
 * True if the command can be undone.
 * @type Boolean
 */
MozileCommandList.prototype.isUndoable = function() {
	return false;
}

/**
 * Lists have menus, not menuitems. Returns getMenu().
 * @type XULElement
 */
MozileCommandList.prototype.getMenuitem = function() {
	return this.getMenu();
}

/**
 * Gets the div element which will contain the list's commands.
 * @type HTMLDivElement
 */
MozileCommandList.prototype.getBox = function() {
	if(!this._box) this._createBox();
	return this._box;
}

/**
 * Gets the menu element which will contain the list's commands.
 * @type XULElement
 */
MozileCommandList.prototype.getMenu = function() {
	if(!this._menu) this._createMenu();
	return this._menu;
}

/**
 * Gets the commandList object.
 * @type Object
 */
MozileCommandList.prototype.getCommands = function() {
	if(!this._commands) this._commands = new Object;
	return this._commands;
}

/**
 * Gets a command from the command list given its id.
 * @type Object
 */
MozileCommandList.prototype.getCommand = function(id) {
	if(this.getCommands()[id]) return this.getCommands()[id];
	else return undefined;
}

/** 
 * Adds a command to the commands list.
 * @param {MozileCommand} command
 * @type MozileCommand
 * @return The command object given.
 */
MozileCommandList.prototype.addCommand = function(command) {
	if(command.getId()) this.getCommands()[command.getId()] = command;
	else throw Error("Invalid command.");
	return command;
}

/**
 * Gets the menupopup element which will contain the list's commands.
 * @private
 * @type XULElement
 */
MozileCommandList.prototype._getMenupopup = function() {
	if(!this._menupopup) this._createMenupopup();
	return this._menupopup;
}

/**
 * Shows the button, menu, and box.
 * @type Void
 */
MozileCommandList.prototype.show = function() {
	if(mozile.getOption("hideInactiveCommands")) {
		if(this._button) this._button.setAttribute("collapsed", "false");
		if(this._menu) this._menu.setAttribute("collapsed", "false");
		if(this._box) this._box.setAttribute("collapsed", "false");
	}
	else {
		if(this._button) this._button.setAttribute("disabled", "false");
		if(this._menu) this._menu.setAttribute("disabled", "false");
		if(this._box) this._box.setAttribute("disabled", "false");
	}
}

/**
 * Hides the button, menu, and box.
 * @type Void
 */
MozileCommandList.prototype.hide = function() {
	if(mozile.getOption("hideInactiveCommands")) {
		if(this._button) this._button.setAttribute("collapsed", "true");
		if(this._menu) this._menu.setAttribute("collapsed", "true");
		if(this._box) this._box.setAttribute("collapsed", "true");
	}
	else {
		if(this._button) this._button.setAttribute("disabled", "true");
		if(this._menu) this._menu.setAttribute("disabled", "true");
		if(this._box) this._box.setAttribute("disabled", "true");
	}
}


/**
 * Updates the button, menuitem, and box, as well as all commands on the list.
 * @type Void
 */
MozileCommandList.prototype.update = function() {
	if(!this.isAvailable()) {
		this.hide();
		return;
	}
	this.show();

	for(var command in this.getCommands()) {
		this.getCommand(command).update();
	}
}

/**
 * Makes sure that if the number of buttons has changed the box is updated.
 * @type Boolean
 */
MozileCommandList.prototype.updateBox = function() {
	if(this._buttonArray.length != this.getBox().childNodes.length) {
		this._createBox();
		this.update();
		return true;
	}
	return false;
}

/**
 * Lists cannot be executed - overrides parent with an empty function.
 * @param {Event} event The event object which triggered the command.
 * @type Void
 */
MozileCommandList.prototype.execute = function(event) { }


/** 
 * Creates a new command, adds it to the command list and mozile command list, and adds it to the buttonArray and menuArray as needed.
 * @param {String} configString A properly formatted configuration string.
 * @type Command
 * @return The new commmand.
 */
MozileCommandList.prototype.createCommand = function(configString) {
	var firstWord = /\s*(\w*)/;
	var name = firstWord.exec(configString)[1];
	if(!name) throw Error("Invalid configuration string.");

	var command = eval("new "+ name +"(configString)");
	try {
		command.getId();
	}
	catch(e) {
		return undefined;
	}
	
		// Register the command locally and globally, and the with global accelerator list.
	this.addCommand(command);
	mozile.addCommand(command);
	if(command.getOption("accelerator")) {
		var accel = command.getOption("accelerator");
		if(mozile.getOperatingSystem()=="Mac") {
			accel = accel.replace("Command", "Meta");
		}
		else {
			accel = accel.replace("Command", "Control");
		}
		mozile.addAccelerator(accel, command);
	}

		// Position the button, either at the end or at the given index.
	var position = command.getOption("buttonPosition");
	if(position == undefined) this._buttonArray.push(command);
	else {
		if(this._buttonArray[position] == null) this._buttonArray[position] = command;
		else this._buttonArray.splice(position, 0, command);
	}

		// Position the menuitem, either at the end or at the given index.
	position = command.getOption("menuPosition");
	if(position == undefined) this._menuArray.push(command);
	else {
		if(this._menuArray[position] == null) this._menuArray[position] = command;
		else this._menuArray.splice(position, 0, command);
	}
	
	return command;
}


/** 
 * Creates an XUL button element for this command.
 * @private
 * @type XULElement
 */
MozileCommandList.prototype._createButton = function() {
	this._button = document.createElementNS(XULNS, "toolbarbutton");
	this._button.setAttribute("id", this.getId() +"-Button");
	this._button.setAttribute("class", "mozileButton");
	this._button.setAttribute("image", this.getOption("image"));
	this._button.setAttribute("label", this.getOption("label"));
	if(this.getOption("tooltip")) this._button.setAttribute("tooltiptext", this.getOption("tooltip"));
	this._button.setAttribute("type", "menu");
	
		// Hack to fix problem with toolbarbutton menupopups in Mozilla 1.7.11 and 1.7.12. The boxObject.screenY is wrong by event.pageY pixels, so we fix it. Already fixed in 1.8+.
	if(mozile.getMozillaVersion().indexOf("1.7")>=0) {
		this._button.setAttribute("onpopupshown", "this.firstChild.autoPosition = false; this.firstChild.moveTo(this.boxObject.screenX, this.boxObject.screenY+this.boxObject.height-event.pageY)");
	}
	
	this._button.appendChild(this._getMenupopup());
	return this._button;
}


/** 
 * Lists have menus, not menuitems. Gets the menu instead.
 * @private
 * @type Void
 */
MozileCommandList.prototype._createMenuitem = function() {	return this.getMenu(); }

/** 
 * Creates an XHTML div element to hold the commands on this list.
 * @private
 * @type HTMLDivElement
 */
MozileCommandList.prototype._createBox = function() {
	this._box = document.createElementNS(XHTMLNS, "div");
	this._box.setAttribute("id", this.getId() +"-Box");
	this._box.setAttribute("class", "mozileBox");
	this._box.setAttribute("label", this.getOption("label"));
	if(this.getOption("tooltip")) this._box.setAttribute("tooltiptext", this.getOption("tooltip"));
	
		// Add all the buttons from the buttonArray
	for(var i=0; i < this._buttonArray.length; i++) {
		if(this._buttonArray[i]) {
			this._box.appendChild(this._buttonArray[i].getButton());
		}
	}
	
	return this._box;
}

/** 
 * Creates an XUL menupopup element to hold the commands on this list.
 * @private
 * @type XULElement
 */
MozileCommandList.prototype._createMenu = function() {
	this._menu = document.createElementNS(XULNS, "menu");
	this._menu.setAttribute("id", this.getId() +"-Menu");
	this._menu.setAttribute("class", "mozileMenu");
	this._menu.setAttribute("label", this.getOption("label"));
	if(this.getOption("tooltip")) this._menu.setAttribute("tooltiptext", this.getOption("tooltip"));
	if(this.getOption("accesskey")) this._menu.setAttribute("accesskey", this.getOption("accesskey"));
	
	this._menu.appendChild(this._getMenupopup());
	return this._menu;
}


/** 
 * Creates a menupopup element with child menuitems for each command on the _menuArray.
 * @private
 * @type XULElement
 */
MozileCommandList.prototype._createMenupopup = function() {
	/**
	 * @private
	 * @type XULElement
	 */
	this._menupopup = document.createElementNS(XULNS, "menupopup");
	for(var i=0; i < this._menuArray.length; i++) {
		if(this._menuArray[i]) {
			this._menupopup.appendChild(this._menuArray[i].getMenuitem());
		}
	}
	return this._menupopup;
}




/** 
 * Subclass of MozileComponent designed for manipulating interfaces (e.g. popups, toolbar, etc.). Configuration string format is "InterfaceName: optionKey1=optionValue1, optionKey2=optionValue2".
 * @constructor
 * @param elementOrPath Either the root element for the interface or a string with the path to an external XML document. In the latter case the documentElement of the external document will become the element for this interface.
 * @param {String} configString A properly formatted configuration string.
 */
function MozileInterface(elementOrPath, configString) {
	
	/**
	 * @private
	 * @type String
	 */
	this._elementOrPath = elementOrPath;

	/**
	 * @private
	 * @type String
	 */
	this._configString = String(configString);

}

MozileInterface.prototype = new MozileComponent;
MozileInterface.prototype.constructor = MozileInterface;


/**
 * Gets the root element for the interface. If necessary, loads an external XML file and returns the documentElement.
 * <p>If the interface was created with an element, that element will be returned. If the interface was created with a URL, then we try to load the URL and get the documentElement. If this script was injected by the Mozile Extension, then we require a bit of a hack: the Extension will have also injected the interface, so instead of fetching it we look for its id instead.
 * @type Element
 */
MozileInterface.prototype.getElement = function() {
	if(!this._element) {
		if(document.getElementById(this.getName())) {
			this._element = document.getElementById(this.getName());
			this._parent = this._element.parentNode;
			this._element.collapsed = false;
			this._element.parentNode.removeChild(this._element);
		} 
		else if(typeof(this._elementOrPath) == "object" && this._elementOrPath.nodeType && this._elementOrPath.nodeType==1) {
			this._element = this._elementOrPath;
			this._parent = this._element.parentNode;
		}
		else if(typeof(this._elementOrPath) == "string") {
			this._url = this._elementOrPath;
			try {
				var xmlDoc = document.implementation.createDocument("", "", null);
				xmlDoc.async = false;
				var loaded = xmlDoc.load(this._url);
				if(!loaded) throw Error("Could not load interface.");
				this._element = document.importNode(xmlDoc.documentElement, true);
				this._parent = null;
			}
			catch(e) {
				throw Error("Failed to load external interface in MozileInterface.getElement() at "+ this._elementOrPath +" \n"+ e);
			}
		}
		else {
			throw Error("Invalid elementOrPath in MozileInterface.getElement(): "+ this._elementOrPath);
		}
	}
	return this._element;
}

/**
 * Returns the parent of the interface's root element, finding it if necessary. In an HTML document the parent is the "body" tag. Otherwise it's the documentElement.
 * @type Element
 */
MozileInterface.prototype.getParent = function() {
	if(!this._parent) {	
		this._parent = document.getBody();
	}
	return this._parent;
}

var mozileInterfaceShowing = false;
var mozileCurrentInterface;

/**
 * Reveal the interface.
 * @type Void
 */
MozileInterface.prototype.show = function() {
		// Don't show again if already showing.
	if(this.getElement().parentNode && this.getElement().parentNode == this.getParent()) return;
	
	if(mozileInterfaceShowing) mozileCurrentInterface.hide();
	mozileCurrentInterface = this;
	mozileInterfaceShowing = true;
	
	try {
		if(this._nextSibling) this.getParent().insertBefore(this.getElement(), this._nextSibling);
		else this.getParent().appendChild(this.getElement());
	}
	catch(e) { }
	
	this.getElement().position = "fixed";
	
	if(!this._interval) this._interval = window.setInterval("mozileCurrentInterface.update()", mozile.getOption("defaultInterval"));
	
	this.init();
}

/**
 * Hide the interface.
 * @type Void
 */
MozileInterface.prototype.hide = function() {
		// Hide doesn't work if the element isn't showing.
	if(!this.getElement().parentNode) return;
	
	this._nextSibling = this.getElement().nextSibling;
	this.getParent().removeChild(this.getElement());
	
	mozileInterfaceShowing = false;
	if(this._interval) {
		window.clearInterval(this._interval);
		this._interval = undefined;
	}
}

/**
 * Update the interface.
 * @type Void
 */
MozileInterface.prototype.update = function() {
	this.reposition();
}


/**
 * Center the interface in the window.
 * @type Void
 */
MozileInterface.prototype.reposition = function() {
		// Apply positioning options.
	var options = ["width", "height", "top", "left", "right", "bottom"];
	for(var i=0; i < options.length; i++) {
		if(this.getOption(options[i])) {	
			this.getElement().style[options[i]] = this.getOption(options[i]);
		}
	}
	
		// Try to center the box.
	try {
		if(this.getElement().boxObject) {
			var left = (window.innerWidth - this.getElement().boxObject.width) / window.innerWidth * 50 ;
			if(left > 0) this.getElement().style.left = left + "%";
			var top = (window.innerHeight - this.getElement().boxObject.height) / window.innerHeight * 50;
			if(top > 0) this.getElement().style.top = top + "%";
		}
	} catch(e) { }
}

/**
 * Initialize the interface.
 * @type Void
 */
MozileInterface.prototype.init = function() { }


/** 
 * Subclass of MozileInterface for dealing with the toolbar and statusbar.
 * <p>The "position" option should be set. The current options are "topOfWindow" (default) and "bottomOfWindow".
 * @constructor
 * @param elementOrPath Either the root element for the interface or a string with the path to an external XML document. In the latter case the documentElement of the external document will become the element for this interface.
 * @param {String} configString A properly formatted configuration string.
 */
function MozileToolbar(elementOrPath, configString) {
	
	/**
	 * @private
	 * @type String
	 */
	this._elementOrPath = elementOrPath;

	/**
	 * @private
	 * @type String
	 */
	this._configString = String(configString);

}

MozileToolbar.prototype = new MozileInterface;
MozileToolbar.prototype.constructor = MozileToolbar;


/**
 * Gets the position for the toolbar. If the otpion isn't set, sets it to "topOfWindow".
 * @type String
 */
MozileToolbar.prototype.getPosition = function() {
	return this.getOption("position", "topOfWindow");
}

/**
 * Repositions the toolbar.
 * @type Void
 */
MozileToolbar.prototype.reposition = function() {
		// This seems unnecessary, but it makes the mozile.getToolbar().boxObject.width read properly (or at least better).
	//this.getElement().style.left= "0px";
	
	try{ this.getElement().boxObject }
	catch(e) { return; }
	
		// Set the left position so the element is centred.
	if(window.innerWidth - this.getElement().boxObject.width >= 0) {
		this.getElement().style.left = (window.innerWidth - this.getElement().boxObject.width) / 2 +"px";
	}
	else this.getElement().style.left = "0px";
	
	if(this.getPosition() == "bottomOfWindow") {
		this.getElement().style.top = window.pageYOffset + window.innerHeight - this.getElement().boxObject.height + 1 +"px";
	}
	else this.getElement().style.top = window.pageYOffset - 1 +"px";
}


/**
 * Reveal the interface.
 * @type Void
 */
MozileToolbar.prototype.show = function() {
		// If it's in the document, collapse it.
	if(this.getElement().parentNode && this.getElement().parentNode == this.getParent()) { 
		this.getElement().collapsed = false;
	}
		// Otherwise add it to the document.
	else {
		this.getParent().appendChild(this.getElement());
	}
	this.init();
}

/**
 * Hide the interface.
 * @type Void
 */
MozileToolbar.prototype.hide = function() {
	this.getElement().collapsed = true;
}


Documentation generated by JSDoc on Wed Nov 1 15:11:15 2006

The mozile project can be contacted through the mailing list or the member list.
Copyright © 2000-2019. All rights reserved. Terms of Use & Privacy Policy.