Skip to content

Commit

Permalink
Merge branch 'jccazeaux-remove-functions-autoexection'
Browse files Browse the repository at this point in the history
  • Loading branch information
benadamstyles committed Feb 10, 2016
2 parents f9d0a45 + 2b5dd9d commit 666c56a
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 6 deletions.
6 changes: 6 additions & 0 deletions docs/docs/guide/_sections/functions-call.md
@@ -0,0 +1,6 @@
To call a function in an expression, rivets includes a special formatter `call`. This formatter will call the function, any formatter parameter will become an argument sent to the function. The following text binding will call the function `event.duration` with the two arguments `event.start` and `event.end`.

```html
<span rv-text="event.duration | call event.start event.end"></span>
```
`event.duration` will be called again every time `event.start` and `event.end` change
5 changes: 4 additions & 1 deletion docs/docs/guide/_sections/usage/configuring.md
Expand Up @@ -23,7 +23,10 @@ rivets.configure({
// Augment the event handler of the on-* binder
handler: function(target, event, binding) {
this.call(target, event, binding.view.models)
}
},

// Since rivets 0.9 functions are not automatically executed in expressions. If you need backward compatibilty, set this parameter to true
executeFunctions: false

})
```
1 change: 1 addition & 0 deletions gulpfile.js
Expand Up @@ -18,6 +18,7 @@ source = [
'src/view.coffee',
'src/bindings.coffee',
'src/binders.coffee',
'src/formatters.coffee',
'src/adapter.coffee',
'src/export.coffee'
]
Expand Down
18 changes: 17 additions & 1 deletion spec/rivets/binding.js
Expand Up @@ -124,12 +124,28 @@ describe('Rivets.Binding', function() {
binding.set('sweater')
binding.binder.routine.calledWith(el, 'awesome sweater').should.be.true
})
})

describe('functions in bindings', function() {
it('does not call methods by default', function() {
sinon.spy(binding.binder, 'routine')
var fn = function() {};
binding.set(fn)
binding.binder.routine.calledWith(el, fn).should.be.true
})

it('calls methods with the object as context', function() {
it('does call methods with model if backward compatibility is set', function() {
rivets.configure({
executeFunctions:true
})
binding.model = {foo: 'bar'}
sinon.spy(binding.binder, 'routine')
binding.set(function() { return this.foo })
binding.binder.routine.calledWith(el, binding.model.foo).should.be.true
// Back to default !!
rivets.configure({
executeFunctions:false
})
})
})

Expand Down
31 changes: 31 additions & 0 deletions spec/rivets/formatters.js
@@ -0,0 +1,31 @@
describe("Rivets.formatters", function() {

describe("call", function() {
var model

beforeEach(function() {
model = {
fn: function(arg1, arg2) {
return '' + arg1 + arg2;
}
}
})

it("calls function with arguments", function() {
rivets.formatters['call'](model.fn, 'foo', 'bar').should.equal('foobar')
})

it("calls function with the model as context", function() {
model.obj = {
name: 'foo',
fn: function() {
return this.name;
}
}
var el = document.createElement('div')
el.setAttribute('rv-text', 'obj.fn | call')
rivets.bind(el, model)
el.innerText.should.equal('foo')
})
})
});
1 change: 1 addition & 0 deletions spec/runner.html
Expand Up @@ -21,6 +21,7 @@

<script src="lib/mock.data.js"></script>
<script src="rivets/binders.js"></script>
<script src="rivets/formatters.js"></script>
<script src="rivets/binding.js"></script>
<script src="rivets/component_binding.js"></script>
<script src="rivets/functional.js"></script>
Expand Down
7 changes: 4 additions & 3 deletions src/bindings.coffee
Expand Up @@ -65,9 +65,9 @@ class Rivets.Binding
observer.value()

if formatter?.read instanceof Function
value = formatter.read value, processedArgs...
value = formatter.read.call @model, value, processedArgs...
else if formatter instanceof Function
value = formatter value, processedArgs...
value = formatter.call @model, value, processedArgs...

value

Expand All @@ -79,7 +79,8 @@ class Rivets.Binding
# Sets the value for the binding. This Basically just runs the binding routine
# with the suplied value formatted.
set: (value) =>
value = if value instanceof Function and !@binder.function
# Since 0.9 : doesn't execute function unless backward compatibility is active
value = if (value instanceof Function and !@binder.function and Rivets.public.executeFunctions)
@formattedValue value.call @model
else
@formattedValue value
Expand Down
6 changes: 6 additions & 0 deletions src/formatters.coffee
@@ -0,0 +1,6 @@
# Core formatters

# Calls a function with arguments
Rivets.public.formatters['call'] = (value, args...) ->
value.call @, args...

6 changes: 5 additions & 1 deletion src/rivets.coffee
Expand Up @@ -5,7 +5,8 @@ Rivets =
'templateDelimiters'
'rootInterface'
'preloadData'
'handler'
'handler',
'executeFunctions'
]

extensions: [
Expand Down Expand Up @@ -41,6 +42,9 @@ Rivets =
# Preload data by default.
preloadData: true,

# Execute functions in bindings. Defaultis false since rivets 0.9. Set to true to be backward compatible with rivets 0.8.
executeFunctions: false,

# Alias for index in rv-each binder
iterationAlias : (modelName) ->
return '%' + modelName + '%'
Expand Down

0 comments on commit 666c56a

Please sign in to comment.