Rivets.js / jQuery Binding Issue
by dswitzer
HTML
<script src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script src="https://rawgithub.com/mikeric/rivets/master/dist/rivets.min.js"></script>
<script src="https://rawgithub.com/azproduction/rivets-backbone-adapter/master/rivets-backbone.js"></script>
<div>
<h2>Normal Field</h2>
<p>Manually enter a numeric value</p>
<input type="text" data-bind-value="model.counter" />
</div>
<div>
<h2>jQuery Plugin</h2>
<p>Click the button below to increment</p>
<input type="text" data-bind-incrementer="model.counter" id="incrementer" />
</div>
<div>
<h2>Backbone</h2>
<p>Clicking the button below fires of the "rountine" binder twice. This is because the set fires off the routine, which then ultimately triggers an "update" event, which fires off the set method again.</p>
<button onclick="Tracker.increment();">Increase</button>
</div>
<div>
<h3>
Bound Value:
<span data-bind-text="model.counter"></span>
</h3>
</div>
JavaScript
/* backbone */
var Tracker = new Backbone.Model({counter:0});
Tracker.increment = function (){
Tracker.set("counter", parseInt(Tracker.get("counter"), 10) +1);
}
Tracker.on("change:counter", function (){
console.log("log: " + this.get("counter"));
});
/* rivets */
/* global rivets configuration */
rivets.configure({
prefix: "bind"
});
/* generic binder handlers for jQuery plugins */
rivets.ext = (function (ext){
// set up the jQuery extension
if( !ext.jQuery ) ext.jQuery = {binder: {}};
function getKeyName(name, key){
return "rivets.binders." + name + "." + key;
};
ext.jQuery.binder.isRunning = function(name, el){
return !!$(el).data(getKeyName(name, "isRunning"));
}
ext.jQuery.binder.listener = function (name, self, el){
var args = arguments
, isPublishing = getKeyName(name, "isPublishing")
, $el = $(el);
return function (){
var isRunning = ext.jQuery.binder.isRunning(name, el), results;
// if the model logic is already running, don't run again
if( !isRunning ){
// mark that we're in a routine
$el.data(isPublishing, true);
// the plugin has been updated, publish the results
results = self.publish.apply(el, args);
// mark that we're in a routine
$el.data(isPublishing, false);
}
return results;
};
};
ext.jQuery.binder.routine = function (name, callback){
var isRunning = getKeyName(name, "isRunning")
, isPublishing = getKeyName(name, "isPublishing");
return function (el, value){
var $el = $(el);
// if we're publishing the results, stop process to avoid calling the plugin logic again
if( $el.data(isPublishing) === true ) return;
// mark that we're in a routine
$el.data(isRunning, true);
// the model has changed, so update the plugin
callback.apply(this, [el, value, $el]);
// set we're out of the routine
$el.data(isRunning, false);
};
};
return ext;
})(rivets.ext || {});
var rountineCounter = 0;
/* start custom binders...