Comparing version 0.10.15 to 0.10.16
@@ -184,2 +184,5 @@ /* | ||
} | ||
// DEPRECATED: constructor.prototype.view and constructor.prototype.name | ||
var viewFilename = constructor.view || constructor.prototype.view; | ||
var constructorIs = constructor.is || constructor.prototype.name; | ||
@@ -189,11 +192,9 @@ // Inherit from Component | ||
// Load template view from filename | ||
if (constructor.prototype.view) { | ||
var viewFilename = constructor.prototype.view; | ||
viewName = constructor.prototype.name || path.basename(viewFilename, '.html'); | ||
if (viewFilename) { | ||
viewName = viewName || constructorIs || path.basename(viewFilename, '.html'); | ||
this.loadViews(viewFilename, viewName); | ||
} else if (!viewName) { | ||
if (constructor.prototype.name) { | ||
viewName = constructor.prototype.name; | ||
if (constructorIs) { | ||
viewName = constructorIs; | ||
var view = this.views.register(viewName); | ||
@@ -200,0 +201,0 @@ view.template = templates.emptyTemplate; |
@@ -25,7 +25,24 @@ /* | ||
function Component(parent, context, id, scope) { | ||
function Component(context, data) { | ||
var parent = context.controller; | ||
var id = context.id(); | ||
var scope = ['$components', id]; | ||
var model = parent.model.root.eventContext(id); | ||
model._at = scope.join('.'); | ||
data.id = id; | ||
model._set(scope, data); | ||
// Store a reference to the component's scope such that the expression | ||
// getters are relative to the component | ||
model.data = data; | ||
Controller.call(this, parent.app, parent.page, model); | ||
this.parent = parent; | ||
this.context = context; | ||
this.context = context.componentChild(this); | ||
this.id = id; | ||
this._scope = scope; | ||
// Add reference to this component on the page so that all components | ||
// associated with a page can be destroyed when the page transitions | ||
this.page._components[id] = this; | ||
this.isDestroyed = false; | ||
} | ||
@@ -42,2 +59,3 @@ | ||
if (components) delete components.object[this.id]; | ||
this.isDestroyed = true; | ||
}; | ||
@@ -344,2 +362,7 @@ | ||
function ComponentModelData() { | ||
this.id = null; | ||
this.$controller = null; | ||
} | ||
function ComponentFactory(constructor) { | ||
@@ -349,20 +372,13 @@ this.constructor = constructor; | ||
ComponentFactory.prototype.init = function(context) { | ||
var component = new this.constructor(); | ||
var DataConstructor = this.constructor.DataConstructor || ComponentModelData; | ||
var data = new DataConstructor(); | ||
var component = new this.constructor(context, data); | ||
// Detect whether the component constructor already called super by checking | ||
// for one of the properties it sets. If not, call the Component constructor | ||
if (!component.context) { | ||
Component.call(component, context, data); | ||
} | ||
var parent = context.controller; | ||
var id = context.id(); | ||
var scope = ['$components', id]; | ||
var model = parent.model.root.eventContext(component); | ||
model._at = scope.join('.'); | ||
model.set('id', id); | ||
// Store a reference to the component's scope such that the expression | ||
// getters are relative to the component | ||
model.data = model.get(); | ||
parent.page._components[id] = component; | ||
setModelAttributes(component.context, component.model); | ||
var componentContext = context.componentChild(component); | ||
Controller.call(component, parent.app, parent.page, model); | ||
Component.call(component, parent, componentContext, id, scope); | ||
setModelAttributes(componentContext, model); | ||
// Do the user-specific initialization. The component constructor should be | ||
@@ -375,5 +391,5 @@ // an empty function and the actual initialization code should be done in the | ||
component.emit('init', component); | ||
if (component.init) component.init(model); | ||
if (component.init) component.init(component.model); | ||
return componentContext; | ||
return component.context; | ||
}; | ||
@@ -380,0 +396,0 @@ ComponentFactory.prototype.create = function(context) { |
@@ -137,4 +137,4 @@ /* | ||
// filter deletes the main property so that the normal file name lookup happens | ||
function deleteMain(package) { | ||
delete package.main; | ||
function deleteMain() { | ||
return {}; | ||
} |
{ | ||
"name": "derby", | ||
"description": "MVC framework making it easy to write realtime, collaborative applications that run in both Node.js and browsers.", | ||
"version": "0.10.15", | ||
"version": "0.10.16", | ||
"homepage": "http://derbyjs.com/", | ||
@@ -6,0 +6,0 @@ "repository": { |
@@ -9,2 +9,60 @@ var expect = require('chai').expect; | ||
describe('destroy', function() { | ||
it('emits a "destroy" event when the component is removed from the DOM', function(done) { | ||
var app = derby.createApp(); | ||
var page = app.createPage(); | ||
app.views.register('Body', | ||
'{{unless _page.hide}}' + | ||
'<view is="box" as="box"></view>' + | ||
'{{/unless}}' | ||
); | ||
app.views.register('box', '<div></div>'); | ||
function Box() {} | ||
app.component('box', Box); | ||
page.getFragment('Body'); | ||
expect(page.box).instanceof(Box); | ||
page.box.on('destroy', function() { | ||
done(); | ||
}); | ||
page.model.set('_page.hide', true); | ||
}); | ||
it('emits an event declared in the template with `on-destroy`', function(done) { | ||
var app = derby.createApp(); | ||
var page = app.createPage(); | ||
app.views.register('Body', | ||
'{{unless _page.hide}}' + | ||
'<view is="box" on-destroy="destroyBox()"></view>' + | ||
'{{/unless}}' | ||
); | ||
app.views.register('box', '<div></div>'); | ||
function Box() {} | ||
app.component('box', Box); | ||
page.destroyBox = function() { | ||
done(); | ||
}; | ||
page.getFragment('Body'); | ||
page.model.set('_page.hide', true); | ||
}); | ||
it('sets `this.isDestroyed` property to true after a component has been fully destroyed', function() { | ||
var app = derby.createApp(); | ||
var page = app.createPage(); | ||
app.views.register('Body', | ||
'{{unless _page.hide}}' + | ||
'<view is="box" as="box"></view>' + | ||
'{{/unless}}' | ||
); | ||
app.views.register('box', '<div></div>'); | ||
function Box() {} | ||
app.component('box', Box); | ||
page.getFragment('Body'); | ||
var box = page.box; | ||
expect(box.isDestroyed).equal(false); | ||
page.model.set('_page.hide', true); | ||
expect(box.isDestroyed).equal(true); | ||
}); | ||
}); | ||
describe('bind', function() { | ||
@@ -11,0 +69,0 @@ it('calls a function with `this` being the component and passed in arguments', function() { |
4395
171605
33