Skip to content

Instantly share code, notes, and snippets.

@steve8708
Last active December 22, 2015 02:08
Show Gist options
  • Save steve8708/6400844 to your computer and use it in GitHub Desktop.
Save steve8708/6400844 to your computer and use it in GitHub Desktop.
Bind nested Bacbone models and collections to Ractive views!
// An adaptor for binding Ractive.js views with nested Backbone models and collections via
// backbone-associations (https://github.com/dhruvaray/backbone-associations)
//
// Based on the original Backbone adaptor for Ractive by Rich Harris:
// https://github.com/Rich-Harris/Ractive/blob/master/src/Ractive/Ractive.adaptors/backbone.js
Ractive.adaptors.backboneAssociatedModel = function ( model, path ) {
var settingModel, settingView, setModel, setView, pathMatcher, pathLength, prefix, modelChangeEventHandler;
if ( path ) {
path += '.';
pathMatcher = new RegExp( '^' + path.replace( /\./g, '\\.' ) );
pathLength = path.length;
}
modelChangeEventHandler = function ( eventName ) {
var eventNameSplit, eventType, keypath, value;
eventNameSplit = eventName.split( ':' );
eventType = eventNameSplit[0];
keypath = eventNameSplit[1];
if ( eventType === 'change' && keypath ) {
value = model.get( keypath );
if ( value && value.toJSON ) {
value = value.toJSON();
}
setView( keypath, value );
}
};
return {
init: function ( view ) {
// if no path specified...
if ( !path ) {
setView = function ( keypath, value ) {
if ( !settingModel ) {
settingView = true;
view.set( keypath, value );
settingView = false;
}
};
setModel = function ( keypath, value ) {
if ( !settingView ) {
settingModel = true;
model.set( keypath, value );
settingModel = false;
}
};
}
else {
prefix = function ( attrs ) {
var attr, result;
result = {};
for ( attr in attrs ) {
if ( ({}).hasOwnProperty.call( attrs, attr ) ) {
result[ path + attr ] = attrs[ attr ];
}
}
return result;
};
setView = function ( keypath, value ) {
if ( !settingModel ) {
settingView = true;
var changed = {};
changed[keypath] = value;
view.set( prefix( model.changed ) );
settingView = false;
}
};
setModel = function ( keypath, value ) {
if ( !settingView ) {
if ( pathMatcher.test( keypath ) ) {
settingModel = true;
model.set( keypath.substring( pathLength ), value );
settingModel = false;
}
}
};
}
model.on( 'all', modelChangeEventHandler );
view.on( 'set', setModel );
// initialise
view.set( path ? prefix( model.toJSON() ) : model.toJSON() );
},
teardown: function ( view ) {
model.off( 'all', modelChangeEventHandler );
view.off( 'set', setModel );
}
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment