Components.utils.import("resource://dactyl/bootstrap.jsm");
defineModule("finder", {
exports: ["RangeFind", "RangeFinder", "rangefinder"],
+ require: ["prefs"],
use: ["messages", "services", "util"]
}, this);
function equals(a, b) XPCNativeWrapper(a) == XPCNativeWrapper(b);
+try {
+
/** @instance rangefinder */
var RangeFinder = Module("rangefinder", {
Local: function (dactyl, modules, window) ({
set rangeFind(val) modules.buffer.localStore.rangeFind = val
}),
+ init: function init() {
+ prefs.safeSet("accessibility.typeaheadfind.autostart", false);
+ // The above should be sufficient, but: http://dactyl.sf.net/bmo/348187
+ prefs.safeSet("accessibility.typeaheadfind", false);
+ },
+
get commandline() this.modules.commandline,
get modes() this.modules.modes,
get options() this.modules.options,
if (this.rangeFind && equals(this.rangeFind.window.get(), this.window))
this.rangeFind.reset();
- this.find("", mode === this.modes.FIND_BACKWARD);
+ this.find("", mode == this.modes.FIND_BACKWARD);
},
bootstrap: function (str, backward) {
+ if (arguments.length < 2 && this.rangeFind)
+ backward = this.rangeFind.reverse;
+
let highlighted = this.rangeFind && this.rangeFind.highlighted;
let selections = this.rangeFind && this.rangeFind.selections;
let linksOnly = false;
}
},
+ onHistory: function () {
+ this.rangeFind.found = false;
+ },
+
onSubmit: function (command) {
if (!this.options["incfind"] || !this.rangeFind || !this.rangeFind.found) {
this.clear();
modes.addMode("FIND", {
description: "Find mode, active when typing search input",
- bases: [modes.COMMAND_LINE],
+ bases: [modes.COMMAND_LINE]
});
modes.addMode("FIND_FORWARD", {
description: "Forward Find mode, active when typing search input",
get onCancel() modules.rangefinder.closure.onCancel,
get onChange() modules.rangefinder.closure.onChange,
+ get onHistory() modules.rangefinder.closure.onHistory,
get onSubmit() modules.rangefinder.closure.onSubmit
});
},
mappings: function (dactyl, modules, window) {
- const { buffer, config, mappings, modes, rangefinder } = modules;
+ const { Buffer, buffer, config, mappings, modes, rangefinder } = modules;
var myModes = config.browserModes.concat([modes.CARET]);
mappings.add(myModes,
- ["/"], "Find a pattern starting at the current caret position",
+ ["/", "<find-forward>"], "Find a pattern starting at the current caret position",
function () { rangefinder.openPrompt(modes.FIND_FORWARD); });
mappings.add(myModes,
- ["?"], "Find a pattern backward of the current caret position",
+ ["?", "<find-backward>"], "Find a pattern backward of the current caret position",
function () { rangefinder.openPrompt(modes.FIND_BACKWARD); });
mappings.add(myModes,
- ["n"], "Find next",
+ ["n", "<find-next>"], "Find next",
function () { rangefinder.findAgain(false); });
mappings.add(myModes,
- ["N"], "Find previous",
+ ["N", "<find-previous>"], "Find previous",
function () { rangefinder.findAgain(true); });
- mappings.add(myModes.concat([modes.CARET, modes.TEXT_EDIT]), ["*"],
+ mappings.add(myModes.concat([modes.CARET, modes.TEXT_EDIT]), ["*", "<find-word-forward>"],
"Find word under cursor",
function () {
- rangefinder.find(buffer.getCurrentWord(), false);
+ rangefinder.find(Buffer.currentWord(buffer.focusedFrame, true), false);
rangefinder.findAgain();
});
- mappings.add(myModes.concat([modes.CARET, modes.TEXT_EDIT]), ["#"],
+ mappings.add(myModes.concat([modes.CARET, modes.TEXT_EDIT]), ["#", "<find-word-backward>"],
"Find word under cursor backwards",
function () {
- rangefinder.find(buffer.getCurrentWord(), true);
+ rangefinder.find(Buffer.currentWord(buffer.focusedFrame, true), true);
rangefinder.findAgain();
});
const { options, rangefinder } = modules;
const { prefs } = require("prefs");
- // prefs.safeSet("accessibility.typeaheadfind.autostart", false);
- // The above should be sufficient, but: https://bugzilla.mozilla.org/show_bug.cgi?id=348187
- prefs.safeSet("accessibility.typeaheadfind", false);
-
options.add(["hlfind", "hlf"],
"Highlight all /find pattern matches on the current page after submission",
"boolean", false, {
});
options.add(["incfind", "if"],
- "Find a pattern incrementally as it is typed rather than awaiting <Return>",
+ "Find a pattern incrementally as it is typed rather than awaiting c_<Return>",
"boolean", true);
}
});
let doc = range.startContainer.ownerDocument;
let win = doc.defaultView;
let ranges = this.ranges.filter(function (r)
- r.window === win && RangeFind.contains(r.range, range));
+ r.window === win && RangeFind.sameDocument(r.range, range) && RangeFind.contains(r.range, range));
if (this.backward)
return ranges[ranges.length - 1];
var node = util.evaluateXPath(RangeFind.selectNodePath,
this.lastRange.commonAncestorContainer).snapshotItem(0);
if (node) {
- node.focus()
+ node.focus();
// Re-highlight collapsed selection
this.selectedRange = this.lastRange;
}
frames.push(r);
}
- let range = start.startContainer.ownerDocument.createRange();
+ let doc = start.startContainer.ownerDocument;
+
+ let range = doc.createRange();
range.setStart(start.startContainer, start.startOffset);
range.setEnd(end.startContainer, end.startOffset);
}
function rec(win) {
let doc = win.document;
- let pageRange = RangeFind.nodeRange(doc.body || doc.documentElement.lastChild);
+ let pageRange = RangeFind[doc.body ? "nodeRange" : "nodeContents"](doc.body || doc.documentElement);
backup = backup || pageRange;
let pageStart = RangeFind.endpoint(pageRange, true);
let pageEnd = RangeFind.endpoint(pageRange, false);
}
}
pushRange(pageStart, pageEnd);
+
+ let anonNodes = doc.getAnonymousNodes(doc.documentElement);
+ if (anonNodes) {
+ for (let [, elem] in iter(anonNodes)) {
+ let range = RangeFind.nodeContents(elem);
+ pushRange(RangeFind.endpoint(range, true), RangeFind.endpoint(range, false));
+ }
+ }
}
rec(win);
if (frames.length == 0)
return false;
}
},
+ nodeContents: function (node) {
+ let range = node.ownerDocument.createRange();
+ try {
+ range.selectNodeContents(node);
+ }
+ catch (e) {}
+ return range;
+ },
nodeRange: function (node) {
let range = node.ownerDocument.createRange();
try {
catch (e) {}
return range;
},
- sameDocument: function (r1, r2) r1 && r2 && r1.endContainer.ownerDocument == r2.endContainer.ownerDocument,
+ sameDocument: function (r1, r2) {
+ if (!(r1 && r2 && r1.endContainer.ownerDocument == r2.endContainer.ownerDocument))
+ return false;
+ try {
+ r1.compareBoundaryPoints(r1.START_TO_START, r2);
+ }
+ catch (e if e.result == 0x80530004 /* NS_ERROR_DOM_WRONG_DOCUMENT_ERR */) {
+ return false;
+ }
+ return true;
+ },
selectNodePath: ["a", "xhtml:a", "*[@onclick]"].map(function (p) "ancestor-or-self::" + p).join(" | ")
});
+} catch(e){ if (typeof e === "string") e = Error(e); dump(e.fileName+":"+e.lineNumber+": "+e+"\n" + e.stack); }
+
endModule();
+
// vim: set fdm=marker sw=4 ts=4 et ft=javascript: