ember-computed-change-gate
Advanced tools
Comparing version 0.0.1 to 0.0.2
import Em from 'ember'; | ||
var get = Em.get, | ||
getMeta = Em.getMeta, | ||
setMeta = Em.setMeta; | ||
var get = Em.get; | ||
var defaultFilter = function(value) { console.log('value', value); return value; } | ||
var defaultFilter = function(value) { return value; }; | ||
@@ -12,29 +10,25 @@ export default function(dependentKey, filter) { | ||
return Em.computed(function(key) { | ||
var hasObserverKey = '_changeGate:%@:hasObserver'.fmt(key); | ||
var lastValueKey = '_changeGate:%@:lastValue'.fmt(key); | ||
var isFirstRun = !getMeta(this, hasObserverKey); | ||
var computed = Em.computed(function handler(key) { | ||
if(isFirstRun) { //setup an observer which is responsible for notifying property changes | ||
// debugger; | ||
var value = filter(get(this, dependentKey)); | ||
var lastValueKey = '__changeGate%@LastValue'.fmt(key); | ||
setMeta(this, hasObserverKey, true); | ||
setMeta(this, lastValueKey, value); | ||
var isFirstRun = !this.hasOwnProperty(lastValueKey); | ||
if (isFirstRun) { //setup an observer which is responsible for notifying property changes | ||
this[lastValueKey] = filter.call(this, get(this, dependentKey)); | ||
this.addObserver(dependentKey, function() { | ||
var newValue = filter(get(this, dependentKey)); | ||
var lastValue = getMeta(this, lastValueKey); | ||
var newValue = filter.call(this, get(this, dependentKey)); | ||
var lastValue = this[lastValueKey]; | ||
if(newValue !== lastValue) { | ||
setMeta(this, lastValueKey, newValue); | ||
this[lastValueKey] = newValue; | ||
this.notifyPropertyChange(key); | ||
} | ||
}); | ||
} | ||
return value; | ||
} else { | ||
return getMeta(this, lastValueKey); | ||
} | ||
return this[lastValueKey]; | ||
}); | ||
return computed; | ||
} |
{ | ||
"name": "ember-computed-change-gate", | ||
"version": "0.0.1", | ||
"version": "0.0.2", | ||
"directories": { | ||
@@ -5,0 +5,0 @@ "doc": "doc", |
# ember-computed-change-gate | ||
Observers on Ember.js computed properties are fired regardless of the property value changes or not. `ember-computed-change-gate` only triggers observers when the result of a computed property changes. | ||
[![Build Status](https://travis-ci.org/GavinJoyce/ember-computed-change-gate.svg)](https://travis-ci.org/GavinJoyce/ember-computed-change-gate) | ||
Observers on Ember.js computed properties are fired if a dependant key changes, regardless of whether the property value changes or not. `ember-computed-change-gate` only triggers observers when the result of a computed property changes. | ||
Consider the following example: | ||
@@ -37,5 +39,5 @@ | ||
## [Watch a screencast on how this addon was built >>](https://www.youtube.com/watch?v=PDgvMAyA8ic) | ||
## Watch a screencast showing how this addon was built below | ||
![Image](https://cloud.githubusercontent.com/assets/2526/4349867/d399b15e-41c9-11e4-8319-43c2e06186aa.png) | ||
[![Image](https://cloud.githubusercontent.com/assets/2526/4349867/d399b15e-41c9-11e4-8319-43c2e06186aa.png)](https://www.youtube.com/watch?v=PDgvMAyA8ic) | ||
@@ -42,0 +44,0 @@ Questions? Ping me [@gavinjoyce](https://twitter.com/gavinjoyce) |
@@ -73,1 +73,98 @@ import Em from 'ember'; | ||
}); | ||
test('a changeGate on multiple instances of same class', function(){ | ||
var Paragraph = Em.Object.extend({ | ||
text: 'Hello there', | ||
wordCount: changeGate('text', function(value) { | ||
return value.split(/\s+/).length; | ||
}) | ||
}); | ||
var p1 = Paragraph.create({text: 'Foo Bar baz'}); | ||
var p2 = Paragraph.create({text: 'Bar Foo'}); | ||
equal(p1.get('wordCount'), 3); | ||
equal(p2.get('wordCount'), 2); | ||
var p1Observer = 0; | ||
var p2Observer = 0; | ||
p1.addObserver('wordCount', function() { | ||
p1Observer++; | ||
}); | ||
p2.addObserver('wordCount', function() { | ||
p2Observer++; | ||
}); | ||
p1.set('text', 'Foo Bar Bar Boo'); | ||
equal(p1Observer, 1, "the observer fires once when the value is changed on p1"); | ||
p2.set('text', "Bar Foo Foo"); | ||
equal(p2Observer, 1, "the observer fires once when the value is changed on p2"); | ||
p1.set('text', 'Foo Bar Bar Bar Baa'); | ||
equal(p1Observer, 2, "change to p1 is only recorded on this object, not the other"); | ||
}); | ||
test('multiple changeGate properties on same object', function() { | ||
var Paragraph = Em.Object.extend({ | ||
text: 'Hello there', | ||
wordCount: changeGate('text', function(value) { | ||
return value.split(/\s+/).length; | ||
}), | ||
letterCount: changeGate('text', function(value) { | ||
return value.split('').length; | ||
}) | ||
}); | ||
var p = Paragraph.create(); | ||
var wordCountObserverCount = 0; | ||
var letterCountObserverCount = 0; | ||
p.addObserver('wordCount', function() { | ||
wordCountObserverCount++; | ||
}); | ||
p.addObserver('letterCount', function(){ | ||
letterCountObserverCount++; | ||
}); | ||
equal(p.get('wordCount'), 2); | ||
equal(p.get('letterCount'), 11); | ||
p.set('text', 'Hello there'); | ||
equal(p.get('wordCount'), 2); | ||
equal(p.get('letterCount'), 12); | ||
equal(letterCountObserverCount, 1, "uneffected observer does not fire when another observer is fired"); | ||
p.set('text', 'Hello there you'); | ||
equal(p.get('letterCount'), 15); | ||
equal(p.get('wordCount'), 3); | ||
equal(letterCountObserverCount, 2, "intended observer fires when effected"); | ||
equal(wordCountObserverCount, 1, "uneffected observer does not fire when another observer is fired"); | ||
}); | ||
test("changeGate filter is bound to instance that it's attached to", function(){ | ||
expect(1); | ||
var instance; | ||
var Paragraph = Em.Object.extend({ | ||
text: 'Hello there', | ||
wordCount: changeGate('text', function(value) { | ||
equal(this, instance); | ||
return value.split(/\s+/).length; | ||
}) | ||
}); | ||
instance = Paragraph.create(); | ||
instance.get('wordCount'); | ||
}); |
19541
319
55