diff --git a/mozilla/extensions/venkman/js/venkman-service.js b/mozilla/extensions/venkman/js/venkman-service.js index 77207d36a26..8294af74e17 100644 --- a/mozilla/extensions/venkman/js/venkman-service.js +++ b/mozilla/extensions/venkman/js/venkman-service.js @@ -36,13 +36,41 @@ /* components defined in this file */ const CLINE_SERVICE_CTRID = "@mozilla.org/commandlinehandler/general-startup;1?type=venkman"; -const CATMAN_CTRID = "@mozilla.org/categorymanager;1"; const CLINE_SERVICE_CID = Components.ID("{18269616-1dd2-11b2-afa8-b612439bda27}"); +const JSDPROT_HANDLER_CTRID = + "@mozilla.org/network/protocol;1?name=x-jsd"; +const JSDPROT_HANDLER_CID = + Components.ID("{12ec790d-304e-4525-89a9-3e723d489d14}"); -const nsICmdLineHandler = Components.interfaces.nsICmdLineHandler; -const nsICategoryManager = Components.interfaces.nsICategoryManager; -const nsISupports = Components.interfaces.nsISupports; +/* components used by this file */ +const CATMAN_CTRID = "@mozilla.org/categorymanager;1"; +const STRING_STREAM_CTRID = "@mozilla.org/io/string-input-stream;1"; +const MEDIATOR_CTRID = + "@mozilla.org/appshell/window-mediator;1"; +const SIMPLEURI_CTRID = "@mozilla.org/network/simple-uri;1"; + +const nsIWindowMediator = Components.interfaces.nsIWindowMediator; +const nsICmdLineHandler = Components.interfaces.nsICmdLineHandler; +const nsICategoryManager = Components.interfaces.nsICategoryManager; +const nsIProtocolHandler = Components.interfaces.nsIProtocolHandler; +const nsIURI = Components.interfaces.nsIURI; +const nsIURL = Components.interfaces.nsIURL; +const nsIStringInputStream = Components.interfaces.nsIStringInputStream; +const nsIChannel = Components.interfaces.nsIChannel; +const nsIRequest = Components.interfaces.nsIRequest; +const nsIProgressEventSink = Components.interfaces.nsIProgressEventSink; +const nsISupports = Components.interfaces.nsISupports; + +function findDebuggerWindow () +{ + var windowManager = + Components.classes[MEDIATOR_CTRID].getService(nsIWindowMediator); + + var window = windowManager.getMostRecentWindow("mozapp:venkman"); + + return window; +} /* Command Line handler service */ function CLineService() @@ -50,17 +78,17 @@ function CLineService() CLineService.prototype.commandLineArgument = "-venkman"; CLineService.prototype.prefNameForStartup = "general.startup.venkman"; -CLineService.prototype.chromeUrlForTask="chrome://venkman/content"; -CLineService.prototype.helpText = "Start with JavaScript debugger"; -CLineService.prototype.handlesArgs=false; -CLineService.prototype.defaultArgs =""; -CLineService.prototype.openWindowWithArgs=false; +CLineService.prototype.chromeUrlForTask = "chrome://venkman/content"; +CLineService.prototype.helpText = "Start with JavaScript Debugger."; +CLineService.prototype.handlesArgs = false; +CLineService.prototype.defaultArgs = ""; +CLineService.prototype.openWindowWithArgs = false; /* factory for command line handler service (CLineService) */ var CLineFactory = new Object(); CLineFactory.createInstance = -function (outer, iid) { +function clf_create (outer, iid) { if (outer != null) throw Components.results.NS_ERROR_NO_AGGREGATION; @@ -70,6 +98,277 @@ function (outer, iid) { return new CLineService(); } +/* x-jsd: protocol handler */ + +const JSD_DEFAULT_PORT = 2206; /* Dana's apartment number. */ + +/* protocol handler factory object */ +var JSDProtocolHandlerFactory = new Object(); + +JSDProtocolHandlerFactory.createInstance = +function jsdhf_create (outer, iid) { + if (outer != null) + throw Components.results.NS_ERROR_NO_AGGREGATION; + + if (!iid.equals(nsIProtocolHandler) && !iid.equals(nsISupports)) + throw Components.results.NS_ERROR_INVALID_ARG; + + return new JSDProtocolHandler(); +} + +function JSDURI (spec, charset) +{ + this.spec = this.prePath = spec; + this.charset = this.originCharset = charset; +} + +JSDURI.prototype.QueryInterface = +function jsdch_qi (iid) +{ + + if (!iid.equals(nsIURI) && !iid.equals(nsIURL) && + !iid.equals(nsISupports)) + throw Components.results.NS_ERROR_NO_INTERFACE; + + return this; +} + +JSDURI.prototype.scheme = "x-jsd"; + + +JSDURI.prototype.fileBaseName = +JSDURI.prototype.fileExtension = +JSDURI.prototype.filePath = +JSDURI.prototype.param = +JSDURI.prototype.query = +JSDURI.prototype.ref = +JSDURI.prototype.directory = +JSDURI.prototype.fileName = +JSDURI.prototype.username = +JSDURI.prototype.password = +JSDURI.prototype.hostPort = +JSDURI.prototype.path = +JSDURI.prototype.asciiHost = +JSDURI.prototype.userPass = ""; + +JSDURI.prototype.port = JSD_DEFAULT_PORT; + +JSDURI.prototype.schemeIs = +function jsduri_schemeis (scheme) +{ + return scheme.toLowerCase() == "x-jsd"; +} + +JSDURI.prototype.getCommonBaseSpec = +function jsduri_commonbase (uri) +{ + return "x-jsd:"; +} + +JSDURI.prototype.getRelativeSpec = +function jsduri_commonbase (uri) +{ + return uri; +} + +JSDURI.prototype.equals = +function jsduri_equals (uri) +{ + return uri.spec == this.spec; +} + +JSDURI.prototype.clone = +function jsduri_clone () +{ + return new JSDURI (this.spec); +} + +JSDURI.prototype.resolve = +function jsduri_resolve(path) +{ + //dump ("resolve " + path + " from " + this.spec + "\n"); + if (path[0] == "#") + return this.spec + path; + + return path; +} + +function JSDProtocolHandler() +{ + /* nothing here */ +} + +JSDProtocolHandler.prototype.scheme = "x-jsd"; +JSDProtocolHandler.prototype.defaultPort = JSD_DEFAULT_PORT; +JSDProtocolHandler.prototype.protocolFlags = nsIProtocolHandler.URI_NORELATIVE; + +JSDProtocolHandler.prototype.allowPort = +function jsdph_allowport (aPort, aScheme) +{ + return false; +} + +JSDProtocolHandler.prototype.newURI = +function jsdph_newuri (spec, charset, baseURI) +{ + if (baseURI) + { + debug ("-*- jsdHandler: aBaseURI passed to newURI, bailing.\n"); + return null; + } + + var clazz = Components.classes[SIMPLEURI_CTRID]; + var uri = clazz.createInstance(nsIURI); + uri.spec = spec; + return uri; +} + +JSDProtocolHandler.prototype.newChannel = +function jsdph_newchannel (uri) +{ + return new JSDChannel (uri); +} + +function JSDChannel (uri) +{ + this.URI = uri; + this.originalURI = uri; + this._isPending = true; + var clazz = Components.classes[STRING_STREAM_CTRID]; + this.stringStream = clazz.createInstance(nsIStringInputStream); +} + +JSDChannel.prototype.QueryInterface = +function jsdch_qi (iid) +{ + + if (!iid.equals(nsIChannel) && !iid.equals(nsIRequest) && + !iid.equals(nsISupports)) + throw Components.results.NS_ERROR_NO_INTERFACE; + + return this; +} + +/* nsIChannel */ +JSDChannel.prototype.loadAttributes = null; +JSDChannel.prototype.contentType = "text/html"; +JSDChannel.prototype.contentLength = -1; +JSDChannel.prototype.owner = null; +JSDChannel.prototype.loadGroup = null; +JSDChannel.prototype.notificationCallbacks = null; +JSDChannel.prototype.securityInfo = null; + +JSDChannel.prototype.open = +function jsdch_open() +{ + throw Components.results.NS_ERROR_NOT_IMPLEMENTED; +} + +JSDChannel.prototype.asyncOpen = +function jsdch_aopen (streamListener, context) +{ + this.streamListener = streamListener; + this.context = context; + if (this.loadGroup) + this.loadGroup.addRequest (this, null); + + var window = findDebuggerWindow(); + var ary = this.URI.spec.match (/x-jsd:([^:]+)/); + var exception; + + if (window && "console" in window && ary) + { + try + { + window.asyncOpenJSDURL (this, streamListener, context); + return; + } + catch (ex) + { + exception = ex; + } + } + + var str = + "
" +
+ exception.stack;
+ }
+ else
+ {
+ str += "Debugger is not running.";
+ }
+
+ str += "";
+
+ this.respond (str);
+}
+
+JSDChannel.prototype.respond =
+function jsdch_respond (str)
+{
+ this.streamListener.onStartRequest (this, this.context);
+
+ var len = str.length;
+ this.stringStream.setData (str, len);
+ this.streamListener.onDataAvailable (this, this.context,
+ this.stringStream, 0, len);
+ this.streamListener.onStopRequest (this, this.context,
+ Components.results.NS_OK);
+ if (this.loadGroup)
+ this.loadGroup.removeRequest (this, null, Components.results.NS_OK);
+ this._isPending = false;
+}
+
+/* nsIRequest */
+JSDChannel.prototype.isPending =
+function jsdch_ispending ()
+{
+ return this._isPending;
+}
+
+JSDChannel.prototype.status = Components.results.NS_OK;
+
+JSDChannel.prototype.cancel =
+function jsdch_cancel (status)
+{
+ if (this._isPending)
+ {
+ this._isPending = false;
+ this.streamListener.onStopRequest (this, this.context, status);
+ if (this.loadGroup)
+ {
+ try
+ {
+ this.loadGroup.removeRequest (this, null, status);
+ }
+ catch (ex)
+ {
+ debug ("we're not in the load group?\n");
+ }
+ }
+ }
+
+ this.status = status;
+}
+
+JSDChannel.prototype.suspend =
+JSDChannel.prototype.resume =
+function jsdch_notimpl ()
+{
+ throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+}
+
+/*****************************************************************************/
+
var Module = new Object();
Module.registerSelf =
@@ -77,7 +376,8 @@ function (compMgr, fileSpec, location, type)
{
debug("*** Registering -venkman handler.\n");
- compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
+ compMgr =
+ compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
compMgr.registerFactoryLocation(CLINE_SERVICE_CID,
"Venkman CommandLine Service",
@@ -90,7 +390,26 @@ function (compMgr, fileSpec, location, type)
catman.addCategoryEntry("command-line-argument-handlers",
"venkman command line handler",
CLINE_SERVICE_CTRID, true, true);
-
+
+ debug("*** Registering x-jsd protocol handler.\n");
+ compMgr.registerFactoryLocation(JSDPROT_HANDLER_CID,
+ "x-jsd protocol handler",
+ JSDPROT_HANDLER_CTRID,
+ fileSpec,
+ location,
+ type);
+ try
+ {
+ const JSD_CTRID = "@mozilla.org/js/jsd/debugger-service;1";
+ const jsdIDebuggerService = Components.interfaces.jsdIDebuggerService;
+ var jsds = Components.classes[JSD_CTRID].getService(jsdIDebuggerService);
+ jsds.initAtStartup = true;
+ }
+ catch (ex)
+ {
+ debug ("*** ERROR initializing debugger service");
+ debug (ex);
+ }
}
Module.unregisterSelf =
@@ -109,11 +428,8 @@ function (compMgr, cid, iid) {
if (cid.equals(CLINE_SERVICE_CID))
return CLineFactory;
- if (cid.equals(IRCCNT_HANDLER_CID))
- return IRCContentHandlerFactory;
-
- if (cid.equals(IRCPROT_HANDLER_CID))
- return IRCProtocolHandlerFactory;
+ if (cid.equals(JSDPROT_HANDLER_CID))
+ return JSDProtocolHandlerFactory;
if (!iid.equals(Components.interfaces.nsIFactory))
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
diff --git a/mozilla/extensions/venkman/resources/content/command-manager.js b/mozilla/extensions/venkman/resources/content/command-manager.js
index 6d0557198db..88cf64c8be5 100644
--- a/mozilla/extensions/venkman/resources/content/command-manager.js
+++ b/mozilla/extensions/venkman/resources/content/command-manager.js
@@ -33,7 +33,7 @@ function getAccessKey (str)
return str[i + 1];
}
-function CommandRecord (name, func, usage, help, label, flags)
+function CommandRecord (name, func, usage, help, label, flags, keystr)
{
this.name = name;
this.func = func;
@@ -41,11 +41,13 @@ function CommandRecord (name, func, usage, help, label, flags)
this.scanUsage();
this.help = help;
this.label = label ? label : name;
+ this.labelstr = label.replace ("&", "");
this.flags = flags;
this._enabled = true;
- this.key = null;
- this.keystr = MSG_VAL_NA;
- this.uiElements = new Object();
+ this.keyNodes = new Array();
+ this.keystr = keystr;
+ this.uiElements = new Array();
+
}
CommandRecord.prototype.__defineGetter__ ("enabled", cr_getenable);
@@ -57,7 +59,7 @@ function cr_getenable ()
CommandRecord.prototype.__defineSetter__ ("enabled", cr_setenable);
function cr_setenable (state)
{
- for (var i in this.uiElements)
+ for (var i = 0; i < this.uiElements.length; ++i)
{
if (state)
this.uiElements[i].removeAttribute ("disabled");
@@ -96,7 +98,7 @@ function cr_scanusage()
var capNext = false;
this._usage = spec;
- this.argNames = new Array();
+ this.argNames = new Array();
for (var i = 0; i < len; ++i)
{
@@ -141,7 +143,7 @@ function cr_getdocs(flagFormatter)
var str;
str = getMsg(MSN_DOC_COMMANDLABEL,
[this.label.replace("&", ""), this.name]) + "\n";
- str += getMsg(MSN_DOC_KEY, this.keystr) + "\n";
+ str += getMsg(MSN_DOC_KEY, this.keystr ? this.keystr : MSG_VAL_NA) + "\n";
str += getMsg(MSN_DOC_SYNTAX, [this.name, this.usage]) + "\n";
str += MSG_DOC_NOTES + "\n";
str += (flagFormatter ? flagFormatter(this.flags) : this.flags) + "\n\n";
@@ -152,151 +154,137 @@ function cr_getdocs(flagFormatter)
CommandRecord.prototype.argNames = new Array();
-function CommandManager ()
+function CommandManager (defaultBundle)
{
this.commands = new Object();
+ this.defaultBundle = defaultBundle;
+}
+
+CommandManager.prototype.defineCommands =
+function cmgr_defcmds (cmdary)
+{
+ var len = cmdary.length;
+ var commands = new Object();
+ var bundle = ("stringBundle" in cmdary ?
+ cmdary.stringBundle :
+ this.defaultBundle);
+
+ for (var i = 0; i < len; ++i)
+ {
+ var name = cmdary[i][0];
+ var func = cmdary[i][1];
+ var flags = cmdary[i][2];
+ var usage = getMsgFrom(bundle, "cmd." + name + ".params", null, "");
+
+ var helpDefault;
+ var labelDefault = name;
+ var aliasFor;
+ if (flags & CMD_NO_HELP)
+ helpDefault = MSG_NO_HELP;
+
+ if (typeof func == "string")
+ {
+ var ary = func.match(/(\S+)/);
+ if (ary)
+ aliasFor = ary[1];
+ helpDefault = getMsg (MSN_DEFAULT_ALIAS_HELP, func);
+ labelDefault = getMsgFrom (bundle,
+ "cmd." + aliasFor + ".label", null, name);
+ }
+
+ var label = getMsgFrom(bundle,
+ "cmd." + name + ".label", null, labelDefault);
+ var help = getMsgFrom(bundle,
+ "cmd." + name + ".help", null, helpDefault);
+ var keystr = getMsgFrom (bundle, "cmd." + name + ".key", null, "");
+ var command = new CommandRecord (name, func, usage, help, label, flags,
+ keystr);
+ if (aliasFor)
+ command.aliasFor = aliasFor;
+ this.addCommand(command);
+ commands[name] = command;
+ }
+
+ return commands;
+}
+
+CommandManager.prototype.installKeys =
+function cmgr_instkeys (document, commands)
+{
+ var parentElem = document.getElementById("dynamic-keys");
+ if (!parentElem)
+ {
+ parentElem = document.createElement("keyset");
+ parentElem.setAttribute ("id", "dynamic-keys");
+ document.firstChild.appendChild (parentElem);
+ }
+
+ if (!commands)
+ commands = this.commands;
+
+ for (var c in commands)
+ this.installKey (parentElem, commands[c]);
}
/**
- * Internal use only.
+ * Create a node relative to a DOM node. Usually called once per command,
+ * per document, so that accelerator keys work in all application windows.
*
- * |showPopup| is called from the "onpopupshowing" event of menus
- * managed by the CommandManager. If a command is disabled, represents a command
- * that cannot be "satisfied" by the current command context |cx|, or has an
- * "enabledif" attribute that eval()s to false, then the menuitem is disabled.
- * In addition "checkedif" and "visibleif" attributes are eval()d and
- * acted upon accordingly.
+ * @param parentElem A reference to the DOM node which should contain the new
+ * node.
+ * @param command reference to the CommandRecord to install.
*/
-CommandManager.showPopup =
-function cmgr_showpop (id)
+CommandManager.prototype.installKey =
+function cmgr_instkey (parentElem, command)
{
- /* returns true if the command context has the properties required to
- * execute the command associated with |menuitem|.
- */
- function satisfied()
+ if (!command.keystr)
+ return;
+
+ var ary = command.keystr.match (/(.*\s)?([\S]+)$/);
+ if (!ASSERT(ary, "couldn't parse key string ``" + command.keystr +
+ "'' for command ``" + command.name + "''"))
{
- if (menuitem.hasAttribute("isSeparator"))
- return true;
-
- if (!("commandManager" in cx))
- {
- dd ("no commandManager in cx");
- return false;
- }
-
- var name = menuitem.getAttribute("commandname");
- if (!ASSERT (name in cx.commandManager.commands,
- "menu contains unknown command '" + name + "'"))
- return false;
-
- var command = cx.commandManager.commands[name];
-
- var rv = cx.commandManager.isCommandSatisfied(cx, command);
- delete cx.parseError;
- return rv;
+ return;
}
- /* Convenience function for "enabledif", etc, attributes. */
- function has (prop)
- {
- return (prop in cx);
- }
+ var key = document.createElement ("key");
+ key.setAttribute ("id", "key:" + command.name);
+ key.setAttribute ("oncommand", "dispatch('" + command.name + "');");
+ key.setAttribute ("modifiers", ary[1]);
+ if (ary[2].indexOf("VK_") == 0)
+ key.setAttribute ("keycode", ary[2]);
+ else
+ key.setAttribute ("key", ary[2]);
- /* evals the attribute named |attr| on the node |node|. */
- function evalIfAttribute (node, attr)
+ parentElem.appendChild(key);
+ command.keyNodes.push(key);
+}
+
+CommandManager.prototype.uninstallKeys =
+function cmgr_uninstkeys (commands)
+{
+ if (!commands)
+ commands = this.commands;
+
+ for (var c in commands)
+ this.uninstallKey (commands[c]);
+}
+
+CommandManager.prototype.uninstallKey =
+function cmgr_uninstkey (command)
+{
+ for (var i in command.keyNodes)
{
- var ex;
- var expr = node.getAttribute(attr);
- if (!expr)
- return true;
-
- expr = expr.replace (/\Wor\W/gi, " || ");
- expr = expr.replace (/\Wand\W/gi, " && ");
try
{
- return eval("(" + expr + ")");
+ /* document may no longer exist in a useful state. */
+ command.keyNodes[i].parentNode.removeChild(command.keyNodes[i]);
}
catch (ex)
{
- dd ("caught exception evaling '" + node.getAttribute("id") + "'.'" +
- attr + "'\n" + ex);
+ dd ("*** caught exception uninstalling key node: " + ex);
}
- return true;
}
-
- var cx;
-
- /* If the host provided a |contextFunction|, use it now. Remember the
- * return result as this.cx for use if something from this menu is actually
- * dispatched. this.cx is deleted in |hidePopup|. */
- if (typeof this.contextFunction == "function")
- cx = this.cx = this.contextFunction (id);
- else
- cx = new Object();
-
- /* make this a member of cx so the |this| value is useful to attriutes. */
-
- var popup = document.getElementById (id);
- var menuitem = popup.firstChild;
-
- do
- {
- /* should it be visible? */
- if (menuitem.hasAttribute("visibleif"))
- {
- if (evalIfAttribute(menuitem, "visibleif"))
- menuitem.removeAttribute ("hidden");
- else
- {
- menuitem.setAttribute ("hidden", "true");
- continue;
- }
- }
-
- /* ok, it's visible, maybe it should be disabled? */
- if (satisfied())
- {
- if (menuitem.hasAttribute("enabledif"))
- {
- if (evalIfAttribute(menuitem, "enabledif"))
- menuitem.removeAttribute ("disabled");
- else
- menuitem.setAttribute ("disabled", "true");
- }
- else
- menuitem.removeAttribute ("disabled");
- }
- else
- {
- menuitem.setAttribute ("disabled", "true");
- }
-
- /* should it have a check? */
- if (menuitem.hasAttribute("checkedif"))
- {
- if (evalIfAttribute(menuitem, "checkedif"))
- menuitem.setAttribute ("checked", "true");
- else
- menuitem.removeAttribute ("checked");
- }
-
- } while ((menuitem = menuitem.nextSibling));
-
- return true;
-}
-
-/**
- * Internal use only.
- *
- * |hidePopup| is called from the "onpopuphiding" event of menus
- * managed by the CommandManager. Here we just clean up the context, which
- * would have (and may have) become the event object used by any command
- * dispatched while the menu was open.
- */
-CommandManager.hidePopup =
-function cmgr_hidepop (id)
-{
- delete this.cx;
}
/**
@@ -308,255 +296,120 @@ function cmgr_add (command)
this.commands[command.name] = command;
}
-/**
- * Set the accelerator key used to trigger a command. Multiple keys can be
- * assigned to a command, but only the last one will appear in the documentation
- * entry for the command.
- * @param parent ID of the keyset to add the to.
- * @param command reference to the CommandRecord which should be dispatced.
- * @param keystr String representation of the key, in the format
- * (|), where the parameter names
- * represent attributes on the object.
- */
-CommandManager.prototype.setKey =
-function cmgr_add (parent, command, keystr)
+CommandManager.prototype.removeCommands =
+function cmgr_removes (commands)
{
- var parentElem = document.getElementById(parent);
- if (!ASSERT(parentElem, "setKey: couldn't get parent '" + parent +
- "' for " + command.name))
- return;
+ for (var c in commands)
+ this.removeCommand(commands[c]);
+}
- var ary = keystr.match (/(.*\s)?([\S]+)$/);
- var key = document.createElement ("key");
- key.setAttribute ("id", "key:" + command.name);
- key.setAttribute ("oncommand",
- "dispatch('" + command.name + "');");
- key.setAttribute ("modifiers", ary[1]);
- if (ary[2].indexOf("VK_") == 0)
- key.setAttribute ("keycode", ary[2]);
+CommandManager.prototype.removeCommand =
+function cmgr_remove (command)
+{
+ delete this.commands[command.name];
+}
+
+/**
+ * Register a hook for a particular command name. |id| is a human readable
+ * identifier for the hook, and can be used to unregister the hook. If you
+ * re-use a hook id, the previous hook function will be replaced.
+ * If |before| is |true|, the hook will be called *before* the command executes,
+ * if |before| is |false|, or not specified, the hook will be called *after*
+ * the command executes.
+ */
+CommandManager.prototype.addHook =
+function cmgr_hook (commandName, func, id, before)
+{
+ if (!ASSERT(commandName in this.commands,
+ "Unknown command '" + commandName + "'"))
+ {
+ return;
+ }
+
+ var command = this.commands[commandName];
+
+ if (before)
+ {
+ if (!("beforeHookNames" in command))
+ command.beforeHookNames = new Array();
+ if (!("beforeHooks" in command))
+ command.beforeHooks = new Object();
+ if (id in command.beforeHooks)
+ {
+ arrayRemoveAt(command.beforeHookNames,
+ command.beforeHooks[id][id + "_hookIndex"]);
+ }
+ command.beforeHooks[id] = func;
+ command.beforeHookNames.push(id);
+ }
else
- key.setAttribute ("key", ary[2]);
-
- parentElem.appendChild(key);
- command.key = key;
- command.keystr = keystr;
+ {
+ if (!("afterHookNames" in command))
+ command.afterHookNames = new Array();
+ if (!("afterHooks" in command))
+ command.afterHooks = new Object();
+ func[id + "_hookIndex"] = command.afterHookNames.length
+ command.afterHooks[id] = func;
+ command.afterHookNames.push(id);
+ }
}
-/**
- * Internal use only.
- *
- * Registers event handlers on a given menu.
- */
-CommandManager.prototype.hookPopup =
-function cmgr_hookpop (id)
+CommandManager.prototype.addHooks =
+function cmgr_hooks (hooks, prefix)
{
- var element = document.getElementById (id);
- element.setAttribute ("onpopupshowing",
- "return CommandManager.showPopup('" + id + "');");
- element.setAttribute ("onpopuphiding",
- "return CommandManager.hidePopup();");
+ if (!prefix)
+ prefix = "";
+
+ for (var h in hooks)
+ {
+ this.addHook(h, hooks[h], prefix + ":" + h,
+ ("before" in hooks[h]) ? hooks[h].before : false);
+ }
}
-/**
- * Appends a sub-menu to an existing menu.
- * @param parent ID of the parent menu to add this submenu to.
- * @param id ID of the sub-menu to add.
- * @param label Text to use for this sub-menu. The & character can be
- * used to indicate the accesskey.
- * @param attribs Object containing CSS attributes to set on the element.
- */
-CommandManager.prototype.appendSubMenu =
-function cmgr_addsmenu (parent, id, label, attribs)
+CommandManager.prototype.removeHooks =
+function cmgr_remhooks (hooks, prefix)
{
- var menu = document.getElementById (id);
- if (!menu)
- {
- var parentElem = document.getElementById(parent + "-popup");
- if (!parentElem)
- parentElem = document.getElementById(parent);
-
- if (!ASSERT(parentElem, "addSubMenu: couldn't get parent '" + parent +
- "' for " + id))
- return;
+ if (!prefix)
+ prefix = "";
- menu = document.createElement ("menu");
- menu.setAttribute ("id", id);
- parentElem.appendChild(menu);
- }
-
- menu.setAttribute ("accesskey", getAccessKey(label));
- menu.setAttribute ("label", label.replace("&", ""));
- menu.setAttribute ("isSeparator", true);
- var menupopup = document.createElement ("menupopup");
- menupopup.setAttribute ("id", id + "-popup");
- if (typeof attribs == "object")
+ for (var h in hooks)
{
- for (var p in attribs)
- menupopup.setAttribute (p, attribs[p]);
+ this.removeHook(h, prefix + ":" + h,
+ ("before" in hooks[h]) ? hooks[h].before : false);
}
-
- menu.appendChild(menupopup);
- this.hookPopup (id + "-popup");
}
-/**
- * Appends a popup to an existing popupset.
- * @param parent ID of the popupset to add this popup to.
- * @param id ID of the popup to add.
- * @param label Text to use for this popup. Popup menus don't normally have
- * labels, but we set a "label" attribute anyway, in case
- * the host wants it for some reason. Any "&" characters will
- * be stripped.
- * @param attribs Object containing CSS attributes to set on the element.
- */
-CommandManager.prototype.appendPopupMenu =
-function cmgr_addsmenu (parent, id, label, attribs)
+CommandManager.prototype.removeHook =
+function cmgr_unhook (commandName, id, before)
{
- var parentElem = document.getElementById (parent);
- if (!ASSERT(parentElem, "addPopupMenu: couldn't get parent '" + parent +
- "' for " + id))
- return;
+ var command = this.commands[commandName];
- var popup = document.createElement ("popup");
- popup.setAttribute ("label", label.replace("&", ""));
- popup.setAttribute ("id", id);
- if (typeof attribs == "object")
+ if (before)
{
- for (var p in attribs)
- popup.setAttribute (p, attribs[p]);
+ arrayRemoveAt(command.beforeHookNames,
+ command.beforeHooks[id][id + "_hookIndex"]);
+ delete command.beforeHooks[id][id + "_hookIndex"];
+ delete command.beforeHooks[id];
+ if (keys(command.beforeHooks).length == 0)
+ {
+ delete command.beforeHookNames;
+ delete command.beforeHooks;
+ }
+ }
+ else
+ {
+ arrayRemoveAt(command.afterHookNames,
+ command.afterHooks[id][id + "_hookIndex"]);
+ delete command.afterHooks[id][id + "_hookIndex"];
+ delete command.afterHooks[id];
+ if (command.afterHookNames.length == 0)
+ {
+ delete command.afterHookNames;
+ delete command.afterHooks;
+ }
}
- parentElem.appendChild(popup);
- this.hookPopup (id);
-}
-
-/**
- * Appends a menuitem to an existing menu or popup.
- * @param parent ID of the popup to add this menuitem to.
- * @param command A reference to the CommandRecord this menu item will represent.
- * @param attribs Object containing CSS attributes to set on the element.
- */
-CommandManager.prototype.appendMenuItem =
-function cmgr_addmenu (parent, command, attribs)
-{
- if (command == "-")
- {
- this.appendMenuSeparator(parent, attribs);
- return;
- }
-
- var parentElem = document.getElementById(parent + "-popup");
- if (!parentElem)
- parentElem = document.getElementById(parent);
-
- if (!ASSERT(parentElem, "appendMenuItem: couldn't get parent '" + parent +
- "' for " + command.name))
- return;
-
- var menuitem = document.createElement ("menuitem");
- var id = parent + ":" + command.name;
- menuitem.setAttribute ("id", id);
- menuitem.setAttribute ("commandname", command.name);
- menuitem.setAttribute ("key", "key:" + command.name);
- menuitem.setAttribute ("accesskey", getAccessKey(command.label));
- menuitem.setAttribute ("label", command.label.replace("&", ""));
- menuitem.setAttribute ("oncommand",
- "dispatch('" + command.name + "');");
- if (typeof attribs == "object")
- {
- for (var p in attribs)
- menuitem.setAttribute (p, attribs[p]);
- }
-
- command.uiElements[id] = menuitem;
- parentElem.appendChild (menuitem);
-}
-
-/**
- * Appends a menuseparator to an existing menu or popup.
- * @param parent ID of the popup to add this menuitem to.
- */
-CommandManager.prototype.appendMenuSeparator =
-function cmgr_addsep (parent)
-{
- var parentElem = document.getElementById(parent + "-popup");
- if (!parentElem)
- parentElem = document.getElementById(parent);
-
- if (!ASSERT(parentElem, "appendMenuSeparator: couldn't get parent '" +
- parent + "'"))
- return;
-
- var menuitem = document.createElement ("menuseparator");
- menuitem.setAttribute ("isSeparator", true);
- if (typeof attribs == "object")
- {
- for (var p in attribs)
- menuitem.setAttribute (p, attribs[p]);
- }
- parentElem.appendChild (menuitem);
-}
-
-/**
- * Appends a toolbaritem to an existing box element.
- * @param parent ID of the box to add this toolbaritem to.
- * @param command A reference to the CommandRecord this toolbaritem will
- * represent.
- * @param attribs Object containing CSS attributes to set on the element.
- */
-CommandManager.prototype.appendToolbarItem =
-function cmgr_addtb (parent, command, attribs)
-{
- if (command == "-")
- {
- this.appendToolbarSeparator(parent, attribs);
- return;
- }
-
- var parentElem = document.getElementById(parent);
-
- if (!ASSERT(parentElem, "appendToolbarItem: couldn't get parent '" + parent +
- "' for " + command.name))
- return;
-
- var tbitem = document.createElement ("toolbarbutton");
- // separate toolbar id's with a "-" character, because : intereferes with css
- var id = parent + "-" + command.name;
- tbitem.setAttribute ("id", id);
- tbitem.setAttribute ("class", "toolbarbutton-1");
- tbitem.setAttribute ("label", command.label.replace("&", ""));
- tbitem.setAttribute ("oncommand",
- "dispatch('" + command.name + "');");
- if (typeof attribs == "object")
- {
- for (var p in attribs)
- tbitem.setAttribute (p, attribs[p]);
- }
-
- command.uiElements[id] = tbitem;
- parentElem.appendChild (tbitem);
-}
-
-/**
- * Appends a toolbarseparator to an existing box.
- * @param parent ID of the box to add this toolbarseparator to.
- */
-CommandManager.prototype.appendToolbarSeparator =
-function cmgr_addmenu (parent)
-{
- var parentElem = document.getElementById(parent);
- if (!ASSERT(parentElem, "appendToolbarSeparator: couldn't get parent '" +
- parent + "'"))
- return;
-
- var tbitem = document.createElement ("toolbarseparator");
- tbitem.setAttribute ("isSeparator", true);
- if (typeof attribs == "object")
- {
- for (var p in attribs)
- tbitem.setAttribute (p, attribs[p]);
- }
- parentElem.appendChild (tbitem);
}
/**
@@ -574,8 +427,8 @@ function cmgr_list (partialName, flags)
* all commands if |partialName| is not specified */
function compare (a, b)
{
- a = a.label.toLowerCase().replace("&", "");
- b = b.label.toLowerCase().replace("&", "");
+ a = a.labelstr.toLowerCase();
+ b = b.labelstr.toLowerCase();
if (a == b)
return 0;
@@ -723,7 +576,7 @@ function parse_parseargsraw (e)
}
}
- if (e.inputData)
+ if ("inputData" in e && e.inputData)
{
/* if data has been provided, parse it */
e.unparsedData = e.inputData;
@@ -792,7 +645,7 @@ function parse_parseargsraw (e)
* Returns true if |e| has the properties required to call the command |command|.
* If |command| is not provided, |e.command| is used instead.
* @param e Event object to test against the command.
- * @param command Command to text.
+ * @param command Command to test.
*/
CommandManager.prototype.isCommandSatisfied =
function cmgr_isok (e, command)
@@ -821,7 +674,7 @@ function cmgr_isok (e, command)
}
/**
- * Internally use only.
+ * Internal use only.
* See parseArguments above and the |argTypes| object below.
*
* Parses the next argument by calling an appropriate parser function, or the
@@ -868,7 +721,7 @@ function at_alias (list, type)
* Parses an integer, stores result in |e[name]|.
*/
CommandManager.prototype.argTypes["int"] =
-function parse_number (e, name)
+function parse_int (e, name)
{
var ary = e.unparsedData.match (/(\d+)(?:\s+(.*))?$/);
if (!ary)
@@ -886,7 +739,7 @@ function parse_number (e, name)
* Stores result in |e[name]|.
*/
CommandManager.prototype.argTypes["word"] =
-function parse_number (e, name)
+function parse_word (e, name)
{
var ary = e.unparsedData.match (/(\S+)(?:\s+(.*))?$/);
if (!ary)
@@ -905,13 +758,13 @@ function parse_number (e, name)
* Stores result in |e[name]|.
*/
CommandManager.prototype.argTypes["state"] =
-function parse_number (e, name)
+function parse_state (e, name)
{
var ary =
e.unparsedData.match (/(true|on|yes|1|false|off|no|0)(?:\s+(.*))?$/i);
if (!ary)
return false;
- if (ary[1].toLowerCase().search(/true|on|yes|1/i) != -1)
+ if (ary[1].search(/true|on|yes|1/i) != -1)
e[name] = true;
else
e[name] = false;
@@ -929,7 +782,7 @@ function parse_number (e, name)
* Stores result in |e[name]|.
*/
CommandManager.prototype.argTypes["toggle"] =
-function parse_number (e, name)
+function parse_toggle (e, name)
{
var ary = e.unparsedData.match
(/(toggle|true|on|yes|1|false|off|no|0)(?:\s+(.*))?$/i);
@@ -954,7 +807,7 @@ function parse_number (e, name)
* Stores result in |e[name]|.
*/
CommandManager.prototype.argTypes["rest"] =
-function parse_number (e, name)
+function parse_rest (e, name)
{
e[name] = e.unparsedData;
e.unparsedData = "";
diff --git a/mozilla/extensions/venkman/resources/content/html-consts.js b/mozilla/extensions/venkman/resources/content/html-consts.js
index 0a988e9d272..283df86d636 100644
--- a/mozilla/extensions/venkman/resources/content/html-consts.js
+++ b/mozilla/extensions/venkman/resources/content/html-consts.js
@@ -92,6 +92,11 @@ function htmlBR(attribs)
return HTML("html:br", attribs, argumentsAsArray(arguments, 1));
}
+function htmlWBR(attribs)
+{
+ return HTML("html:wbr", attribs, argumentsAsArray(arguments, 1));
+}
+
function htmlImg(attribs, src)
{
var img = HTML("html:img", attribs, argumentsAsArray(arguments, 2));
diff --git a/mozilla/extensions/venkman/resources/content/menu-manager.js b/mozilla/extensions/venkman/resources/content/menu-manager.js
new file mode 100644
index 00000000000..4ba1a2ea8fe
--- /dev/null
+++ b/mozilla/extensions/venkman/resources/content/menu-manager.js
@@ -0,0 +1,497 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (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.mozilla.org/MPL/
+ *
+ * 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 The JavaScript Debugger
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation
+ * Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU Public License (the "GPL"), in which case the
+ * provisions of the GPL are applicable instead of those above.
+ * If you wish to allow use of your version of this file only
+ * under the terms of the GPL and not to allow others to use your
+ * version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL. If you do not delete
+ * the provisions above, a recipient may use your version of this
+ * file under either the MPL or the GPL.
+ *
+ * Contributor(s):
+ * Robert Ginda, , original author
+ *
+ */
+
+function MenuManager (commandManager, menuSpecs, contextFunction, commandStr)
+{
+ var menuManager = this;
+
+ this.commandManager = commandManager;
+ this.menuSpecs = menuSpecs;
+ this.contextFunction = contextFunction;
+ this.commandStr = commandStr;
+
+ this.onPopupShowing =
+ function mmgr_onshow (event) { return menuManager.showPopup (event); };
+ this.onPopupHiding =
+ function mmgr_onhide (event) { return menuManager.hidePopup (event); };
+}
+
+/**
+ * Internal use only.
+ *
+ * Registers event handlers on a given menu.
+ */
+MenuManager.prototype.hookPopup =
+function mmgr_hookpop (node)
+{
+ node.addEventListener ("popupshowing", this.onPopupShowing, false);
+ node.addEventListener ("popuphiding", this.onPopupHiding, false);
+}
+
+/**
+ * Internal use only.
+ *
+ * |showPopup| is called from the "onpopupshowing" event of menus
+ * managed by the CommandManager. If a command is disabled, represents a command
+ * that cannot be "satisfied" by the current command context |cx|, or has an
+ * "enabledif" attribute that eval()s to false, then the menuitem is disabled.
+ * In addition "checkedif" and "visibleif" attributes are eval()d and
+ * acted upon accordingly.
+ */
+MenuManager.prototype.showPopup =
+function mmgr_showpop (event)
+{
+ //dd ("showPopup {");
+ /* returns true if the command context has the properties required to
+ * execute the command associated with |menuitem|.
+ */
+ function satisfied()
+ {
+ if (menuitem.hasAttribute("isSeparator"))
+ return true;
+
+ if (!("menuManager" in cx))
+ {
+ dd ("no menuManager in cx");
+ return false;
+ }
+
+ var name = menuitem.getAttribute("commandname");
+ var commandManager = cx.menuManager.commandManager;
+ var commands = commandManager.commands;
+
+ if (!ASSERT (name in commands,
+ "menu contains unknown command '" + name + "'"))
+ {
+ return false;
+ }
+
+ var rv = commandManager.isCommandSatisfied(cx, commands[name]);
+ delete cx.parseError;
+ return rv;
+ };
+
+ /* Convenience function for "enabledif", etc, attributes. */
+ function has (prop)
+ {
+ return (prop in cx);
+ };
+
+ /* evals the attribute named |attr| on the node |node|. */
+ function evalIfAttribute (node, attr)
+ {
+ var ex;
+ var expr = node.getAttribute(attr);
+ if (!expr)
+ return true;
+
+ expr = expr.replace (/\Wand\W/gi, " && ");
+
+ try
+ {
+ return eval("(" + expr + ")");
+ }
+ catch (ex)
+ {
+ dd ("caught exception evaling '" + node.getAttribute("id") + "'.'" +
+ attr + "'\n" + ex);
+ }
+ return true;
+ };
+
+ var cx;
+ var popup = event.originalTarget;
+ var menuitem = popup.firstChild;
+
+
+ /* If the host provided a |contextFunction|, use it now. Remember the
+ * return result as this.cx for use if something from this menu is actually
+ * dispatched. this.cx is deleted in |hidePopup|. */
+ if (typeof this.contextFunction == "function")
+ {
+ cx = this.cx = this.contextFunction (popup.getAttribute("menuName"),
+ event);
+ }
+ else
+ {
+ cx = this.cx = { menuManager: this, originalEvent: event };
+ }
+
+ do
+ {
+ /* should it be visible? */
+ if (menuitem.hasAttribute("visibleif"))
+ {
+ if (evalIfAttribute(menuitem, "visibleif"))
+ menuitem.removeAttribute ("hidden");
+ else
+ {
+ menuitem.setAttribute ("hidden", "true");
+ continue;
+ }
+ }
+
+ /* ok, it's visible, maybe it should be disabled? */
+ if (satisfied())
+ {
+ if (menuitem.hasAttribute("enabledif"))
+ {
+ if (evalIfAttribute(menuitem, "enabledif"))
+ menuitem.removeAttribute ("disabled");
+ else
+ menuitem.setAttribute ("disabled", "true");
+ }
+ else
+ menuitem.removeAttribute ("disabled");
+ }
+ else
+ {
+ menuitem.setAttribute ("disabled", "true");
+ }
+
+ /* should it have a check? */
+ if (menuitem.hasAttribute("checkedif"))
+ {
+ if (evalIfAttribute(menuitem, "checkedif"))
+ menuitem.setAttribute ("checked", "true");
+ else
+ menuitem.removeAttribute ("checked");
+ }
+
+ } while ((menuitem = menuitem.nextSibling));
+
+ //dd ("}");
+
+ return true;
+}
+
+/**
+ * Internal use only.
+ *
+ * |hidePopup| is called from the "onpopuphiding" event of menus
+ * managed by the CommandManager. Nothing to do here anymore.
+ * We used to just clean up this.cx, but that's a problem for nested
+ * menus.
+ */
+MenuManager.prototype.hidePopup =
+function mmgr_hidepop (id)
+{
+ return true;
+}
+
+/**
+ * Appends a sub-menu to an existing menu.
+ * @param parentNode DOM Node to insert into
+ * @param beforeNode DOM Node already contained by parentNode, to insert before
+ * @param id ID of the sub-menu to add.
+ * @param label Text to use for this sub-menu. The & character can be
+ * used to indicate the accesskey.
+ * @param attribs Object containing CSS attributes to set on the element.
+ */
+MenuManager.prototype.appendSubMenu =
+function mmgr_addsmenu (parentNode, beforeNode, menuName, domId, label, attribs)
+{
+ var document = parentNode.ownerDocument;
+
+ /* sometimes the menu is already there, for overlay purposes. */
+ var menu = document.getElementById(domId);
+
+ if (!menu)
+ {
+ menu = document.createElement ("menu");
+ menu.setAttribute ("id", domId);
+ parentNode.insertBefore(menu, beforeNode);
+ }
+
+ var menupopup = menu.firstChild;
+
+ if (!menupopup)
+ {
+ menupopup = document.createElement ("menupopup");
+ menupopup.setAttribute ("id", domId + "-popup");
+ menu.appendChild(menupopup);
+ menupopup = menu.firstChild;
+ }
+
+ menupopup.setAttribute ("menuName", menuName);
+
+ menu.setAttribute ("accesskey", getAccessKey(label));
+ menu.setAttribute ("label", label.replace("&", ""));
+ menu.setAttribute ("isSeparator", true);
+
+ if (typeof attribs == "object")
+ {
+ for (var p in attribs)
+ menu.setAttribute (p, attribs[p]);
+ }
+
+ this.hookPopup (menupopup);
+
+ return menupopup;
+}
+
+/**
+ * Appends a popup to an existing popupset.
+ * @param parentNode DOM Node to insert into
+ * @param beforeNode DOM Node already contained by parentNode, to insert before
+ * @param id ID of the popup to add.
+ * @param label Text to use for this popup. Popup menus don't normally have
+ * labels, but we set a "label" attribute anyway, in case
+ * the host wants it for some reason. Any "&" characters will
+ * be stripped.
+ * @param attribs Object containing CSS attributes to set on the element.
+ */
+MenuManager.prototype.appendPopupMenu =
+function mmgr_addpmenu (parentNode, beforeNode, menuName, id, label, attribs)
+{
+ var document = parentNode.ownerDocument;
+ var popup = document.createElement ("popup");
+ popup.setAttribute ("id", id);
+ if (label)
+ popup.setAttribute ("label", label.replace("&", ""));
+ if (typeof attribs == "object")
+ {
+ for (var p in attribs)
+ popup.setAttribute (p, attribs[p]);
+ }
+
+ popup.setAttribute ("menuName", menuName);
+
+ parentNode.insertBefore(popup, beforeNode);
+ this.hookPopup (popup);
+
+ return popup;
+}
+
+/**
+ * Appends a menuitem to an existing menu or popup.
+ * @param parentNode DOM Node to insert into
+ * @param beforeNode DOM Node already contained by parentNode, to insert before
+ * @param command A reference to the CommandRecord this menu item will represent.
+ * @param attribs Object containing CSS attributes to set on the element.
+ */
+MenuManager.prototype.appendMenuItem =
+function mmgr_addmenu (parentNode, beforeNode, commandName, attribs)
+{
+ var menuManager = this;
+
+ var document = parentNode.ownerDocument;
+ if (commandName == "-")
+ return this.appendMenuSeparator(parentNode, beforeNode, attribs);
+
+ var parentId = parentNode.getAttribute("id");
+
+ if (!ASSERT(commandName in this.commandManager.commands,
+ "unknown command " + commandName + " targeted for " +
+ parentId))
+ {
+ return null;
+ }
+
+ var command = this.commandManager.commands[commandName];
+ var menuitem = document.createElement ("menuitem");
+ menuitem.setAttribute ("id", parentId + ":" + commandName);
+ menuitem.setAttribute ("commandname", command.name);
+ menuitem.setAttribute ("key", "key:" + command.name);
+ menuitem.setAttribute ("accesskey", getAccessKey(command.label));
+ menuitem.setAttribute ("label", command.label.replace("&", ""));
+ menuitem.setAttribute ("oncommand", this.commandStr);
+
+ if (typeof attribs == "object")
+ {
+ for (var p in attribs)
+ menuitem.setAttribute (p, attribs[p]);
+ }
+
+ command.uiElements.push(menuitem);
+ parentNode.insertBefore (menuitem, beforeNode);
+
+ return menuitem;
+}
+
+/**
+ * Appends a menuseparator to an existing menu or popup.
+ * @param parentNode DOM Node to insert into
+ * @param beforeNode DOM Node already contained by parentNode, to insert before
+ * @param attribs Object containing CSS attributes to set on the element.
+ */
+MenuManager.prototype.appendMenuSeparator =
+function mmgr_addsep (parentNode, beforeNode, attribs)
+{
+ var document = parentNode.ownerDocument;
+ var menuitem = document.createElement ("menuseparator");
+ menuitem.setAttribute ("isSeparator", true);
+ if (typeof attribs == "object")
+ {
+ for (var p in attribs)
+ menuitem.setAttribute (p, attribs[p]);
+ }
+ parentNode.insertBefore (menuitem, beforeNode);
+
+ return menuitem;
+}
+
+/**
+ * Appends a toolbaritem to an existing box element.
+ * @param parentNode DOM Node to insert into
+ * @param beforeNode DOM Node already contained by parentNode, to insert before
+ * @param command A reference to the CommandRecord this toolbaritem will
+ * represent.
+ * @param attribs Object containing CSS attributes to set on the element.
+ */
+MenuManager.prototype.appendToolbarItem =
+function mmgr_addtb (parentNode, beforeNode, commandName, attribs)
+{
+ if (commandName == "-")
+ return this.appendToolbarSeparator(parentNode, beforeNode, attribs);
+
+ var parentId = parentNode.getAttribute("id");
+
+ if (!ASSERT(commandName in this.commandManager.commands,
+ "unknown command " + commandName + " targeted for " +
+ parentId))
+ {
+ return null;
+ }
+
+ var command = this.commandManager.commands[commandName];
+ var document = parentNode.ownerDocument;
+ var tbitem = document.createElement ("toolbarbutton");
+
+ var id = parentNode.getAttribute("id") + ":" + commandName;
+ tbitem.setAttribute ("id", id);
+ tbitem.setAttribute ("class", "toolbarbutton-1");
+ tbitem.setAttribute ("label", command.label.replace("&", ""));
+ tbitem.setAttribute ("oncommand",
+ "dispatch('" + commandName + "');");
+ if (typeof attribs == "object")
+ {
+ for (var p in attribs)
+ tbitem.setAttribute (p, attribs[p]);
+ }
+
+ command.uiElements.push(tbitem);
+ parentNode.insertBefore (tbitem, beforeNode);
+
+ return tbitem;
+}
+
+/**
+ * Appends a toolbarseparator to an existing box.
+ * @param parentNode DOM Node to insert into
+ * @param beforeNode DOM Node already contained by parentNode, to insert before
+ * @param attribs Object containing CSS attributes to set on the element.
+ */
+MenuManager.prototype.appendToolbarSeparator =
+function mmgr_addmenu (parentNode, beforeNode, attribs)
+{
+ var document = parentNode.ownerDocument;
+ var tbitem = document.createElement ("toolbarseparator");
+ tbitem.setAttribute ("isSeparator", true);
+ if (typeof attribs == "object")
+ {
+ for (var p in attribs)
+ tbitem.setAttribute (p, attribs[p]);
+ }
+ parentNode.appendChild (tbitem);
+
+ return tbitem;
+}
+
+/**
+ * Creates menu DOM nodes from a menu specification.
+ * @param parentNode DOM Node to insert into
+ * @param beforeNode DOM Node already contained by parentNode, to insert before
+ * @param menuSpec array of menu items
+ */
+MenuManager.prototype.createMenu =
+function mmgr_newmenu (parentNode, beforeNode, menuName, domId, attribs)
+{
+ if (typeof domId == "undefined")
+ domId = menuName;
+
+ if (!ASSERT(menuName in this.menuSpecs, "unknown menu name " + menuName))
+ return null;
+
+ var menuSpec = this.menuSpecs[menuName];
+
+ var subMenu = this.appendSubMenu (parentNode, beforeNode, menuName, domId,
+ menuSpec.label, attribs);
+
+ this.createMenuItems (subMenu, null, menuSpec.items);
+ return subMenu;
+}
+
+MenuManager.prototype.createMenuItems =
+function mmgr_newitems (parentNode, beforeNode, menuItems)
+{
+ function itemAttribs()
+ {
+ return (1 in menuItems[i]) ? menuItems[i][1] : null;
+ };
+
+ var parentId = parentNode.getAttribute("id");
+
+ for (var i in menuItems)
+ {
+ var itemName = menuItems[i][0];
+ if (itemName[0] == ">")
+ {
+ itemName = itemName.substr(1);
+ if (!ASSERT(itemName in this.menuSpecs,
+ "unknown submenu " + itemName + " referenced in " +
+ parentId))
+ {
+ continue;
+ }
+ this.createMenu (parentNode, beforeNode, itemName,
+ parentId + ":" + itemName, itemAttribs());
+ }
+ else if (itemName in this.commandManager.commands)
+ {
+ this.appendMenuItem (parentNode, beforeNode, itemName,
+ itemAttribs());
+ }
+ else if (itemName == "-")
+ {
+ this.appendMenuSeparator (parentNode, beforeNode, itemAttribs());
+ }
+ else
+ {
+ dd ("unknown command " + itemName + " referenced in " + parentId);
+ }
+ }
+
+}
diff --git a/mozilla/extensions/venkman/resources/content/profile.csv.tpl b/mozilla/extensions/venkman/resources/content/profile.csv.tpl
new file mode 100644
index 00000000000..b21f081ff97
--- /dev/null
+++ b/mozilla/extensions/venkman/resources/content/profile.csv.tpl
@@ -0,0 +1,4 @@
+# full-url, file-name, function-name, start-line, end-line, call-count, recurse-depth, total-time, min-time, max-time, avg-time
+@-item-start
+$full-url, $file-name, $function-name, $start-line, $end-line, $call-count, $recurse-depth, $total-time, $min-time, $max-time, $avg-time
+@-item-end
diff --git a/mozilla/extensions/venkman/resources/content/profile.html.tpl b/mozilla/extensions/venkman/resources/content/profile.html.tpl
index fbfd811f252..6e6c993a020 100644
--- a/mozilla/extensions/venkman/resources/content/profile.html.tpl
+++ b/mozilla/extensions/venkman/resources/content/profile.html.tpl
@@ -70,14 +70,16 @@
$user-agent
JavaScript Debugger Version:
$venkman-agent
+ Sorted By:
+ $sort-key
-
+@-section-start
$section-link
-
+@-range-start
$range-min - $range-max ms
@@ -85,7 +87,7 @@
Next File |
Previous Range |
Next Range ]
-
+@-item-start
@@ -103,12 +105,12 @@
width="$item-above-pct%">
-
+@-item-end
-
+@-range-end
-
+@-section-end
No job is too big, no fee is too big.