1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2026-01-04 04:14:12 +01:00

Be more assiduous in scrollIntoView. Don't pass it off to the element, which winds up mucking everything up.

This commit is contained in:
Kris Maglione
2011-10-04 02:24:56 -04:00
parent f1e4e9958c
commit 0c1fc4f421
2 changed files with 73 additions and 29 deletions

View File

@@ -501,7 +501,7 @@ var Buffer = Module("Buffer", {
let win = this.focusedFrame;
let sel = win.getSelection();
let viewport = DOM(win).rect;
let { viewport } = DOM(win);
if (sel.rangeCount) {
var range = sel.getRangeAt(0);
@@ -509,7 +509,7 @@ var Buffer = Module("Buffer", {
return;
var { rect } = DOM(range);
var reverse = rect.bottom > win.innerHeight;
var reverse = rect.bottom > viewport.bottom;
rect = { x: rect.left, y: 0, width: rect.width, height: win.innerHeight };
}

View File

@@ -326,26 +326,61 @@ var DOM = Class("DOM", {
}),
}),
get rect() this[0] instanceof Ci.nsIDOMWindow ? { get width() this.innerWidth,
get height() this.innerHeight,
get bottom() this.height,
get right() this.width,
top: 0, left: 0,
__proto__: this[0] } :
get rect() this[0] instanceof Ci.nsIDOMWindow ? { width: this[0].scrollMaxX + this[0].innerWidth,
height: this[0].scrollMaxY + this[0].innerHeight,
get right() this.width + this.left,
get bottom() this.height + this.top,
top: -this[0].scrollY,
left: -this[0].scrollX } :
this[0] ? this[0].getBoundingClientRect() : {},
get viewport() {
if (this[0] instanceof Ci.nsIDOMWindow)
return {
get width() this.right - this.left,
get height() this.bottom - this.top,
bottom: this[0].innerHeight,
right: this[0].innerWidth,
top: 0, left: 0
};
let r = this.rect;
return {
width: this[0].clientWidth,
height: this[0].clientHeight,
top: r.top + this[0].scrollTop + this[0].clientTop,
top: r.top + this[0].clientTop,
get bottom() this.top + this.height,
left: r.left + this[0].scrollLeft + this[0].clientLeft,
left: r.left + this[0].clientLeft,
get right() this.left + this.width
}
},
scrollPos: function scrollPos(left, top) {
if (arguments.length == 0) {
if (this[0] instanceof Ci.nsIDOMElement)
return { top: this[0].scrollTop, left: this[0].scrollLeft };
if (this[0] instanceof Ci.nsIDOMWindow)
return { top: this[0].scrollY, left: this[0].scrollX };
return null;
}
let func = callable(left) && left;
return this.each(function (elem, i) {
if (func)
({ left, top }) = func.call(this, elem, i);
if (elem instanceof Ci.nsIDOMWindow)
elem.scrollTo(left == null ? elem.scrollX : left,
top == null ? elem.scrollY : top);
else {
if (left != null)
elem.scrollLeft = left;
if (top != null)
elem.scrollTop = top;
}
});
},
/**
* Returns true if the given DOM node is currently visible.
* @returns {boolean}
@@ -798,32 +833,41 @@ var DOM = Class("DOM", {
*/
scrollIntoView: function scrollIntoView(alignWithTop) {
return this.each(function (elem) {
let rect = this.rect;
function getAlignment(viewport) {
if (alignWithTop !== undefined)
return alignWithTop;
if (rect.bottom < viewport.top)
return true;
if (rect.top > viewport.bottom)
return false;
return Math.abs(rect.top) < Math.abs(viewport.bottom - rect.bottom)
}
let force = false;
if (rect)
for (let parent in this.ancestors.items) {
if (!parent[0].clientWidth || !parent[0].clientHeight)
continue;
let rect;
function fix(parent) {
if (!(parent[0] instanceof Ci.nsIDOMWindow)
&& parent.style.overflow == "visible")
return;
let isect = util.intersection(rect, parent.viewport);
({ rect }) = DOM(elem);
let { viewport } = parent;
let isect = util.intersection(rect, viewport);
if (parent[0].clientWidth < rect.width && isect.width ||
parent[0].clientHeight < rect.height && isect.height)
continue;
if (isect.height < Math.min(viewport.height, rect.height)) {
let { top } = parent.scrollPos();
util.dump(" " + top + " " + (viewport.top - rect.top) + " " + (viewport.bottom - rect.bottom));
if (getAlignment(viewport))
parent.scrollPos(null, top - (viewport.top - rect.top));
else
parent.scrollPos(null, top - (viewport.bottom - rect.bottom));
force = Math.round(isect.width - rect.width) || Math.round(isect.height - rect.height);
if (force)
break;
}
}
let win = this.document.defaultView;
for (let parent in this.ancestors.items)
fix(parent);
if (force || !(rect && rect.bottom <= win.innerHeight && rect.top >= 0 && rect.left < win.innerWidth && rect.right > 0))
elem.scrollIntoView(alignWithTop !== undefined ? alignWithTop :
rect.bottom < 0 ? true :
rect.top > win.innerHeight ? false
: Math.abs(rect.top) < Math.abs(win.innerHeight - rect.bottom));
fix(DOM(this.document.defaultView));
});
},
}, {