diff --git a/content/buffers.js b/content/buffers.js
index 2ce7624f..102f364a 100644
--- a/content/buffers.js
+++ b/content/buffers.js
@@ -283,13 +283,6 @@ vimperator.Buffer = function () //{{{
return window.content.document.title;
},
- // quick function to get elements inside the document reliably
- // argument "args" is something like: @id='myid' or @type='text' (don't forget the quoted around myid)
- element: function (args, index)
- {
- return vimperator.buffer.evaluateXPath("//*[" + (args || "") + "]").snapshotItem(index || 0)
- },
-
// returns an XPathResult object
evaluateXPath: function (expression, doc, elem, asIterator)
{
@@ -316,14 +309,33 @@ vimperator.Buffer = function () //{{{
return result;
},
+ // quick function to get elements inside the document reliably
+ // argument "args" is something like: @id='myid' or @type='text' (don't forget the quoted around myid)
+ getElement: function (args, index)
+ {
+ return vimperator.buffer.evaluateXPath("//*[" + (args || "") + "]").snapshotItem(index || 0)
+ },
+
// artificially "clicks" a link in order to open it
- followLink: function (elem, where, offsetX, offsetY)
+ followLink: function (elem, where)
{
var doc = window.content.document;
var view = window.document.defaultView;
- //var view = doc.defaultView;
- offsetX = offsetX || 1;
- offsetY = offsetY || 1;
+ var offsetX = 1;
+ var offsetY = 1;
+
+ var localName = elem.localName.toLowerCase();
+ if (localName == "frame" || localName == "iframe") // broken?
+ {
+ elem.contentWindow.focus();
+ return false;
+ }
+ else if (localName == "area") // for imagemap
+ {
+ var coords = elem.getAttribute("coords").split(",");
+ offsetX = Number(coords[0]) + 1;
+ offsetY = Number(coords[1]) + 1;
+ }
var newTab = false, newWindow = false;
switch (where)
@@ -339,15 +351,80 @@ vimperator.Buffer = function () //{{{
vimperator.log("Invalid where argument for followLink()");
}
+ elem.focus();
+
var evt = doc.createEvent("MouseEvents");
evt.initMouseEvent("mousedown", true, true, view, 1, offsetX, offsetY, 0, 0, /*ctrl*/ newTab, /*event.altKey*/0, /*event.shiftKey*/ newWindow, /*event.metaKey*/ newTab, 0, null);
elem.dispatchEvent(evt);
-
- //var evt = doc.createEvent("MouseEvents");
evt.initMouseEvent("click", true, true, view, 1, offsetX, offsetY, 0, 0, /*ctrl*/ newTab, /*event.altKey*/0, /*event.shiftKey*/ newWindow, /*event.metaKey*/ newTab, 0, null);
elem.dispatchEvent(evt);
},
+ // more advanced than a simple elem.focus() as it also works for iframes
+ // and image maps
+ // TODO: merge with followLink()?
+ focusElement: function (elem)
+ {
+ var doc = window.content.document;
+ var elemTagName = elem.localName.toLowerCase();
+ if (elemTagName == "frame" || elemTagName == "iframe")
+ {
+ elem.contentWindow.focus();
+ return false;
+ }
+ else
+ {
+ elem.focus();
+ }
+
+ var evt = doc.createEvent("MouseEvents");
+ var x = 0;
+ var y = 0;
+ // for imagemap
+ if (elemTagName == "area")
+ {
+ var coords = elem.getAttribute("coords").split(",");
+ x = Number(coords[0]);
+ y = Number(coords[1]);
+ }
+
+ evt.initMouseEvent("mouseover", true, true, doc.defaultView, 1, x, y, 0, 0, 0, 0, 0, 0, 0, null);
+ elem.dispatchEvent(evt);
+ },
+
+ yankElementText: function (elem)
+ {
+ var text = elem.textContent || "";
+ vimperator.copyToClipboard(text);
+ vimperator.echo("Yanked " + text, vimperator.commandline.FORCE_SINGLELINE);
+ },
+
+ yankElementLocation: function (elem)
+ {
+ var loc = elem.href || "";
+ vimperator.copyToClipboard(loc);
+ vimperator.echo("Yanked " + loc, vimperator.commandline.FORCE_SINGLELINE);
+ },
+
+ saveLink: function (elem, skipPrompt)
+ {
+ var doc = elem.ownerDocument;
+ var url = makeURLAbsolute(elem.baseURI, elem.href);
+ var text = elem.textContent;
+
+ try
+ {
+ urlSecurityCheck(url, doc.nodePrincipal);
+ // we always want to save that link relative to the current working directory
+ vimperator.options.setFirefoxPref("browser.download.lastDir", vimperator.io.getCurrentDirectory());
+ saveURL(url, text, null, true, skipPrompt, makeURI(url, doc.characterSet));
+ }
+ catch (e)
+ {
+ vimperator.echoerr(e);
+ }
+ },
+
// in contrast to vim, returns the selection if one is made,
// otherwise tries to guess the current word unter the text cursor
// NOTE: might change the selection
@@ -668,7 +745,14 @@ vimperator.Buffer = function () //{{{
bumpZoomLevel(-steps, fullZoom);
},
- pageInfo: function (verbose)
+ // similar to pageInfo
+ // TODO: print more useful information, just like the DOM inspector
+ showElementInfo: function (elem)
+ {
+ vimperator.echo("Element:
" + vimperator.objectToString(elem), vimperator.commandline.FORCE_MULTILINE);
+ },
+
+ showPageInfo: function (verbose)
{
const feedTypes = {
"application/rss+xml": "RSS",
diff --git a/content/commands.js b/content/commands.js
index ee57c333..68a30e88 100644
--- a/content/commands.js
+++ b/content/commands.js
@@ -722,14 +722,14 @@ vimperator.Commands = function () //{{{
case "pagesource": BrowserViewSourceOfDocument(content.document); break;
case "places": PlacesCommandHook.showPlacesOrganizer(ORGANIZER_ROOT_BOOKMARKS); break;
case "preferences": openPreferences(); break;
- // XXX what are onEnter.. and onExit...?
+ // XXX what are onEnter.. and onExit...?
case "printpreview": PrintUtils.printPreview(onEnterPrintPreview, onExitPrintPreview); break;
case "print": PrintUtils.print(); break;
case "printsetup": PrintUtils.showPageSetup(); break;
case "saveframe": saveFrameDocument(); break;
case "savepage": saveDocument(window.content.document); break;
case "searchengines": openDialog("chrome://browser/content/search/engineManager.xul", "_blank", "chrome,dialog,modal,centerscreen"); break;
- // TODO add viewPartialSource('selection'); ...
+ // TODO add viewPartialSource('selection'); ...
case "": vimperator.echoerr("E474: Invalid argument"); break;
default: vimperator.echoerr("Dialog '" + args + "' not available");
}
@@ -1745,7 +1745,7 @@ vimperator.Commands = function () //{{{
}
));
commandManager.add(new vimperator.Command(["pa[geinfo]"],
- function () { vimperator.buffer.pageInfo(true); },
+ function () { vimperator.buffer.showPageInfo(true); },
{
shortHelp: "Show various page information",
help: "See :help 'pageinfo' for available options"
@@ -1883,11 +1883,24 @@ vimperator.Commands = function () //{{{
}
));
commandManager.add(new vimperator.Command(["sav[eas]", "w[rite]"],
- function () { saveDocument(window.content.document); },
+ function (args, special)
+ {
+ var file = vimperator.io.getFile(args || "");
+ // we always want to save that link relative to the current working directory
+ vimperator.options.setFirefoxPref("browser.download.lastDir", vimperator.io.getCurrentDirectory());
+ //if (args)
+ //{
+ // saveURL(vimperator.buffer.URL, args, null, true, special, // special == skipPrompt
+ // makeURI(vimperator.buffer.URL, content.document.characterSet));
+ //}
+ //else
+ saveDocument(window.content.document, special);
+ },
{
shortHelp: "Save current web page to disk",
help: "Opens the original Firefox \"Save page as...\" dialog.
" +
- "There, you can save the current web page to disk with various options."
+ "There, you can save the current web page to disk with various options. " +
+ "Use ! to save the file with a default filename to the current working directory, skipping the Save as... prompt"
}
));
commandManager.add(new vimperator.Command(["se[t]"],
diff --git a/content/help.js b/content/help.js
index c546aa53..f5869830 100644
--- a/content/help.js
+++ b/content/help.js
@@ -301,7 +301,7 @@ vimperator.Help = function(section)
{
vimperator.open("chrome://vimperator/locale/" + file);
setTimeout(function() {
- var elem = vimperator.buffer.element('@class="tag" and text()="' + tag + '"');
+ var elem = vimperator.buffer.getElement('@class="tag" and text()="' + tag + '"');
if (elem)
window.content.scrollTo(0, elem.getBoundingClientRect().top - 10); // 10px context
}, 100);
diff --git a/content/hints.js b/content/hints.js
index 329f5c01..0b23a22a 100644
--- a/content/hints.js
+++ b/content/hints.js
@@ -74,93 +74,6 @@ vimperator.Hints = function () //{{{
(hintNumber > 0 ? " <" + hintNumber + ">" : ""));
}
- // this function 'click' an element, which also works
- // for javascript links
- function openHint(elem, where)
- {
- var x = 1, y = 1;
- var elemTagName = elem.localName.toLowerCase();
- elem.focus();
- if (elemTagName == "frame" || elemTagName == "iframe")
- return false;
-
- // for imagemap
- if (elemTagName == "area")
- {
- var coords = elem.getAttribute("coords").split(",");
- x = Number(coords[0]) + 1;
- y = Number(coords[1]) + 1;
- }
-
- vimperator.buffer.followLink(elem, where, x, y);
- return true;
- }
-
- function focusHint(elem)
- {
- var doc = window.content.document;
- var elemTagName = elem.localName.toLowerCase();
- if (elemTagName == "frame" || elemTagName == "iframe")
- {
- elem.contentWindow.focus();
- return false;
- }
- else
- {
- elem.focus();
- }
-
- var evt = doc.createEvent("MouseEvents");
- var x = 0;
- var y = 0;
- // for imagemap
- if (elemTagName == "area")
- {
- var coords = elem.getAttribute("coords").split(",");
- x = Number(coords[0]);
- y = Number(coords[1]);
- }
-
- evt.initMouseEvent("mouseover", true, true, doc.defaultView, 1, x, y, 0, 0, 0, 0, 0, 0, 0, null);
- elem.dispatchEvent(evt);
- }
-
- // TODO: print more useful information, just like the DOM inspector
- function printHint(elem)
- {
- vimperator.echo("Element:
" + vimperator.objectToString(elem), vimperator.commandline.FORCE_MULTILINE);
- }
-
- function yankHint(elem, text)
- {
- if (text)
- var loc = elem.textContent || "";
- else
- var loc = elem.href || "";
-
- vimperator.copyToClipboard(loc);
- // TODO: echoed text disappears immediately
- vimperator.echo("Yanked " + loc, vimperator.commandline.FORCE_SINGLELINE);
- }
-
- // TODO: should use the 'cwd', does it?
- function saveHint(elem, skipPrompt)
- {
- var doc = elem.ownerDocument;
- var url = makeURLAbsolute(elem.baseURI, elem.href);
- var text = elem.textContent;
-
- try
- {
- urlSecurityCheck(url, doc.nodePrincipal);
- saveURL(url, text, null, true, skipPrompt, makeURI(url, doc.characterSet));
- }
- catch (e)
- {
- vimperator.echoerr(e);
- }
- }
-
function generate(win)
{
var startDate = Date.now();
@@ -232,7 +145,7 @@ vimperator.Hints = function () //{{{
for (var i = 0; i < win.frames.length; i++)
generate(win.frames[i]);
- vimperator.log("hints.generate() completed after: " + (Date.now() - startDate) + "ms");
+ vimperator.log("hints.generate() completed after: " + (Date.now() - startDate) + "ms for " + hints.length + " hints.");
return true;
}
@@ -427,20 +340,20 @@ vimperator.Hints = function () //{{{
switch (submode)
{
// TODO: move/rename those helper functions to a better place
- case ";": focusHint(elem); break;
- case "?": printHint(elem); break;
- case "a": saveHint(elem, false); break;
- case "s": saveHint(elem, true); break;
- case "o": openHint(elem, vimperator.CURRENT_TAB); break;
+ case ";": vimperator.buffer.focusElement(elem); break;
+ case "?": vimperator.buffer.showElementInfo(elem); break;
+ case "a": vimperator.buffer.saveLink(elem, false); break;
+ case "s": vimperator.buffer.saveLink(elem, true); break;
+ case "o": vimperator.buffer.followLink(elem, vimperator.CURRENT_TAB); break;
case "O": vimperator.commandline.open(":", "open " + loc, vimperator.modes.EX); break;
- case "t": openHint(elem, vimperator.NEW_TAB); break;
+ case "t": vimperator.buffer.followLink(elem, vimperator.NEW_TAB); break;
case "T": vimperator.commandline.open(":", "tabopen " + loc, vimperator.modes.EX); break;
case "v": vimperator.commands.viewsource(loc); break;
case "V": vimperator.commands.viewsource(loc, true); break;
- case "w": openHint(elem, vimperator.NEW_WINDOW); break;
+ case "w": vimperator.buffer.followLink(elem, vimperator.NEW_WINDOW); break;
case "W": vimperator.commandline.open(":", "winopen " + loc, vimperator.modes.EX); break;
- case "y": yankHint(elem, false); break;
- case "Y": yankHint(elem, true); break;
+ case "y": vimperator.buffer.yankElementLocation(elem); break;
+ case "Y": vimperator.buffer.yankElementText(elem); break;
default:
vimperator.echoerr("INTERNAL ERROR: unknown submode: " + submode);
}
diff --git a/content/io.js b/content/io.js
index 64a9a014..5bfbccb7 100644
--- a/content/io.js
+++ b/content/io.js
@@ -54,6 +54,11 @@ vimperator.IO = function () //{{{
MODE_SYNC: 0x40,
MODE_EXCL: 0x80,
+ get directorySeperator()
+ {
+ return WINDOWS ? "\\" : "/";
+ },
+
expandPath: function (path)
{
// TODO: proper pathname separator translation like Vim
diff --git a/content/mappings.js b/content/mappings.js
index cc14cd22..b4f61c77 100644
--- a/content/mappings.js
+++ b/content/mappings.js
@@ -1099,7 +1099,7 @@ vimperator.Mappings = function () //{{{
// page info
addDefaultMap(new vimperator.Map([vimperator.modes.NORMAL], [""],
- function (count) { vimperator.buffer.pageInfo(false); },
+ function (count) { vimperator.buffer.showPageInfo(false); },
{
shortHelp: "Print the current file name",
help: "Also shows some additional file information like file size or the last modified date. " +
@@ -1108,7 +1108,7 @@ vimperator.Mappings = function () //{{{
}
));
addDefaultMap(new vimperator.Map([vimperator.modes.NORMAL], ["g"],
- function (count) { vimperator.buffer.pageInfo(true); },
+ function (count) { vimperator.buffer.showPageInfo(true); },
{
shortHelp: "Print file information",
help: "Same as :pa[geinfo]."