liverange ui tweaks. just a few tests but they pass

This commit is contained in:
Geoff Schmidt
2011-12-16 19:48:42 -08:00
committed by Nick Martin
parent 0399108751
commit 4c3206031b
2 changed files with 29 additions and 26 deletions

View File

@@ -19,6 +19,8 @@ Sky.ui = Sky.ui || {};
// 'start' - start point, in preorder traversal (range starts just before start)
// 'end' - end point, in postorder traversal (range ends just after end)
// if there are any other ranges that also span exactly from start
// to end, the new range will be outside of them.
Sky.ui._LiveRange = function (tag, start, end) {
if ((start instanceof Document) || (start instanceof DocumentFragment)) {
end = start.lastChild;
@@ -26,41 +28,42 @@ Sky.ui = Sky.ui || {};
}
end = end || start;
this._tag = tag;
// XXX this is public for reading. document it.
this.tag = tag;
this._ensure_tags([start, end]);
// this._start is the node N such that we begin before N, but not
// before the node before N in the preorder traversal of the
// document (if there is such a node.) this._start[this._tag][0]
// document (if there is such a node.) this._start[this.tag][0]
// will be the list of all LiveRanges for which this._start is N,
// including us, sorted in the order that the ranges start. and
// finally, this._start[this._start_idx] === this.
this._start = start;
this._start_idx = start[tag][0].length;
start[tag][0].push(this);
this._start_idx = 0;
start[tag][0].splice(0, 0, this);
for (var i = 1; i < start[tag][0].length; i++)
start[tag][0][i]._start_idx = i;
// just like this._end, except it's the node N such that we end
// after N, but not after the node after N in the postorder
// traversal; and the data is stored in this._end[this._tag][1], and
// traversal; and the data is stored in this._end[this.tag][1], and
// it's sorted in the order that the ranges end.
this._end = end;
this._end_idx = 0;
end[tag][1].splice(0, 0, this);
for (var i = 1; i < end[tag][1].length; i++)
end[tag][1][i]._end_idx = i;
this._end_idx = end[tag][1].length;
end[tag][1].push(this);
};
Sky.ui._LiveRange.prototype._ensure_tags = function (nodes) {
for (var i = 0; i < nodes.length; i++)
if (!(this._tag in nodes[i]))
nodes[i][this._tag] = [[], []];
if (!(this.tag in nodes[i]))
nodes[i][this.tag] = [[], []];
};
Sky.ui._LiveRange.prototype._clean_tags = function (nodes) {
for (var i = 0; i < nodes.length; i++) {
var data = nodes[i][this._tag];
var data = nodes[i][this.tag];
if (data && !(data[0].length + data[1].length))
delete nodes[i][this._tag];
delete nodes[i][this.tag];
}
};
@@ -70,20 +73,20 @@ Sky.ui = Sky.ui || {};
// versions of IE, you do need to manually remove all ranges because
// IE can't GC reference cycles through the DOM.
Sky.ui._LiveRange.prototype.destroy = function () {
this._start[this._tag][0].splice(this._start_idx, 1);
this._end[this._tag][1].splice(this._end_idx, 1);
this._start[this.tag][0].splice(this._start_idx, 1);
this._end[this.tag][1].splice(this._end_idx, 1);
this._clean_tags([this._start, this._end]);
this._start = this._end = null;
};
// The first node in the range (in preorder traversal)
Sky.ui._LiveRange.prototype.start = function () {
Sky.ui._LiveRange.prototype.firstNode = function () {
return this._start;
};
// The last node in the range (in postorder traversal)
Sky.ui._LiveRange.prototype.end = function () {
Sky.ui._LiveRange.prototype.lastNode = function () {
return this._end;
};
@@ -101,7 +104,7 @@ Sky.ui = Sky.ui || {};
visit_range(true, data[0][i]);
visit_node && visit_node(true, node);
for (var walk = node.firstChild; walk; walk = walk.nextSibling) {
var walk_data = walk[this._tag] || [[], []];
var walk_data = walk[this.tag] || [[], []];
traverse(walk, walk_data, 0, walk_data[1].length);
}
visit_node && visit_node(false, node);
@@ -111,7 +114,7 @@ Sky.ui = Sky.ui || {};
var walk = this._start;
while (true) {
var walk_data = walk[this._tag] || [[], []];
var walk_data = walk[this.tag] || [[], []];
traverse(walk, walk_data, walk === this._start ? this._start_idx + 1 : 0,
walk === this._end ? this._end_idx : walk_data[1].length);
if (walk === this._end)
@@ -145,12 +148,12 @@ Sky.ui = Sky.ui || {};
throw new Error("Ranges must contain at least one element");
// Fix up range pointers on departing fragment
var old_enter = this._start[this._tag][0];
var old_enter = this._start[this.tag][0];
var save_enter = old_enter.splice(0, this._start_idx + 1);
for (var i = 0; i < old_enter.length; i++)
old_enter[i]._start_idx = i;
var old_leave = this._end[this._tag][1]
var old_leave = this._end[this.tag][1]
var save_leave = old_leave.splice(this._end_idx, old_leave.length);
this._clean_tags([this._start, this._end]);
@@ -175,14 +178,14 @@ Sky.ui = Sky.ui || {};
// Fix up range pointers on new fragment -- including our own
// Clobbers this._start(_idx), this._end(_idx)
var new_enter = new_start[this._tag][0];
var new_enter = new_start[this.tag][0];
Array.prototype.splice.apply(new_enter, [0, 0].concat(save_enter));
for (var i = 0; i < new_enter.length; i++) {
new_enter[i]._start = new_start;
new_enter[i]._start_idx = i;
}
var new_leave = new_end[this._tag][1];
var new_leave = new_end[this.tag][1];
for (var i = 0; i < save_leave.length; i++) {
save_leave[i]._end = new_end;
save_leave[i]._end_idx = new_leave.length + i;
@@ -210,7 +213,7 @@ Sky.ui = Sky.ui || {};
// the right.
// We're abutting on the left if this._start_idx > 0. We're abutting
// on the right if this._end_idx !== this._end[this._tag][1].length - 1.
// on the right if this._end_idx !== this._end[this.tag][1].length - 1.
// XXX is this complete, eg maybe need to look at eg this._end.
// ---

View File

@@ -77,8 +77,8 @@ Sky.ui.render = function (render_func, events, event_data) {
if (old_context.killed)
return; // _cleanup is killing us
if (!(document.body.contains ? document.body.contains(range.start())
: (document.body.compareDocumentPosition(range.start()) & 16))) {
if (!(document.body.contains ? document.body.contains(range.firstNode())
: (document.body.compareDocumentPosition(range.lastNode()) & 16))) {
// It was taken offscreen. Stop updating it so it can get GC'd.
Sky.ui._cleanup(range);
range.destroy();