Skip to content
This repository has been archived by the owner on Mar 20, 2021. It is now read-only.

Client restore #338

Merged
merged 18 commits into from
Mar 17, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 79 additions & 4 deletions src/collection.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
/*global assignView, assignTemplate, createRegistryWrapper, dataObject, getValue, modelCidAttributeName, viewCidAttributeName */
/*global
$serverSide,
assignView, assignTemplate, createRegistryWrapper, dataObject, getValue,
modelCidAttributeName, modelIdAttributeName, viewCidAttributeName
*/
var _fetch = Backbone.Collection.prototype.fetch,
_set = Backbone.Collection.prototype.set,
_replaceHTML = Thorax.View.prototype._replaceHTML,
Expand Down Expand Up @@ -107,6 +111,51 @@ Thorax.CollectionView = Thorax.View.extend({
}
},

restore: function(el) {
var self = this,
children = this.$el.children(),
toRemove = [];

if (!Thorax.View.prototype.restore.call(this, el)) {
// If we had to rerender for other reasons then we don't need to do anything as it
// was already all blown away
return;
}

this._lookupCollectionElement();

// Find any items annotated with server info and restore. Else rerender
$('[' + modelIdAttributeName + ']', el).each(function() {
var id = this.getAttribute(modelIdAttributeName),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will each collection element have data-model-id and data-model-cid now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct.

model = self.collection.get(id);
if (!model) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry to be sense but if the collection item was rendered for a model in the collection, what would be the case where the model would no longer exist?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two cases: the there is no constant id value and somehow the data changed between data sources between the time that the client and server data was rendered. The later generally shouldn't happen but we want to play it safe.

toRemove.push(this);
} else {
self.restoreItem(model, children.index(this), this);
}
});
$('[data-view-empty]', el).each(function() {
self.restoreEmpty(this);
});

if (toRemove.length) {
// TODO : Is it better to just rerender the whole thing since we don't necessarily
// know what state the list is in at this point?
// Kill off any now invalid nodes
_.each(toRemove, function(el) {
el.parentNode.removeChild(el);
});

// Render anything that we might have locally but was missed
var $el = this._collectionElement;
this.collection.each(function(model) {
if (!$el.find('[' + modelCidAttributeName + '="' + model.cid + '"]').length) {
self.appendItem(model);
}
});
}
},

//appendItem(model [,index])
//appendItem(html_string, index)
//appendItem(view, index)
Expand Down Expand Up @@ -154,7 +203,10 @@ Thorax.CollectionView = Thorax.View.extend({
});

if (model) {
itemElement.attr(modelCidAttributeName, model.cid);
itemElement.attr({
'data-model-id': model.id,
'data-model-cid': model.cid
});
}
var previousModel = index > 0 ? collection.at(index - 1) : false;
if (!previousModel) {
Expand All @@ -166,7 +218,10 @@ Thorax.CollectionView = Thorax.View.extend({
}

this.trigger('append', null, function($el) {
$el.attr(modelCidAttributeName, model.cid);
$el.attr({
'data-model-cid': model.cid,
'data-model-id': model.id,
});
});

if (!options || !options.silent) {
Expand Down Expand Up @@ -258,12 +313,20 @@ Thorax.CollectionView = Thorax.View.extend({
viewOptions.template = this.emptyTemplate;
}
var view = Thorax.Util.getViewInstance(this.emptyView, viewOptions);
view.ensureRendered();
view.$el.attr('data-view-empty', 'true');
return view;
} else {
return this.emptyTemplate && this.renderTemplate(this.emptyTemplate);
}
},
restoreEmpty: function(el) {
var child = this.renderEmpty();

child.restore(el);
this._addChild(child);
return child;
},

renderItem: function(model, i) {
if (!this.itemView) {
assignView.call(this, 'itemView', {
Expand Down Expand Up @@ -294,6 +357,18 @@ Thorax.CollectionView = Thorax.View.extend({
return this.renderTemplate(this.itemTemplate, this.itemContext.call(this, model, i));
}
},
restoreItem: function(model, i, el) {
// Associate the element with the proper model.
el.setAttribute(modelCidAttributeName, model.cid);

// If we are dealing with something other than a template then reinstantiate the view.
if (this.itemView || this.renderItem !== Thorax.CollectionView.prototype.renderItem) {
var child = this.renderItem(model, i);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will this work correctly with the old style (-item templates) as well as with the collection helper?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should but let me add a test case to ensure coverage there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does work. Test case added.


child.restore(el);
this._addChild(child);
}
},
itemContext: function(model /*, i */) {
return model.attributes;
},
Expand Down
11 changes: 9 additions & 2 deletions src/data-object.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*global getValue, inheritVars, listenTo, walkInheritTree */
/*global $serverSide, getValue, inheritVars, listenTo, walkInheritTree */

function dataObject(type, spec) {
spec = inheritVars[type] = _.defaults({
Expand Down Expand Up @@ -36,7 +36,14 @@ function dataObject(type, spec) {
}

this.bindDataObject(type, dataObject, _.extend({}, this.options, options));
$el && $el.attr(spec.cidAttrName, dataObject.cid);
if ($el) {
var attr = {};
if ($serverSide && spec.idAttrName) {
attr[spec.idAttrName] = dataObject.id;
}
attr[spec.cidAttrName] = dataObject.cid;
$el.attr(attr);
}
dataObject.trigger('set', dataObject, old);
} else {
this[type] = false;
Expand Down
8 changes: 5 additions & 3 deletions src/event.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ _.extend(Thorax.View.prototype, {
} else if (!$serverSide) {
// DOM Events
if (!params.nested) {
boundHandler = containHandlerToCurentView(boundHandler, this.cid);
boundHandler = containHandlerToCurentView(boundHandler, this);
}

var name = params.name + '.delegateEvents' + this.cid;
Expand Down Expand Up @@ -168,10 +168,12 @@ pushDomEvents([
'focus', 'blur'
]);

function containHandlerToCurentView(handler, cid) {
function containHandlerToCurentView(handler, current) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change? cid seems to be the only property used

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the cid is stored directly in a closure variable then the changes that
can occur from _assignCid won't be seen, causing the event filtering to
blow up.

On Thu, Mar 13, 2014 at 1:29 PM, Roman Bataev [email protected]:

In src/event.js:

@@ -168,10 +168,10 @@ pushDomEvents([
'focus', 'blur'
]);

-function containHandlerToCurentView(handler, cid) {
+function containHandlerToCurentView(handler, current) {

Why this change? cid seems to be the only property used


Reply to this email directly or view it on GitHubhttps://github.com//pull/338/files#r10578674
.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, gotcha

// Passing the current view rather than just a cid to allow for updates to the view's cid
// caused by the restore process.
return function(event) {
var view = $(event.target).view({helper: false});
if (view && view.cid === cid) {
if (view && view.cid === current.cid) {
event.originalContext = this;
return handler(event);
}
Expand Down
Loading