ampersand-view
Advanced tools
Comparing version 8.0.1 to 9.0.0
@@ -27,8 +27,3 @@ /*$AMPERSAND_VERSION*/ | ||
this.on('change:el', this._handleElementChange, this); | ||
this._parsedBindings = bindings(this.bindings, this); | ||
this._initializeBindings(); | ||
if (attrs.el && !this.autoRender) { | ||
this._handleElementChange(); | ||
} | ||
this._initializeSubviews(); | ||
this._upsertBindings(); | ||
this.template = attrs.template || this.template; | ||
@@ -158,2 +153,3 @@ this._cache.rendered = false; // prep `rendered` derived cache immediately | ||
_render: function () { | ||
this._upsertBindings(); | ||
this.renderWithTemplate(this); | ||
@@ -167,16 +163,5 @@ this._rendered = true; | ||
_remove: function () { | ||
var parsedBindings = this._parsedBindings; | ||
if (this.el && this.el.parentNode) this.el.parentNode.removeChild(this.el); | ||
this._rendered = false; | ||
if (this._subviews) invoke(flatten(this._subviews), 'remove'); | ||
this.stopListening(); | ||
// TODO: Not sure if this is actually necessary. | ||
// Just trying to de-reference this potentially large | ||
// amount of generated functions to avoid memory leaks. | ||
forEach(parsedBindings, function (properties, modelName) { | ||
forEach(properties, function (value, key) { | ||
delete parsedBindings[modelName][key]; | ||
}); | ||
delete parsedBindings[modelName]; | ||
}); | ||
this._downsertBindings(); | ||
return this; | ||
@@ -246,5 +231,5 @@ }, | ||
} | ||
if (!container) container = this.el; | ||
this.registerSubview(view); | ||
view.render(); | ||
(container || this.el).appendChild(view.el); | ||
container.appendChild(view.render().el); | ||
return view; | ||
@@ -294,5 +279,4 @@ }, | ||
waitFor: subview.waitFor || '', | ||
prepareView: subview.prepareView || function (el) { | ||
prepareView: subview.prepareView || function () { | ||
return new subview.constructor({ | ||
el: el, | ||
parent: self | ||
@@ -308,4 +292,8 @@ }); | ||
subview = this[name] = opts.prepareView.call(this, el); | ||
subview.render(); | ||
this.registerSubview(subview); | ||
if (!subview.el) { | ||
this.renderSubview(subview, el); | ||
} else { | ||
subview.render(); | ||
this.registerSubview(subview); | ||
} | ||
this.off('change', action); | ||
@@ -429,2 +417,31 @@ } | ||
}); | ||
}, | ||
_downsertBindings: function() { | ||
var parsedBindings = this._parsedBindings; | ||
if (!this.bindingsSet) return; | ||
if (this._subviews) invoke(flatten(this._subviews), 'remove'); | ||
this.stopListening(); | ||
// TODO: Not sure if this is actually necessary. | ||
// Just trying to de-reference this potentially large | ||
// amount of generated functions to avoid memory leaks. | ||
forEach(parsedBindings, function (properties, modelName) { | ||
forEach(properties, function (value, key) { | ||
delete parsedBindings[modelName][key]; | ||
}); | ||
delete parsedBindings[modelName]; | ||
}); | ||
this.bindingsSet = false; | ||
}, | ||
_upsertBindings: function(attrs) { | ||
attrs = attrs || this; | ||
if (this.bindingsSet) return; | ||
this._parsedBindings = bindings(this.bindings, this); | ||
this._initializeBindings(); | ||
if (attrs.el && !this.autoRender) { | ||
this._handleElementChange(); | ||
} | ||
this._initializeSubviews(); | ||
this.bindingsSet = true; | ||
} | ||
@@ -431,0 +448,0 @@ }); |
{ | ||
"name": "ampersand-view", | ||
"description": "A smart base view for Backbone apps, to make it easy to bind collections and properties to the DOM.", | ||
"version": "8.0.1", | ||
"version": "9.0.0", | ||
"author": "Henrik Joreteg <henrik@andyet.net>", | ||
@@ -6,0 +6,0 @@ "browser": "./ampersand-view.js", |
# ampersand-view | ||
Lead Maintainer: [Christopher Dieringer](https://github.com/cdaringe) | ||
A set of common helpers and conventions for using as a base view for ampersand.js apps. | ||
@@ -602,3 +604,5 @@ | ||
## Changelog | ||
- 9.0.0 | ||
- support render-remove-render view instance lifecycle. previously bindings were trashed for good on remove() | ||
- subviews declared in the subviews hash by default append the subview-el into its target, vs replace its target | ||
- 8.0.0 Improve `rendered` property behavior. `rendered` now set after calling render()/remove() fns, vs. old strategy which simply checked for `view.el` | ||
@@ -605,0 +609,0 @@ - 7.0.0 Replacing use of `role` in lieu of `data-hook` for [accessibility reasons discussed here](https://github.com/AmpersandJS/ampersand/issues/21) |
@@ -785,2 +785,29 @@ var test = require('tape'); | ||
t.equal(view.el.innerHTML, '<div class="container"><span></span></div>'); | ||
t.end(); | ||
}); | ||
test('declarative subViews basics (with prepareView which tests pre-issue#87 functionality)', function (t) { | ||
var Sub = AmpersandView.extend({ | ||
template: '<span></span>' | ||
}); | ||
var View = AmpersandView.extend({ | ||
template: '<div><div class="container"></div></div>', | ||
autoRender: true, | ||
subviews: { | ||
sub1: { | ||
selector: '.container', | ||
constructor: Sub, | ||
prepareView: function (el) { | ||
return new Sub({ | ||
el: el | ||
}); | ||
} | ||
} | ||
} | ||
}); | ||
var view = new View(); | ||
t.equal(view.el.innerHTML, '<span></span>'); | ||
@@ -808,3 +835,3 @@ | ||
t.equal(view.el.innerHTML, '<span></span>'); | ||
t.equal(view.el.innerHTML, '<div class="container"><span></span></div>'); | ||
@@ -831,3 +858,3 @@ t.end(); | ||
t.equal(view.el.innerHTML, '<span></span>'); | ||
t.equal(view.el.innerHTML, '<div data-hook="test.hi-there"><span></span></div>'); | ||
@@ -866,5 +893,5 @@ t.end(); | ||
t.equal(view._events.change.length, 1); | ||
t.equal(view.el.outerHTML, '<div><span>yes</span><span data-hook="sub"></span></div>'); | ||
t.equal(view.el.outerHTML, '<div><span class="container"><span>yes</span></span><span data-hook="sub"></span></div>'); | ||
view.model2 = new Model(); | ||
t.equal(view.el.outerHTML, '<div><span>yes</span><span>yes</span></div>'); | ||
t.equal(view.el.outerHTML, '<div><span class="container"><span>yes</span></span><span data-hook="sub"><span>yes</span></span></div>'); | ||
t.notOk(view._events.change); | ||
@@ -923,1 +950,35 @@ | ||
}); | ||
test('render, remove, render yields consistent subview behavior', function (t) { | ||
t.plan(1); | ||
var event = document.createEvent("MouseEvent"); | ||
var parentEl = document.createElement('div'); | ||
var childContainerEl = document.createElement('div'); | ||
childContainerEl.id = 'child_container'; | ||
parentEl.appendChild(childContainerEl); | ||
var Child = AmpersandView.extend({ | ||
template: function() { return document.createElement('div'); }, | ||
events: { | ||
'click div': 'divClicked' | ||
}, | ||
divClicked: function (e) { | ||
t.ok(true, 'child view bindings withheld through parent render/remove/render cycle'); | ||
t.end(); | ||
} | ||
}); | ||
var Parent = AmpersandView.extend({ | ||
template: function() { return parentEl; }, | ||
subviews: { | ||
childv: { | ||
selector: '#child_container', | ||
constructor: Child | ||
} | ||
} | ||
}); | ||
var parent = new Parent({ el: document.createElement('div') }); | ||
parent.render(); | ||
parent.remove(); | ||
parent.render(); | ||
event.initMouseEvent('click'); | ||
parent.childv.el.dispatchEvent(event); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
83345
1560
636