diff --git a/backbone-polymer-mixin.js b/backbone-polymer-mixin.js index 33e5997..74b716d 100644 --- a/backbone-polymer-mixin.js +++ b/backbone-polymer-mixin.js @@ -1,6 +1,5 @@ var BackbonePolymerAttach = function(element, pathPrefix) { - console.log('BackbonePolymerAttach', this, element, pathPrefix); var indexOf = this.indexOf.bind(this); @@ -14,44 +13,36 @@ var BackbonePolymerAttach = function(element, pathPrefix) { }); }; - var splicesObject = this.models; - - var addNotify = function(model) { - var ix = indexOf(model); - - // https://www.polymer-project.org/1.0/docs/devguide/properties.html#array-observation - var change = {keySplices:[], indexSplices:[]}; - change.keySplices.push({ - index: ix, - removed: [], - removedItems: [], - added: [ix] - }); - change.indexSplices.push({ - index: ix, - addedCount: 1, - removed: [], - object: splicesObject, - type: 'splice', - addedKeys: [ix] - }); - - element.notifyPath(pathPrefix + '.models.splices', change); + this.each(modelSetup.bind(this)); - // remove this timeout and the rendered element goes blank - window.setTimeout(function() { - // TODO would it be possible to notify .* here? - for (var attribute in model.attributes) { - // we could reuse code with modelSetup here - var value = model.get(attribute); - element.notifyPath(pathPrefix + '.models.' + ix + '.attributes.' + attribute, value); - } - }, 1); + // override Backbone add + var _add = this.add; + var addOptions = {add: true, remove: false}; // from backbone source + this.add = function(model, options) { + this.length = this.length + 1; + if (_.isArray(model)) { + throw new Error('backbone-polymer only accepts add of single model'); + } + if (!this._isModel(model)) { + throw new Error('backbone-polymer requires model instances, not just attributes'); + } + if (this.get(model)) { + throw new Error('backbone-polymer model already exists as cid ' + this.get(model).cid); + } + + var options = _.extend({merge: false}, options, addOptions); + var ix = options.at || 0; + + element.splice(pathPrefix + '.models', ix, 0, model); + this._addReference(model, options); + if (!options.silent) { + model.trigger('add', model, this, options); + this.trigger('update', this, options); + } + + modelSetup.call(this, model); + return model; }; - - this.each(modelSetup.bind(this)); - this.on('add', addNotify.bind(this)); - this.on('add', modelSetup.bind(this)); }; if (typeof module !== 'undefined') { diff --git a/test/backbone-compatibility.html b/test/backbone-compatibility.html new file mode 100644 index 0000000..fd9144f --- /dev/null +++ b/test/backbone-compatibility.html @@ -0,0 +1,153 @@ + + +
+ + + + + + + + + + + + + + + + diff --git a/test/test.html b/test/test.html index 5aab32a..1cabfa9 100644 --- a/test/test.html +++ b/test/test.html @@ -85,7 +85,7 @@ }); - it("Uses 'this' for the collection, like a regular Backbone member function", function(done) { + it("Can be used with .call instead of as mixin", function(done) { var element1 = document.querySelector('#collection1'); @@ -106,7 +106,7 @@ expect(renderTimeAllowMs).to.be.at.least(2); // the sequence below is fragile, and there's a timeout in the notification too window.setTimeout(function() { - m1 = c1.add({type: 'text', content: 'As added after setup.'}); + m1 = c1.add(new Backbone.Model({type: 'text', content: 'As added after setup.'})); }, renderTimeAllowMs); window.setTimeout(function() {