Permalink
Browse files

Merge pull request #717 from juggy/issue233

Fix issue #233 - Appending and removing a view in a single runloop
  • Loading branch information...
2 parents e7096b8 + a982beb commit 08d025be0480f262e088bc1def25aa4d6d27892a @krisselden krisselden committed Apr 21, 2012
@@ -9,6 +9,8 @@ var DOMManager = {
remove: function(view) {
var morph = view.morph;
if (morph.isRemoved()) { return; }
+ set(view, 'element', null);
+ set(view, 'lastInsert', null);
morph.remove();
},
@@ -266,7 +266,6 @@ Ember.CollectionView = Ember.ContainerView.extend(
addedViews.push(emptyView);
set(this, 'emptyView', emptyView);
}
-
childViews.replace(start, 0, addedViews);
},
@@ -27,6 +27,12 @@ Ember.View.states = {
// Handle events from `Ember.EventDispatcher`
handleEvent: function() {
return true; // continue event propagation
+ },
+
+ destroyElement: function(view) {
+ set(view, 'element', null);
+ set(view, 'lastInsert', null);
+ return view;
}
}
};
@@ -27,6 +27,7 @@ Ember.View.states.hasElement = {
setElement: function(view, value) {
if (value === null) {
view.invalidateRecursively('element');
+
view.transitionTo('preRender');
} else {
throw "You cannot set an element to a non-null value when the element is already in the DOM.";
@@ -48,10 +49,10 @@ Ember.View.states.hasElement = {
// once the view is already in the DOM, destroying it removes it
// from the DOM, nukes its element, and puts it back into the
- // preRender state.
+ // preRender state if inDOM.
+
destroyElement: function(view) {
view._notifyWillDestroyElement();
-
view.domManager.remove(view);
return view;
},
@@ -81,7 +82,10 @@ Ember.View.states.hasElement = {
Ember.View.states.inDOM = {
parentState: Ember.View.states.hasElement,
- insertElement: function() {
+ insertElement: function(view, fn) {
+ if (view.get('lastInsert') !== fn.insertGuid){
+ return;
+ }
throw "You can't insert an element into the DOM that has already been inserted";
}
};
@@ -13,6 +13,9 @@ Ember.View.states.preRender = {
// a view leaves the preRender state once its element has been
// created (createElement).
insertElement: function(view, fn) {
+ if (view.get('lastInsert') !== fn.insertGuid){
+ return;
+ }
view.createElement();
view._notifyWillInsertElement(true);
// after createElement, the view will be in the hasElement state.
@@ -745,6 +745,7 @@ Ember.View = Ember.Object.extend(Ember.Evented,
@param {Function} fn the function that inserts the element into the DOM
*/
_insertElementLater: function(fn) {
+ set(this, 'lastInsert', fn.insertGuid = Ember.generateGuid());
Ember.run.schedule('render', this, this.invokeForState, 'insertElement', fn);
},
@@ -1528,6 +1529,7 @@ var DOMManager = {
var elem = get(view, 'element');
set(view, 'element', null);
+ set(view, 'lastInsert', null);
Ember.$(elem).remove();
},
@@ -313,3 +313,30 @@ test("should allow declaration of itemViewClass as a string", function() {
equal(view.$('.ember-view').length, 3);
});
+
+test("should not render the emptyView if content is emptied and refilled in the same run loop", function() {
+ view = Ember.CollectionView.create({
+ tagName: 'div',
+ content: Ember.A(['NEWS GUVNAH']),
+
+ emptyView: Ember.View.create({
+ tagName: 'kbd',
+ render: function(buf) {
+ buf.push("OY SORRY GUVNAH NO NEWS TODAY EH");
+ }
+ })
+ });
+
+ Ember.run(function() {
+ view.append();
+ });
+
+ equal(view.$().find('kbd:contains("OY SORRY GUVNAH")').length, 0);
+
+ Ember.run(function() {
+ view.get('content').popObject();
+ view.get('content').pushObject(['NEWS GUVNAH']);
+ });
+ equal(view.$('div').length, 1);
+ equal(view.$().find('kbd:contains("OY SORRY GUVNAH")').length, 0);
+});
@@ -95,5 +95,27 @@ test("does nothing if not in parentView", function() {
});
+test("the DOM element is gone after doing append and remove in two separate runloops", function() {
+ var view = Ember.View.create();
+ Ember.run(function() {
+ view.append();
+ });
+ Ember.run(function() {
+ view.remove();
+ });
+
+ var viewElem = Ember.$('#'+get(view, 'elementId'));
+ ok(viewElem.length === 0, "view's element doesn't exist in DOM");
+});
+test("the DOM element is gone after doing append and remove in a single runloop", function() {
+ var view = Ember.View.create();
+ Ember.run(function() {
+ view.append();
+ view.remove();
+ });
+
+ var viewElem = Ember.$('#'+get(view, 'elementId'));
+ ok(viewElem.length === 0, "view's element doesn't exist in DOM");
+});

0 comments on commit 08d025b

Please sign in to comment.