summaryrefslogtreecommitdiff
path: root/ext/fg
diff options
context:
space:
mode:
authorAlex Yatskov <alex@foosoft.net>2016-07-24 21:18:17 -0700
committerAlex Yatskov <alex@foosoft.net>2016-07-24 21:18:17 -0700
commit19cc8fda335f27229753038709f3765090e169e8 (patch)
tree49ee07eb15e84c78eca7e07ac81aa88a2c453f08 /ext/fg
parent871acf7c2d75b349e55b761d5513223cf716464e (diff)
Better range handling.
Diffstat (limited to 'ext/fg')
-rw-r--r--ext/fg/js/client.js4
-rw-r--r--ext/fg/js/source-image.js8
-rw-r--r--ext/fg/js/source-input.js8
-rw-r--r--ext/fg/js/source-range.js68
4 files changed, 68 insertions, 20 deletions
diff --git a/ext/fg/js/client.js b/ext/fg/js/client.js
index bb0d3749..9806b96a 100644
--- a/ext/fg/js/client.js
+++ b/ext/fg/js/client.js
@@ -110,13 +110,13 @@ class Client {
return;
}
- textSource.setLength(this.options.scanLength);
+ textSource.setEndOffset(this.options.scanLength);
bgFindTerm(textSource.text(), ({definitions, length}) => {
if (length === 0) {
this.hidePopup();
} else {
const sequence = ++this.sequence;
- textSource.setLength(length);
+ textSource.setEndOffset(length);
bgRenderText(
{definitions, root: this.fgRoot, options: this.options, sequence},
diff --git a/ext/fg/js/source-image.js b/ext/fg/js/source-image.js
index bbc0ba46..319f25fe 100644
--- a/ext/fg/js/source-image.js
+++ b/ext/fg/js/source-image.js
@@ -32,8 +32,14 @@ class TextSourceImage {
return this.img.getAttribute('alt') || '';
}
- setLength(length) {
+ setStartOffset(length) {
+ // NOP
+ return 0;
+ }
+
+ setEndOffset(length) {
this.length = length;
+ return length;
}
containsPoint(point) {
diff --git a/ext/fg/js/source-input.js b/ext/fg/js/source-input.js
index 0bea977b..9f5a76a0 100644
--- a/ext/fg/js/source-input.js
+++ b/ext/fg/js/source-input.js
@@ -32,8 +32,14 @@ class TextSourceInput {
return this.input.nodeName === 'BUTTON' ? this.input.innerHTML : this.input.value;
}
- setLength(length) {
+ setStartOffset(length) {
+ // NOP
+ return 0;
+ }
+
+ setEndOffset(length) {
this.length = length;
+ return length;
}
containsPoint(point) {
diff --git a/ext/fg/js/source-range.js b/ext/fg/js/source-range.js
index e09ec33a..fbab45f9 100644
--- a/ext/fg/js/source-range.js
+++ b/ext/fg/js/source-range.js
@@ -26,9 +26,16 @@ class TextSourceRange {
return this.rng.toString();
}
- setLength(length) {
- const end = TextSourceRange.seekEnd(this.rng.startContainer, this.rng.startOffset + length);
+ setEndOffset(length) {
+ const end = TextSourceRange.seekForward(this.rng.startContainer, this.rng.startOffset + length);
this.rng.setEnd(end.node, end.offset);
+ return length - end.length;
+ }
+
+ setStartOffset(length) {
+ const start = TextSourceRange.seekBackward(this.rng.startContainer, length + (this.rng.startContainer.length - this.rng.startOffset));
+ this.rng.setStart(start.node, start.offset);
+ return length - start.length;
}
containsPoint(point) {
@@ -67,37 +74,66 @@ class TextSourceRange {
return other.rng && other.rng.compareBoundaryPoints(Range.START_TO_START, this.rng) == 0;
}
- static seekEnd(node, length) {
+ static seekForward(node, length) {
const state = {node, offset: 0, length};
+ if (!TextSourceRange.seekForwardHelper(node, state)) {
+ return state;
+ }
- if (!TextSourceRange.seekEndRecurse(node, state)) {
- return {node: state.node, offset: state.offset};
+ for (let current = node; current !== null; current = current.parentElement) {
+ for (let sibling = current.nextSibling; sibling !== null; sibling = sibling.nextSibling) {
+ if (!TextSourceRange.seekForwardHelper(sibling, state)) {
+ return state;
+ }
+ }
}
- for (let sibling = node.nextSibling; sibling !== null; sibling = sibling.nextSibling) {
- if (!TextSourceRange.seekEndRecurse(sibling, state)) {
- return {node: state.node, offset: state.offset};
+ return state;
+ }
+
+ static seekForwardHelper(node, state) {
+ if (node.nodeType === 3) {
+ const consumed = Math.min(node.length, state.length);
+ state.node = node;
+ state.offset = consumed;
+ state.length -= consumed;
+ } else {
+ for (let i = 0; i < node.childNodes.length; ++i) {
+ if (!TextSourceRange.seekForwardHelper(node.childNodes[i], state)) {
+ break;
+ }
}
}
- for (let sibling = node.parentElement.nextSibling; sibling !== null; sibling = sibling.nextSibling) {
- if (!TextSourceRange.seekEndRecurse(sibling, state)) {
- return {node: state.node, offset: state.offset};
+ return state.length > 0;
+ }
+
+ static seekBackward(node, length) {
+ const state = {node, offset: node.length, length};
+ if (!TextSourceRange.seekBackwardHelper(node, state)) {
+ return state;
+ }
+
+ for (let current = node; current !== null; current = current.parentElement) {
+ for (let sibling = current.previousSibling; sibling !== null; sibling = sibling.previousSibling) {
+ if (!TextSourceRange.seekBackwardHelper(sibling, state)) {
+ return state;
+ }
}
}
- return {node: state.node, offset: state.offset};
+ return state;
}
- static seekEndRecurse(node, state) {
+ static seekBackwardHelper(node, state) {
if (node.nodeType === 3) {
const consumed = Math.min(node.length, state.length);
state.node = node;
- state.offset = consumed;
+ state.offset = node.length - consumed;
state.length -= consumed;
} else {
- for (let i = 0; i < node.childNodes.length; ++i) {
- if (!TextSourceRange.seekEndRecurse(node.childNodes[i], state)) {
+ for (let i = node.childNodes.length - 1; i >= 0; --i) {
+ if (!TextSourceRange.seekBackwardHelper(node.childNodes[i], state)) {
break;
}
}