mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Fix DOMRange onAttached; view.{first,last}Node()
DOMRange#setMembers was causing DOMRange#onAttached callbacks to get called, masking a bug in onViewReady where DOMRange#attached was misspelled DOMRange#isAttached.
This commit is contained in:
@@ -120,17 +120,17 @@ DOMRange.forElement = function (elem) {
|
||||
return range;
|
||||
};
|
||||
|
||||
DOMRange.prototype.attach = function (parentElement, nextNode, _isMove) {
|
||||
DOMRange.prototype.attach = function (parentElement, nextNode, _isMove, _isReplace) {
|
||||
// This method is called to insert the DOMRange into the DOM for
|
||||
// the first time, but it's also used internally when
|
||||
// updating the DOM.
|
||||
//
|
||||
// If _isMove is true, move this attached range to a different
|
||||
// location under the same parentElement.
|
||||
if (_isMove) {
|
||||
if (_isMove || _isReplace) {
|
||||
if (! (this.parentElement === parentElement &&
|
||||
this.attached))
|
||||
throw new Error("Can only move an attached DOMRange, and only under the same parent element");
|
||||
throw new Error("Can only move or replace an attached DOMRange, and only under the same parent element");
|
||||
}
|
||||
|
||||
var members = this.members;
|
||||
@@ -150,7 +150,7 @@ DOMRange.prototype.attach = function (parentElement, nextNode, _isMove) {
|
||||
this.attached = true;
|
||||
this.parentElement = parentElement;
|
||||
|
||||
if (! _isMove) {
|
||||
if (! (_isMove || _isReplace)) {
|
||||
for(var i = 0; i < this.attachedCallbacks.length; i++) {
|
||||
var obj = this.attachedCallbacks[i];
|
||||
obj.attached && obj.attached(this, parentElement);
|
||||
@@ -178,9 +178,10 @@ DOMRange.prototype.setMembers = function (newNodeAndRangeArray) {
|
||||
// detach the old members and insert the new members
|
||||
var nextNode = this.lastNode().nextSibling;
|
||||
var parentElement = this.parentElement;
|
||||
this.detach();
|
||||
// Use detach/attach, but don't fire attached/detached hooks
|
||||
this.detach(true /*_isReplace*/);
|
||||
this.members = newMembers;
|
||||
this.attach(parentElement, nextNode);
|
||||
this.attach(parentElement, nextNode, false, true /*_isReplace*/);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -207,7 +208,7 @@ DOMRange.prototype.lastNode = function () {
|
||||
return (m instanceof DOMRange) ? m.lastNode() : m;
|
||||
};
|
||||
|
||||
DOMRange.prototype.detach = function () {
|
||||
DOMRange.prototype.detach = function (_isReplace) {
|
||||
if (! this.attached)
|
||||
throw new Error("Must be attached");
|
||||
|
||||
@@ -222,12 +223,15 @@ DOMRange.prototype.detach = function () {
|
||||
this.parentElement.removeChild(placeholder);
|
||||
this.emptyRangePlaceholder = null;
|
||||
}
|
||||
this.attached = false;
|
||||
this.parentElement = null;
|
||||
|
||||
for(var i = 0; i < this.attachedCallbacks.length; i++) {
|
||||
var obj = this.attachedCallbacks[i];
|
||||
obj.detached && obj.detached(this, oldParentElement);
|
||||
if (! _isReplace) {
|
||||
this.attached = false;
|
||||
this.parentElement = null;
|
||||
|
||||
for(var i = 0; i < this.attachedCallbacks.length; i++) {
|
||||
var obj = this.attachedCallbacks[i];
|
||||
obj.detached && obj.detached(this, oldParentElement);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ Blaze.View.prototype.onViewReady = function (cb) {
|
||||
self._onViewRendered(function onViewRendered() {
|
||||
if (self.isDestroyed)
|
||||
return;
|
||||
if (! self._domrange.isAttached)
|
||||
if (! self._domrange.attached)
|
||||
self._domrange.onAttached(fire);
|
||||
else
|
||||
fire();
|
||||
@@ -167,6 +167,20 @@ Blaze.View.prototype.autorun = function (f, _inViewScope) {
|
||||
return c;
|
||||
};
|
||||
|
||||
Blaze.View.prototype.firstNode = function () {
|
||||
if (! this.isAttached)
|
||||
throw new Error("View must be attached before accessing its DOM");
|
||||
|
||||
return this._domrange.firstNode();
|
||||
};
|
||||
|
||||
Blaze.View.prototype.lastNode = function () {
|
||||
if (! this.isAttached)
|
||||
throw new Error("View must be attached before accessing its DOM");
|
||||
|
||||
return this._domrange.lastNode();
|
||||
};
|
||||
|
||||
Blaze._fireCallbacks = function (view, which) {
|
||||
Blaze._withCurrentView(view, function () {
|
||||
Deps.nonreactive(function fireCallbacks() {
|
||||
|
||||
@@ -32,7 +32,11 @@ if (Meteor.isClient) {
|
||||
test.isFalse(v.isAttached);
|
||||
test.equal(buf, 'c0r1');
|
||||
test.equal(canonicalizeHtml(div.innerHTML), "");
|
||||
test.throws(function () { v.firstNode(); }, /View must be attached/);
|
||||
test.throws(function () { v.lastNode(); }, /View must be attached/);
|
||||
Blaze.insert(v, div);
|
||||
test.equal(typeof (v.firstNode().nodeType), "number");
|
||||
test.equal(typeof (v.lastNode().nodeType), "number");
|
||||
test.isTrue(v.isRendered);
|
||||
test.isTrue(v.isAttached);
|
||||
test.equal(buf, 'c0r1');
|
||||
@@ -48,6 +52,11 @@ if (Meteor.isClient) {
|
||||
Blaze.remove(v);
|
||||
test.equal(buf, 'c0r1y1r2y2d2');
|
||||
test.equal(canonicalizeHtml(div.innerHTML), "");
|
||||
|
||||
buf = "";
|
||||
R.set("baz");
|
||||
Deps.flush();
|
||||
test.equal(buf, "");
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -499,8 +499,8 @@ Tinytest.add("ui - render - templates and views", function (test) {
|
||||
};
|
||||
|
||||
var view = this.view;
|
||||
var start = view._domrange.firstNode();
|
||||
var end = view._domrange.lastNode();
|
||||
var start = view.firstNode();
|
||||
var end = view.lastNode();
|
||||
// skip marker nodes
|
||||
while (start !== end && ! nodeDescr(start))
|
||||
start = start.nextSibling;
|
||||
|
||||
Reference in New Issue
Block a user