Permalink
Browse files

Change scope resolution to use prototype like approach instead of cop…

…ying properties to children scopes.

Use $index instead of index for iteration index property name
  • Loading branch information...
blikblum committed Aug 7, 2016
1 parent 9e70c2b commit 7203c105c194d4d554c4f567c78c437dea8726eb
Showing with 53 additions and 39 deletions.
  1. +22 −1 lib/sightglass.js
  2. +12 −2 spec/rivets/binders.js
  3. +4 −15 spec/rivets/functional.js
  4. +15 −21 src/binders.js
@@ -11,12 +11,12 @@
function Observer(obj, keypath, callback, options) {
this.options = options || {}
this.options.adapters = this.options.adapters || {}
this.obj = obj
this.keypath = keypath
this.callback = callback
this.objectPath = []
this.update = this.update.bind(this)
this.parse()
this.obj = this.getRootObject(obj)

if (isObject(this.target = this.realize())) {
this.set(true, this.key, this.target, this.callback)
@@ -191,6 +191,27 @@
this.set(false, this.key, this.target, this.callback)
}
}
// traverse the scope chain to find the scope which has the root property
// if the property is not found in chain, returns the root scope
Observer.prototype.getRootObject = function (obj) {
var rootProp, current;
if (!obj.$parent) {
return obj;
}

if (this.tokens.length) {
rootProp = this.tokens[0].path
} else {
rootProp = this.key.path
}

current = obj;
while (current.$parent && (current[rootProp] === undefined)) {
current = current.$parent
}

return current;
}

// Check if a value is an object than can be observed.
function isObject(obj) {
@@ -125,8 +125,8 @@ describe("Rivets.binders", function() {
};
});

it.skip("lets you access index from current and parent scope", function() {
nestedEl.textContent = '{%item%}-{%nested%}';
it("lets you access index from current and parent scope", function() {
nestedEl.textContent = '{$parent.$index}-{$index}';
var view = rivets.bind(el, model);

Should(fragment.childNodes[1].childNodes[1].textContent).be.exactly('0-0');
@@ -151,6 +151,16 @@ describe("Rivets.binders", function() {
Should(fragment.childNodes[1].childNodes[2].textContent).be.exactly('New!Level 1 - 0');
Should(fragment.childNodes[2].childNodes[2].textContent).be.exactly('New!Level 1 - 1');
});

it("reflects changes when an undefined property is set in root scope", function() {
nestedEl.textContent = '{unset}';
var view = rivets.bind(el, model);
model.unset = 'NotUndefined';
Should(fragment.childNodes[1].childNodes[1].textContent).be.exactly('NotUndefined');
Should(fragment.childNodes[1].childNodes[2].textContent).be.exactly('NotUndefined');
Should(fragment.childNodes[2].childNodes[2].textContent).be.exactly('NotUndefined');
});

});

describe("if", function() {
@@ -232,28 +232,17 @@ describe('Functional', function() {
el.getElementsByTagName('li')[3].textContent.should.equal('last')
});

it.skip('should allow binding to the iterated element index', function() {
listItem.setAttribute('data-index', 'index');
it('should allow binding to the iterated element index', function() {
listItem.setAttribute('data-index', '$index');
rivets.bind(el, bindData);
el.getElementsByTagName('li')[0].getAttribute('index').should.equal('0');
el.getElementsByTagName('li')[1].getAttribute('index').should.equal('1')
});

it.skip('should allow binding to the iterated element index by using the %item% syntax', function() {
listItem.setAttribute('data-index', '%item%');
rivets.bind(el, bindData);
el.getElementsByTagName('li')[0].getAttribute('index').should.equal('0');
el.getElementsByTagName('li')[1].getAttribute('index').should.equal('1')
});

it.skip('should allow the developer to configure the index attribute available in the iteration', function() {
rivets.configure({
iterationAlias : function(modelName) {
return modelName + 'Index';
}
});

it('should allow the developer to configure the index attribute available in the iteration', function() {
listItem.setAttribute('data-index', 'itemIndex');
listItem.setAttribute('index-property', 'itemIndex');
rivets.bind(el, bindData);
el.getElementsByTagName('li')[0].getAttribute('index').should.equal('0');
el.getElementsByTagName('li')[1].getAttribute('index').should.equal('1')
@@ -143,7 +143,7 @@ const binders = {
priority: 4000,

bind: function(el) {
if (!defined(this.marker)) {
if (!this.marker) {
let attr = [this.view.prefix, this.type].join('-').replace('--', '-')
let declaration = el.getAttribute(attr)

@@ -157,7 +157,7 @@ const binders = {
},

unbind: function() {
if (defined(this.nested)) {
if (this.nested) {
this.nested.unbind()
this.bound = false
}
@@ -166,16 +166,11 @@ const binders = {
routine: function(el, value) {
if (!!value === !this.bound) {
if (value) {
let models = {}

This comment has been minimized.

@Namek

Namek May 23, 2017

do you maybe know if this object was shallow-cloned on purpose? Or did you just remove it from here without thinking about that?

This comment has been minimized.

@blikblum

blikblum May 23, 2017

Owner

I think about that. It fixes the issues of nested scope binding. The related issues are linked in the readme of svelte branch


Object.keys(this.view.models).forEach(key => {
models[key] = this.view.models[key]
})

if (defined(this.nested)) {
if (this.nested) {
this.nested.bind()
} else {
this.nested = rivets.bind(el, models, this.view.options())
this.nested = rivets.bind(el, this.view.models, this.view.options())
}

this.marker.parentNode.insertBefore(el, this.marker.nextSibling)
@@ -189,7 +184,7 @@ const binders = {
},

update: function(models) {
if (defined(this.nested)) {
if (this.nested) {
this.nested.update(models)
}
}
@@ -224,13 +219,13 @@ const binders = {
priority: 1000,

unbind: function(el) {
if (defined(this.handler)) {
if (this.handler) {
unbindEvent(el, this.args[0], this.handler)
}
},

routine: function(el, value) {
if (defined(this.handler)) {
if (this.handler) {
unbindEvent(el, this.args[0], this.handler)
}

@@ -245,7 +240,7 @@ const binders = {
priority: 4000,

bind: function(el) {
if (!defined(this.marker)) {
if (!this.marker) {
let attr = [this.view.prefix, this.type].join('-').replace('--', '-')
this.marker = document.createComment(` rivets: ${this.type} `)
this.iterated = []
@@ -261,7 +256,7 @@ const binders = {
},

unbind: function(el) {
if (defined(this.iterated)) {
if (this.iterated) {
this.iterated.forEach(view => {
view.unbind()
})
@@ -271,6 +266,7 @@ const binders = {
routine: function(el, collection) {
let modelName = this.args[0]
let collection = collection || []
let indexProp = el.getAttribute('index-property') || '$index'

if (this.iterated.length > collection.length) {
times(this.iterated.length - collection.length, () => {
@@ -281,15 +277,11 @@ const binders = {
}

collection.forEach((model, index) => {
let data = {index: index, $parent: this.model}
let data = {$parent: this.view.models}
data[indexProp] = index
data[modelName] = model

if (!defined(this.iterated[index])) {
Object.keys(this.view.models).forEach(key => {
if (!defined(data[key])) {
data[key] = this.view.models[key]
}
})
if (!this.iterated[index]) {

let previous = this.marker

@@ -321,6 +313,8 @@ const binders = {
update: function(models) {
let data = {}

//todo: add test and fix if necessary

Object.keys(models).forEach(key => {
if (key !== this.args[0]) {
data[key] = models[key]

0 comments on commit 7203c10

Please sign in to comment.