From d4f9f9909cdf0a6086da6d7f54a3e618e75ad3ce Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Wed, 9 Feb 2011 08:11:25 -0500 Subject: [PATCH] Move some things around. Fix bug in last commit (I've already forgotten which). --HG-- branch : groups --- common/content/browser.js | 266 +++++++++++++++------- common/content/buffer.js | 426 +++++++++++++---------------------- common/content/hints.js | 2 - common/content/statusline.js | 3 +- common/content/tabs.js | 4 + 5 files changed, 346 insertions(+), 355 deletions(-) diff --git a/common/content/browser.js b/common/content/browser.js index ac647fee..2fe98736 100644 --- a/common/content/browser.js +++ b/common/content/browser.js @@ -11,63 +11,204 @@ /** * @instance browser */ -var Browser = Module("browser", { -}, { - climbUrlPath: function (count) { - let url = buffer.documentURI.clone(); - dactyl.assert(url instanceof Ci.nsIURL); - - while (count-- && url.path != "/") - url.path = url.path.replace(/[^\/]+\/*$/, ""); - - dactyl.assert(!url.equals(buffer.documentURI)); - dactyl.open(url.spec); +var Browser = Module("browser", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { + init: function init() { + this.cleanupProgressListener = util.overlayObject(window.XULBrowserWindow, + this.progressListener); + util.addObserver(this); }, - incrementURL: function (count) { - let matches = buffer.uri.spec.match(/(.*?)(\d+)(\D*)$/); - dactyl.assert(matches); - let oldNum = matches[2]; + cleanup: function () { + this.cleanupProgressListener(); + this.observe.unregister(); + }, - // disallow negative numbers as trailing numbers are often proceeded by hyphens - let newNum = String(Math.max(parseInt(oldNum, 10) + count, 0)); - if (/^0/.test(oldNum)) - while (newNum.length < oldNum.length) - newNum = "0" + newNum; + observers: { + "chrome-document-global-created": function (win, uri) { this.observe(win, "content-document-global-created", uri); }, + "content-document-global-created": function (win, uri) { + let top = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShellTreeItem).rootTreeItem + .QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow); - matches[2] = newNum; - dactyl.open(matches.slice(1).join("")); + if (top == window) + this._triggerLoadAutocmd("PageLoadPre", win.document, win.location.href != "null" ? window.location.href : uri); + } + }, + + _triggerLoadAutocmd: function _triggerLoadAutocmd(name, doc, uri) { + if (!(uri || doc.location)) + return; + + uri = isObject(uri) ? uri : util.newURI(uri || doc.location.href); + let args = { + url: { toString: function () uri.spec, valueOf: function () uri }, + title: doc.title + }; + + if (dactyl.has("tabs")) { + args.tab = tabs.getContentIndex(doc) + 1; + args.doc = { + valueOf: function () doc, + toString: function () "tabs.getTab(" + (args.tab - 1) + ").linkedBrowser.contentDocument" + }; + } + + autocommands.trigger(name, args); + }, + + events: { + DOMContentLoaded: function onDOMContentLoaded(event) { + util.dump("DOMContentLoaded"); + let doc = event.originalTarget; + if (doc instanceof HTMLDocument) + this._triggerLoadAutocmd("DOMLoad", doc); + }, + + // TODO: see what can be moved to onDOMContentLoaded() + // event listener which is is called on each page load, even if the + // page is loaded in a background tab + load: function onLoad(event) { + util.dump("onLoad"); + let doc = event.originalTarget; + if (doc instanceof Document) + dactyl.initDocument(doc); + + if (doc instanceof HTMLDocument) { + if (doc.defaultView.frameElement) { + // document is part of a frameset + + // hacky way to get rid of "Transferring data from ..." on sites with frames + // when you click on a link inside a frameset, because asyncUpdateUI + // is not triggered there (Gecko bug?) + this.timeout(function () { statusline.updateUrl(); }, 10); + } + else { + // code which should happen for all (also background) newly loaded tabs goes here: + if (doc != config.browser.contentDocument) + dactyl.echomsg({ domains: [util.getHost(doc.location)], message: "Background tab loaded: " + (doc.title || doc.location.href) }, 3); + + this._triggerLoadAutocmd("PageLoad", doc); + } + } + } + }, + + /** + * @property {Object} The document loading progress listener. + */ + progressListener: { + // XXX: function may later be needed to detect a canceled synchronous openURL() + onStateChange: util.wrapCallback(function onStateChange(webProgress, request, flags, status) { + onStateChange.superapply(this, arguments); + // STATE_IS_DOCUMENT | STATE_IS_WINDOW is important, because we also + // receive statechange events for loading images and other parts of the web page + if (flags & (Ci.nsIWebProgressListener.STATE_IS_DOCUMENT | Ci.nsIWebProgressListener.STATE_IS_WINDOW)) { + // This fires when the load event is initiated + // only thrown for the current tab, not when another tab changes + if (flags & Ci.nsIWebProgressListener.STATE_START) { + statusline.progress = 0; + } + else if (flags & Ci.nsIWebProgressListener.STATE_STOP) { + // Workaround for bugs 591425 and 606877, dactyl bug #81 + config.browser.mCurrentBrowser.collapsed = false; + if (!dactyl.focusedElement || dactyl.focusedElement === document.documentElement) + dactyl.focusContent(); + statusline.updateUrl(); + } + } + }), + // for notifying the user about secure web pages + onSecurityChange: util.wrapCallback(function onSecurityChange(webProgress, request, state) { + onSecurityChange.superapply(this, arguments); + if (state & Ci.nsIWebProgressListener.STATE_IS_BROKEN) + statusline.security = "broken"; + else if (state & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL) + statusline.security = "extended"; + else if (state & Ci.nsIWebProgressListener.STATE_SECURE_HIGH) + statusline.security = "secure"; + else // if (state & Ci.nsIWebProgressListener.STATE_IS_INSECURE) + statusline.security = "insecure"; + if (webProgress && webProgress.DOMWindow) + webProgress.DOMWindow.document.dactylSecurity = statusline.security; + }), + onStatusChange: util.wrapCallback(function onStatusChange(webProgress, request, status, message) { + onStatusChange.superapply(this, arguments); + statusline.updateUrl(message); + }), + onProgressChange: util.wrapCallback(function onProgressChange(webProgress, request, curSelfProgress, maxSelfProgress, curTotalProgress, maxTotalProgress) { + onProgressChange.superapply(this, arguments); + if (webProgress && webProgress.DOMWindow) + webProgress.DOMWindow.dactylProgress = curTotalProgress / maxTotalProgress; + statusline.progress = curTotalProgress / maxTotalProgress; + }), + // happens when the users switches tabs + onLocationChange: util.wrapCallback(function onLocationChange(webProgress, request, uri) { + onLocationChange.superapply(this, arguments); + + delete contexts.groups; + + statusline.updateUrl(); + statusline.progress = ""; + + let win = webProgress.DOMWindow; + if (win && uri) { + statusline.progress = win.dactylProgress; + + let oldURI = win.document.dactylURI; + if (win.document.dactylLoadIdx === webProgress.loadedTransIndex + || !oldURI || uri.spec.replace(/#.*/, "") !== oldURI.replace(/#.*/, "")) + for (let frame in values(buffer.allFrames(win))) + frame.document.dactylFocusAllowed = false; + win.document.dactylURI = uri.spec; + win.document.dactylLoadIdx = webProgress.loadedTransIndex; + } + + // Workaround for bugs 591425 and 606877, dactyl bug #81 + let collapse = uri && uri.scheme === "dactyl" && webProgress.isLoadingDocument; + if (collapse) + dactyl.focus(document.documentElement); + config.browser.mCurrentBrowser.collapsed = collapse; + + util.timeout(function () { + browser._triggerLoadAutocmd("LocationChange", + (win || content).document, + uri); + }); + + // if this is not delayed we get the position of the old buffer + util.timeout(function () { + statusline.updateBufferPosition(); + statusline.updateZoomLevel(); + if (loaded.commandline) + commandline.clear(); + }, 500); + }), + // called at the very end of a page load + asyncUpdateUI: util.wrapCallback(function asyncUpdateUI() { + asyncUpdateUI.superapply(this, arguments); + util.timeout(function () { statusline.updateUrl(); }, 100); + }), + setOverLink: util.wrapCallback(function setOverLink(link, b) { + setOverLink.superapply(this, arguments); + switch (options["showstatuslinks"]) { + case "status": + statusline.updateUrl(link ? "Link: " + link : null); + break; + case "command": + if (link) + dactyl.echo("Link: " + link, commandline.DISALLOW_MULTILINE); + else + commandline.clear(); + break; + } + }), } }, { - options: function () { - options.add(["encoding", "enc"], - "The current buffer's character encoding", - "string", "UTF-8", - { - scope: Option.SCOPE_LOCAL, - getter: function () config.browser.docShell.QueryInterface(Ci.nsIDocCharset).charset, - setter: function (val) { - if (options["encoding"] == val) - return val; - - // Stolen from browser.jar/content/browser/browser.js, more or less. - try { - config.browser.docShell.QueryInterface(Ci.nsIDocCharset).charset = val; - PlacesUtils.history.setCharsetForURI(getWebNavigation().currentURI, val); - getWebNavigation().reload(Ci.nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE); - } - catch (e) { dactyl.reportError(e); } - return null; - }, - completer: function (context) completion.charset(context) - }); +}, { + events: function () { + events.listen(config.browser, browser, "events", true); }, - mappings: function () { - mappings.add([modes.NORMAL], - ["y", ""], "Yank current location to the clipboard", - function () { dactyl.clipboardWrite(buffer.uri.spec, true); }); - // opening websites mappings.add([modes.NORMAL], ["o"], "Open one or more URLs", @@ -93,16 +234,6 @@ var Browser = Module("browser", { "Open one or more URLs in a new window, based on current location", function () { CommandExMode().open("winopen " + buffer.uri.spec); }); - mappings.add([modes.NORMAL], - [""], "Increment last number in URL", - function (args) { Browser.incrementURL(Math.max(args.count, 1)); }, - { count: true }); - - mappings.add([modes.NORMAL], - [""], "Decrement last number in URL", - function (args) { Browser.incrementURL(-Math.max(args.count, 1)); }, - { count: true }); - mappings.add([modes.NORMAL], ["~"], "Open home directory", function () { dactyl.open("~"); }); @@ -118,29 +249,12 @@ var Browser = Module("browser", { dactyl.open(homepages, { from: "homepage", where: dactyl.NEW_TAB }); }); - mappings.add([modes.NORMAL], ["gu"], - "Go to parent directory", - function (args) { Browser.climbUrlPath(Math.max(args.count, 1)); }, - { count: true }); - - mappings.add([modes.NORMAL], ["gU"], - "Go to the root of the website", - function () { Browser.climbUrlPath(-1); }); - mappings.add(modes.all, [""], "Redraw the screen", function () { ex.redraw(); }); }, commands: function () { - commands.add(["old-downl[oads]", "old-dl"], - "Show progress of current downloads", - function () { - dactyl.open("chrome://mozapps/content/downloads/downloads.xul", - { from: "downloads"}); - }, - { argCount: "0" }); - commands.add(["o[pen]"], "Open one or more URLs in the current tab", function (args) { dactyl.open(args[0] || "about:blank"); }, diff --git a/common/content/buffer.js b/common/content/buffer.js index 5466c445..e5d93668 100644 --- a/common/content/buffer.js +++ b/common/content/buffer.js @@ -14,7 +14,7 @@ * files. * @instance buffer */ -var Buffer = Module("buffer", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { +var Buffer = Module("buffer", { init: function () { this.evaluateXPath = util.evaluateXPath; this.pageInfo = {}; @@ -145,77 +145,6 @@ var Buffer = Module("buffer", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { let elem = event.originalTarget; buffer.viewSource([elem.getAttribute("href"), Number(elem.getAttribute("line"))]); }; - - this.cleanupProgressListener = util.overlayObject(window.XULBrowserWindow, - this.progressListener); - - if (dactyl.has("tabs")) - for (let tab in values(tabs.allTabs)) - if (tab.linkedBrowser.contentDocument.readyState === "complete") - dactyl.initDocument(tab.linkedBrowser.contentDocument); - util.addObserver(this); - }, - - cleanup: function () { - this.cleanupProgressListener(); - this.observe.unregister(); - }, - - getDefaultNames: function getDefaultNames(node) { - let url = node.href || node.src || node.documentURI; - let currExt = url.replace(/^.*?(?:\.([a-z0-9]+))?$/i, "$1").toLowerCase(); - - if (isinstance(node, [Document, HTMLImageElement])) { - let type = node.contentType || node.QueryInterface(Ci.nsIImageLoadingContent) - .getRequest(0).mimeType; - - if (type === "text/plain") - var ext = "." + (currExt || "txt"); - else - ext = "." + services.mime.getPrimaryExtension(type, currExt); - } - else if (currExt) - ext = "." + currExt; - else - ext = ""; - let re = ext ? RegExp("(\\." + currExt + ")?$", "i") : /$/; - - var names = []; - if (node.title) - names.push([node.title, "Page Name"]); - - if (node.alt) - names.push([node.alt, "Alternate Text"]); - - if (!isinstance(node, Document) && node.textContent) - names.push([node.textContent, "Link Text"]); - - names.push([decodeURIComponent(url.replace(/.*?([^\/]*)\/*$/, "$1")), "File Name"]); - - return names.filter(function ([leaf, title]) leaf) - .map(function ([leaf, title]) [leaf.replace(util.OS.illegalCharacters, encodeURIComponent) - .replace(re, ext), title]); - }, - - _triggerLoadAutocmd: function _triggerLoadAutocmd(name, doc, uri) { - if (!(uri || doc.location)) - return; - - uri = isObject(uri) ? uri : util.newURI(uri || doc.location.href); - let args = { - url: { toString: function () uri.spec, valueOf: function () uri }, - title: doc.title - }; - - if (dactyl.has("tabs")) { - args.tab = tabs.getContentIndex(doc) + 1; - args.doc = { - valueOf: function () doc, - toString: function () "tabs.getTab(" + (args.tab - 1) + ").linkedBrowser.contentDocument" - }; - } - - autocommands.trigger(name, args); }, // called when the active document is scrolled @@ -224,162 +153,6 @@ var Buffer = Module("buffer", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { commandline.clear(); }, - observers: { - "chrome-document-global-created": function (win, uri) { this.observe(win, "content-document-global-created", uri); }, - "content-document-global-created": function (win, uri) { - let top = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShellTreeItem).rootTreeItem - .QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow); - - if (top == window) - this._triggerLoadAutocmd("PageLoadPre", win.document, win.location.href != "null" ? window.location.href : uri); - } - }, - - onDOMContentLoaded: function onDOMContentLoaded(event) { - let doc = event.originalTarget; - if (doc instanceof HTMLDocument) - this._triggerLoadAutocmd("DOMLoad", doc); - }, - - // TODO: see what can be moved to onDOMContentLoaded() - // event listener which is is called on each page load, even if the - // page is loaded in a background tab - onPageLoad: function onPageLoad(event) { - let doc = event.originalTarget; - if (doc instanceof Document) - dactyl.initDocument(doc); - - if (doc instanceof HTMLDocument) { - if (doc.defaultView.frameElement) { - // document is part of a frameset - - // hacky way to get rid of "Transferring data from ..." on sites with frames - // when you click on a link inside a frameset, because asyncUpdateUI - // is not triggered there (Gecko bug?) - this.timeout(function () { statusline.updateUrl(); }, 10); - } - else { - // code which should happen for all (also background) newly loaded tabs goes here: - if (doc != config.browser.contentDocument) - dactyl.echomsg({ domains: [util.getHost(doc.location)], message: "Background tab loaded: " + (doc.title || doc.location.href) }, 3); - - this._triggerLoadAutocmd("PageLoad", doc); - } - } - }, - - /** - * @property {Object} The document loading progress listener. - */ - progressListener: { - // XXX: function may later be needed to detect a canceled synchronous openURL() - onStateChange: util.wrapCallback(function onStateChange(webProgress, request, flags, status) { - onStateChange.superapply(this, arguments); - // STATE_IS_DOCUMENT | STATE_IS_WINDOW is important, because we also - // receive statechange events for loading images and other parts of the web page - if (flags & (Ci.nsIWebProgressListener.STATE_IS_DOCUMENT | Ci.nsIWebProgressListener.STATE_IS_WINDOW)) { - // This fires when the load event is initiated - // only thrown for the current tab, not when another tab changes - if (flags & Ci.nsIWebProgressListener.STATE_START) { - statusline.progress = 0; - } - else if (flags & Ci.nsIWebProgressListener.STATE_STOP) { - // Workaround for bugs 591425 and 606877, dactyl bug #81 - config.browser.mCurrentBrowser.collapsed = false; - if (!dactyl.focusedElement || dactyl.focusedElement === document.documentElement) - dactyl.focusContent(); - statusline.updateUrl(); - } - } - }), - // for notifying the user about secure web pages - onSecurityChange: util.wrapCallback(function onSecurityChange(webProgress, request, state) { - onSecurityChange.superapply(this, arguments); - if (state & Ci.nsIWebProgressListener.STATE_IS_BROKEN) - statusline.security = "broken"; - else if (state & Ci.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL) - statusline.security = "extended"; - else if (state & Ci.nsIWebProgressListener.STATE_SECURE_HIGH) - statusline.security = "secure"; - else // if (state & Ci.nsIWebProgressListener.STATE_IS_INSECURE) - statusline.security = "insecure"; - if (webProgress && webProgress.DOMWindow) - webProgress.DOMWindow.document.dactylSecurity = statusline.security; - }), - onStatusChange: util.wrapCallback(function onStatusChange(webProgress, request, status, message) { - onStatusChange.superapply(this, arguments); - statusline.updateUrl(message); - }), - onProgressChange: util.wrapCallback(function onProgressChange(webProgress, request, curSelfProgress, maxSelfProgress, curTotalProgress, maxTotalProgress) { - onProgressChange.superapply(this, arguments); - if (webProgress && webProgress.DOMWindow) - webProgress.DOMWindow.dactylProgress = curTotalProgress / maxTotalProgress; - statusline.progress = curTotalProgress / maxTotalProgress; - }), - // happens when the users switches tabs - onLocationChange: util.wrapCallback(function onLocationChange(webProgress, request, uri) { - onLocationChange.superapply(this, arguments); - - delete contexts.groups; - - statusline.updateUrl(); - statusline.progress = ""; - - let win = webProgress.DOMWindow; - if (win && uri) { - statusline.progress = win.dactylProgress; - - let oldURI = win.document.dactylURI; - if (win.document.dactylLoadIdx === webProgress.loadedTransIndex - || !oldURI || uri.spec.replace(/#.*/, "") !== oldURI.replace(/#.*/, "")) - for (let frame in values(buffer.allFrames(win))) - frame.document.dactylFocusAllowed = false; - win.document.dactylURI = uri.spec; - win.document.dactylLoadIdx = webProgress.loadedTransIndex; - } - - // Workaround for bugs 591425 and 606877, dactyl bug #81 - let collapse = uri && uri.scheme === "dactyl" && webProgress.isLoadingDocument; - if (collapse) - dactyl.focus(document.documentElement); - config.browser.mCurrentBrowser.collapsed = collapse; - - util.timeout(function () { - buffer._triggerLoadAutocmd("LocationChange", - (win || content).document, - uri); - }); - - // if this is not delayed we get the position of the old buffer - util.timeout(function () { - statusline.updateBufferPosition(); - statusline.updateZoomLevel(); - if (loaded.commandline) - commandline.clear(); - }, 500); - }), - // called at the very end of a page load - asyncUpdateUI: util.wrapCallback(function asyncUpdateUI() { - asyncUpdateUI.superapply(this, arguments); - util.timeout(function () { statusline.updateUrl(); }, 100); - }), - setOverLink: util.wrapCallback(function setOverLink(link, b) { - setOverLink.superapply(this, arguments); - switch (options["showstatuslinks"]) { - case "status": - statusline.updateUrl(link ? "Link: " + link : null); - break; - case "command": - if (link) - dactyl.echo("Link: " + link, commandline.DISALLOW_MULTILINE); - else - commandline.clear(); - break; - } - }), - }, - /** * @property {Array} The alternative style sheets for the current * buffer. Only returns style sheets for the 'screen' media type. @@ -392,6 +165,32 @@ var Buffer = Module("buffer", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { ); }, + climbUrlPath: function (count) { + let url = buffer.documentURI.clone(); + dactyl.assert(url instanceof Ci.nsIURL); + + while (count-- && url.path != "/") + url.path = url.path.replace(/[^\/]+\/*$/, ""); + + dactyl.assert(!url.equals(buffer.documentURI)); + dactyl.open(url.spec); + }, + + incrementURL: function (count) { + let matches = buffer.uri.spec.match(/(.*?)(\d+)(\D*)$/); + dactyl.assert(matches); + let oldNum = matches[2]; + + // disallow negative numbers as trailing numbers are often proceeded by hyphens + let newNum = String(Math.max(parseInt(oldNum, 10) + count, 0)); + if (/^0/.test(oldNum)) + while (newNum.length < oldNum.length) + newNum = "0" + newNum; + + matches[2] = newNum; + dactyl.open(matches.slice(1).join("")); + }, + /** * @property {Object} A map of page info sections to their * content generating functions. @@ -775,7 +574,7 @@ var Buffer = Module("buffer", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { onSubmit: function (path) { let file = io.File(path); if (file.exists() && file.isDirectory()) - file.append(buffer.getDefaultNames(elem)[0][0]); + file.append(Buffer.getDefaultNames(elem)[0][0]); try { if (!file.exists()) @@ -1245,6 +1044,42 @@ var Buffer = Module("buffer", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { setZoom: deprecated("buffer.setZoom", function setZoom() buffer.setZoom.apply(buffer, arguments)), bumpZoomLevel: deprecated("buffer.bumpZoomLevel", function bumpZoomLevel() buffer.bumpZoomLevel.apply(buffer, arguments)), + getDefaultNames: function getDefaultNames(node) { + let url = node.href || node.src || node.documentURI; + let currExt = url.replace(/^.*?(?:\.([a-z0-9]+))?$/i, "$1").toLowerCase(); + + if (isinstance(node, [Document, HTMLImageElement])) { + let type = node.contentType || node.QueryInterface(Ci.nsIImageLoadingContent) + .getRequest(0).mimeType; + + if (type === "text/plain") + var ext = "." + (currExt || "txt"); + else + ext = "." + services.mime.getPrimaryExtension(type, currExt); + } + else if (currExt) + ext = "." + currExt; + else + ext = ""; + let re = ext ? RegExp("(\\." + currExt + ")?$", "i") : /$/; + + var names = []; + if (node.title) + names.push([node.title, "Page Name"]); + + if (node.alt) + names.push([node.alt, "Alternate Text"]); + + if (!isinstance(node, Document) && node.textContent) + names.push([node.textContent, "Link Text"]); + + names.push([decodeURIComponent(url.replace(/.*?([^\/]*)\/*$/, "$1")), "File Name"]); + + return names.filter(function ([leaf, title]) leaf) + .map(function ([leaf, title]) [leaf.replace(util.OS.illegalCharacters, encodeURIComponent) + .replace(re, ext), title]); + }, + findScrollableWindow: deprecated("buffer.findScrollableWindow", function findScrollableWindow() buffer.findScrollableWindow.apply(buffer, arguments)), findScrollable: deprecated("buffer.findScrollable", function findScrollable() buffer.findScrollable.apply(buffer, arguments)), @@ -1498,7 +1333,7 @@ var Buffer = Module("buffer", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { let file = io.File(filename.replace(RegExp(File.PATH_SEP + "*$"), "")); if (filename.substr(-1) === File.PATH_SEP || file.exists() && file.isDirectory()) - file.append(buffer.getDefaultNames(doc)[0][0]); + file.append(Buffer.getDefaultNames(doc)[0][0]); dactyl.assert(args.bang || !file.exists(), "E13: File exists (add ! to override)"); @@ -1650,19 +1485,38 @@ var Buffer = Module("buffer", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { completion.savePage = function savePage(context, node) { context.fork("generated", context.filter.replace(/[^/]*$/, "").length, this, function (context) { - context.completions = buffer.getDefaultNames(node); + context.completions = Buffer.getDefaultNames(node); }); }; }, events: function () { - events.listen(config.browser, "DOMContentLoaded", buffer.closure.onDOMContentLoaded, true); - events.listen(config.browser, "load", buffer.closure.onPageLoad, true); events.listen(config.browser, "scroll", buffer.closure._updateBufferPosition, false); }, mappings: function () { - var myModes = config.browserModes; + mappings.add([modes.NORMAL], + ["y", ""], "Yank current location to the clipboard", + function () { dactyl.clipboardWrite(buffer.uri.spec, true); }); - mappings.add(myModes, [".", ""], + mappings.add([modes.NORMAL], + [""], "Increment last number in URL", + function (args) { buffer.incrementURL(Math.max(args.count, 1)); }, + { count: true }); + + mappings.add([modes.NORMAL], + [""], "Decrement last number in URL", + function (args) { buffer.incrementURL(-Math.max(args.count, 1)); }, + { count: true }); + + mappings.add([modes.NORMAL], ["gu"], + "Go to parent directory", + function (args) { buffer.climbUrlPath(Math.max(args.count, 1)); }, + { count: true }); + + mappings.add([modes.NORMAL], ["gU"], + "Go to the root of the website", + function () { buffer.climbUrlPath(-1); }); + + mappings.add(modes.COMMAND, [".", ""], "Repeat the last key event", function (args) { if (mappings.repeat) { @@ -1672,54 +1526,54 @@ var Buffer = Module("buffer", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { }, { count: true }); - mappings.add(myModes, ["i", ""], + mappings.add(modes.COMMAND, ["i", ""], "Start caret mode", function () { modes.push(modes.CARET); }); - mappings.add(myModes, [""], + mappings.add(modes.COMMAND, [""], "Stop loading the current web page", function () { ex.stop(); }); // scrolling - mappings.add(myModes, ["j", "", "", ""], + mappings.add(modes.COMMAND, ["j", "", "", ""], "Scroll document down", function (args) { buffer.scrollVertical("lines", Math.max(args.count, 1)); }, { count: true }); - mappings.add(myModes, ["k", "", "", ""], + mappings.add(modes.COMMAND, ["k", "", "", ""], "Scroll document up", function (args) { buffer.scrollVertical("lines", -Math.max(args.count, 1)); }, { count: true }); - mappings.add(myModes, dactyl.has("mail") ? ["h", ""] : ["h", "", ""], + mappings.add(modes.COMMAND, dactyl.has("mail") ? ["h", ""] : ["h", "", ""], "Scroll document to the left", function (args) { buffer.scrollHorizontal("columns", -Math.max(args.count, 1)); }, { count: true }); - mappings.add(myModes, dactyl.has("mail") ? ["l", ""] : ["l", "", ""], + mappings.add(modes.COMMAND, dactyl.has("mail") ? ["l", ""] : ["l", "", ""], "Scroll document to the right", function (args) { buffer.scrollHorizontal("columns", Math.max(args.count, 1)); }, { count: true }); - mappings.add(myModes, ["0", "^", ""], + mappings.add(modes.COMMAND, ["0", "^", ""], "Scroll to the absolute left of the document", function () { buffer.scrollToPercent(0, null); }); - mappings.add(myModes, ["$", ""], + mappings.add(modes.COMMAND, ["$", ""], "Scroll to the absolute right of the document", function () { buffer.scrollToPercent(100, null); }); - mappings.add(myModes, ["gg", ""], + mappings.add(modes.COMMAND, ["gg", ""], "Go to the top of the document", function (args) { buffer.scrollToPercent(null, args.count != null ? args.count : 0); }, { count: true }); - mappings.add(myModes, ["G", ""], + mappings.add(modes.COMMAND, ["G", ""], "Go to the end of the document", function (args) { buffer.scrollToPercent(null, args.count != null ? args.count : 100); }, { count: true }); - mappings.add(myModes, ["%", ""], + mappings.add(modes.COMMAND, ["%", ""], "Scroll to {count} percent of the document", function (args) { dactyl.assert(args.count > 0 && args.count <= 100); @@ -1727,59 +1581,59 @@ var Buffer = Module("buffer", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { }, { count: true }); - mappings.add(myModes, ["", ""], + mappings.add(modes.COMMAND, ["", ""], "Scroll window downwards in the buffer", function (args) { buffer._scrollByScrollSize(args.count, true); }, { count: true }); - mappings.add(myModes, ["", ""], + mappings.add(modes.COMMAND, ["", ""], "Scroll window upwards in the buffer", function (args) { buffer._scrollByScrollSize(args.count, false); }, { count: true }); - mappings.add(myModes, ["", "", "", ""], + mappings.add(modes.COMMAND, ["", "", "", ""], "Scroll up a full page", function (args) { buffer.scrollVertical("pages", -Math.max(args.count, 1)); }, { count: true }); - mappings.add(myModes, ["", "", "", ""], + mappings.add(modes.COMMAND, ["", "", "", ""], "Scroll down a full page", function (args) { buffer.scrollVertical("pages", Math.max(args.count, 1)); }, { count: true }); - mappings.add(myModes, ["]f", ""], + mappings.add(modes.COMMAND, ["]f", ""], "Focus next frame", function (args) { buffer.shiftFrameFocus(Math.max(args.count, 1)); }, { count: true }); - mappings.add(myModes, ["[f", ""], + mappings.add(modes.COMMAND, ["[f", ""], "Focus previous frame", function (args) { buffer.shiftFrameFocus(-Math.max(args.count, 1)); }, { count: true }); - mappings.add(myModes, ["]]", ""], + mappings.add(modes.COMMAND, ["]]", ""], "Follow the link labeled 'next' or '>' if it exists", function (args) { buffer.findLink("next", options["nextpattern"], (args.count || 1) - 1, true); }, { count: true }); - mappings.add(myModes, ["[[", ""], + mappings.add(modes.COMMAND, ["[[", ""], "Follow the link labeled 'prev', 'previous' or '<' if it exists", function (args) { buffer.findLink("previous", options["previouspattern"], (args.count || 1) - 1, true); }, { count: true }); - mappings.add(myModes, ["gf", ""], + mappings.add(modes.COMMAND, ["gf", ""], "Toggle between rendered and source view", function () { buffer.viewSource(null, false); }); - mappings.add(myModes, ["gF", ""], + mappings.add(modes.COMMAND, ["gF", ""], "View source with an external editor", function () { buffer.viewSource(null, true); }); - mappings.add(myModes, ["gi", ""], + mappings.add(modes.COMMAND, ["gi", ""], "Focus last used input field", function (args) { let elem = buffer.lastInputField; @@ -1811,7 +1665,7 @@ var Buffer = Module("buffer", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { }, { count: true }); - mappings.add(myModes, ["gP"], + mappings.add(modes.COMMAND, ["gP"], "Open (put) a URL based on the current clipboard contents in a new buffer", function () { let url = dactyl.clipboardRead(); @@ -1819,7 +1673,7 @@ var Buffer = Module("buffer", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { dactyl.open(url, { from: "paste", where: dactyl.NEW_TAB, background: true }); }); - mappings.add(myModes, ["p", "", ""], + mappings.add(modes.COMMAND, ["p", "", ""], "Open (put) a URL based on the current clipboard contents in the current buffer", function () { let url = dactyl.clipboardRead(); @@ -1827,7 +1681,7 @@ var Buffer = Module("buffer", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { dactyl.open(url); }); - mappings.add(myModes, ["P", ""], + mappings.add(modes.COMMAND, ["P", ""], "Open (put) a URL based on the current clipboard contents in a new buffer", function () { let url = dactyl.clipboardRead(); @@ -1836,16 +1690,16 @@ var Buffer = Module("buffer", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { }); // reloading - mappings.add(myModes, ["r", ""], + mappings.add(modes.COMMAND, ["r", ""], "Reload the current web page", function () { tabs.reload(tabs.getTab(), false); }); - mappings.add(myModes, ["R", ""], + mappings.add(modes.COMMAND, ["R", ""], "Reload while skipping the cache", function () { tabs.reload(tabs.getTab(), true); }); // yanking - mappings.add(myModes, ["Y", ""], + mappings.add(modes.COMMAND, ["Y", ""], "Copy selected text or current word", function () { let sel = buffer.currentWord; @@ -1854,66 +1708,88 @@ var Buffer = Module("buffer", XPCOM(Ci.nsISupportsWeakReference, ModuleBase), { }); // zooming - mappings.add(myModes, ["zi", "+", ""], + mappings.add(modes.COMMAND, ["zi", "+", ""], "Enlarge text zoom of current web page", function (args) { buffer.zoomIn(Math.max(args.count, 1), false); }, { count: true }); - mappings.add(myModes, ["zm", ""], + mappings.add(modes.COMMAND, ["zm", ""], "Enlarge text zoom of current web page by a larger amount", function (args) { buffer.zoomIn(Math.max(args.count, 1) * 3, false); }, { count: true }); - mappings.add(myModes, ["zo", "-", ""], + mappings.add(modes.COMMAND, ["zo", "-", ""], "Reduce text zoom of current web page", function (args) { buffer.zoomOut(Math.max(args.count, 1), false); }, { count: true }); - mappings.add(myModes, ["zr", ""], + mappings.add(modes.COMMAND, ["zr", ""], "Reduce text zoom of current web page by a larger amount", function (args) { buffer.zoomOut(Math.max(args.count, 1) * 3, false); }, { count: true }); - mappings.add(myModes, ["zz", ""], + mappings.add(modes.COMMAND, ["zz", ""], "Set text zoom value of current web page", function (args) { buffer.setZoom(args.count > 1 ? args.count : 100, false); }, { count: true }); - mappings.add(myModes, ["ZI", "zI", ""], + mappings.add(modes.COMMAND, ["ZI", "zI", ""], "Enlarge full zoom of current web page", function (args) { buffer.zoomIn(Math.max(args.count, 1), true); }, { count: true }); - mappings.add(myModes, ["ZM", "zM", ""], + mappings.add(modes.COMMAND, ["ZM", "zM", ""], "Enlarge full zoom of current web page by a larger amount", function (args) { buffer.zoomIn(Math.max(args.count, 1) * 3, true); }, { count: true }); - mappings.add(myModes, ["ZO", "zO", ""], + mappings.add(modes.COMMAND, ["ZO", "zO", ""], "Reduce full zoom of current web page", function (args) { buffer.zoomOut(Math.max(args.count, 1), true); }, { count: true }); - mappings.add(myModes, ["ZR", "zR", ""], + mappings.add(modes.COMMAND, ["ZR", "zR", ""], "Reduce full zoom of current web page by a larger amount", function (args) { buffer.zoomOut(Math.max(args.count, 1) * 3, true); }, { count: true }); - mappings.add(myModes, ["zZ", ""], + mappings.add(modes.COMMAND, ["zZ", ""], "Set full zoom value of current web page", function (args) { buffer.setZoom(args.count > 1 ? args.count : 100, true); }, { count: true }); // page info - mappings.add(myModes, ["", ""], + mappings.add(modes.COMMAND, ["", ""], "Print the current file name", function () { buffer.showPageInfo(false); }); - mappings.add(myModes, ["g", ""], + mappings.add(modes.COMMAND, ["g", ""], "Print file information", function () { buffer.showPageInfo(true); }); }, options: function () { + options.add(["encoding", "enc"], + "The current buffer's character encoding", + "string", "UTF-8", + { + scope: Option.SCOPE_LOCAL, + getter: function () config.browser.docShell.QueryInterface(Ci.nsIDocCharset).charset, + setter: function (val) { + if (options["encoding"] == val) + return val; + + // Stolen from browser.jar/content/browser/browser.js, more or less. + try { + config.browser.docShell.QueryInterface(Ci.nsIDocCharset).charset = val; + PlacesUtils.history.setCharsetForURI(getWebNavigation().currentURI, val); + getWebNavigation().reload(Ci.nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE); + } + catch (e) { dactyl.reportError(e); } + return null; + }, + completer: function (context) completion.charset(context) + }); + options.add(["iskeyword", "isk"], "Regular expression defining which characters constitute word characters", "string", '[^\\s.,!?:;/"\'^$%&?()[\\]{}<>#*+|=~_-]', diff --git a/common/content/hints.js b/common/content/hints.js index 2b7a6cab..18dceb2a 100644 --- a/common/content/hints.js +++ b/common/content/hints.js @@ -1159,8 +1159,6 @@ var Hints = Module("hints", { function ({ self }) { self.escapeNumbers = !self.escapeNumbers; }); }, options: function () { - const DEFAULT_HINTTAGS = - function xpath(arg) util.makeXPath(arg); options.add(["extendedhinttags", "eht"], "XPath strings of hintable elements for extended hint modes", diff --git a/common/content/statusline.js b/common/content/statusline.js index 7def5b4a..3ec88220 100644 --- a/common/content/statusline.js +++ b/common/content/statusline.js @@ -169,7 +169,7 @@ var StatusLine = Module("statusline", { modified += "-"; } if (modules.bookmarkcache) { - if (bookmarkcache.isBookmarked(buffer.uri)) + if (bookmarkcache.isBookmarked(url)) modified += UTF8("❤"); //modified += UTF8("♥"); } @@ -178,7 +178,6 @@ var StatusLine = Module("statusline", { url = losslessDecodeURI(url); - // make it even more Vim-like if (url == "about:blank") { if (!buffer.title) url = "[No Name]"; diff --git a/common/content/tabs.js b/common/content/tabs.js index 47a14424..1b9a2869 100644 --- a/common/content/tabs.js +++ b/common/content/tabs.js @@ -39,6 +39,10 @@ var Tabs = Module("tabs", { xul|tab { -moz-binding: url(chrome://dactyl/content/bindings.xml#tab) !important; } ]]>, /tab-./g, function (m) util.OS.isMacOSX ? "tab-mac" : m), false, true); + + for (let { linkedBrowser: { contentDocument } } in values(this.allTabs)) + if (contentDocument.readyState === "complete") + dactyl.initDocument(contentDocument); }, cleanup: function cleanup() {