forked from theironcook/Backbone.ModelBinder
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBackbone.ModelBinder.min.js
37 lines (36 loc) · 10.9 KB
/
Backbone.ModelBinder.min.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// Backbone.ModelBinder v0.1.6
// (c) 2012 Bart Wood
// Distributed Under MIT License
(function(factory){if(typeof define==='function'&&define.amd){define(['underscore','jquery','backbone'],factory);}else{factory(_,$,Backbone);}}(function(_,$,Backbone){if(!Backbone){throw'Please include Backbone.js before Backbone.ModelBinder.js';}
Backbone.ModelBinder=function(modelSetOptions){_.bindAll(this);this._modelSetOptions=modelSetOptions||{};};Backbone.ModelBinder.VERSION='0.1.5';Backbone.ModelBinder.Constants={};Backbone.ModelBinder.Constants.ModelToView='ModelToView';Backbone.ModelBinder.Constants.ViewToModel='ViewToModel';_.extend(Backbone.ModelBinder.prototype,{bind:function(model,rootEl,attributeBindings,modelSetOptions){this.unbind();this._model=model;this._rootEl=rootEl;this._modelSetOptions=_.extend({},this._modelSetOptions,modelSetOptions);if(!this._model)throw'model must be specified';if(!this._rootEl)throw'rootEl must be specified';if(attributeBindings){this._attributeBindings=$.extend(true,{},attributeBindings);this._initializeAttributeBindings();this._initializeElBindings();}
else{this._initializeDefaultBindings();}
this._bindModelToView();this._bindViewToModel();},unbind:function(){this._unbindModelToView();this._unbindViewToModel();if(this._attributeBindings){delete this._attributeBindings;this._attributeBindings=undefined;}},_initializeAttributeBindings:function(){var attributeBindingKey,inputBinding,attributeBinding,elementBindingCount,elementBinding;for(attributeBindingKey in this._attributeBindings){inputBinding=this._attributeBindings[attributeBindingKey];if(_.isString(inputBinding)){attributeBinding={elementBindings:[{selector:inputBinding}]};}
else if(_.isArray(inputBinding)){attributeBinding={elementBindings:inputBinding};}
else if(_.isObject(inputBinding)){attributeBinding={elementBindings:[inputBinding]};}
else{throw'Unsupported type passed to Model Binder '+attributeBinding;}
for(elementBindingCount=0;elementBindingCount<attributeBinding.elementBindings.length;elementBindingCount++){elementBinding=attributeBinding.elementBindings[elementBindingCount];elementBinding.attributeBinding=attributeBinding;}
attributeBinding.attributeName=attributeBindingKey;this._attributeBindings[attributeBindingKey]=attributeBinding;}},_initializeDefaultBindings:function(){var elCount,namedEls,namedEl,name,attributeBinding;this._attributeBindings={};namedEls=$('[name]',this._rootEl);for(elCount=0;elCount<namedEls.length;elCount++){namedEl=namedEls[elCount];name=$(namedEl).attr('name');if(!this._attributeBindings[name]){attributeBinding={attributeName:name};attributeBinding.elementBindings=[{attributeBinding:attributeBinding,boundEls:[namedEl]}];this._attributeBindings[name]=attributeBinding;}
else{this._attributeBindings[name].elementBindings.push({attributeBinding:this._attributeBindings[name],boundEls:[namedEl]});}}},_initializeElBindings:function(){var bindingKey,attributeBinding,bindingCount,elementBinding,foundEls,elCount,el;for(bindingKey in this._attributeBindings){attributeBinding=this._attributeBindings[bindingKey];for(bindingCount=0;bindingCount<attributeBinding.elementBindings.length;bindingCount++){elementBinding=attributeBinding.elementBindings[bindingCount];if(elementBinding.selector===''){foundEls=$(this._rootEl);}
else{foundEls=$(elementBinding.selector,this._rootEl);}
if(foundEls.length===0){throw'Bad binding found. No elements returned for binding selector '+elementBinding.selector;}
else{elementBinding.boundEls=[];for(elCount=0;elCount<foundEls.length;elCount++){el=foundEls[elCount];elementBinding.boundEls.push(el);}}}}},_bindModelToView:function(){this._model.on('change',this._onModelChange,this);this.copyModelAttributesToView();},copyModelAttributesToView:function(attributesToCopy){var attributeName,attributeBinding;for(attributeName in this._attributeBindings){if(attributesToCopy===undefined||_.indexOf(attributesToCopy,attributeName)!==-1){attributeBinding=this._attributeBindings[attributeName];this._copyModelToView(attributeBinding);}}},_unbindModelToView:function(){if(this._model){this._model.off('change',this._onModelChange);this._model=undefined;}},_bindViewToModel:function(){$(this._rootEl).delegate('','change',this._onElChanged);$(this._rootEl).delegate('[contenteditable]','blur',this._onElChanged);},_unbindViewToModel:function(){if(this._rootEl){$(this._rootEl).undelegate('','change',this._onElChanged);$(this._rootEl).undelegate('[contenteditable]','blur',this._onElChanged);}},_onElChanged:function(event){var el,elBindings,elBindingCount,elBinding;el=$(event.target)[0];elBindings=this._getElBindings(el);for(elBindingCount=0;elBindingCount<elBindings.length;elBindingCount++){elBinding=elBindings[elBindingCount];if(this._isBindingUserEditable(elBinding)){this._copyViewToModel(elBinding,el);}}},_isBindingUserEditable:function(elBinding){return elBinding.elAttribute===undefined||elBinding.elAttribute==='text'||elBinding.elAttribute==='html';},_getElBindings:function(findEl){var attributeName,attributeBinding,elementBindingCount,elementBinding,boundElCount,boundEl;var elBindings=[];for(attributeName in this._attributeBindings){attributeBinding=this._attributeBindings[attributeName];for(elementBindingCount=0;elementBindingCount<attributeBinding.elementBindings.length;elementBindingCount++){elementBinding=attributeBinding.elementBindings[elementBindingCount];for(boundElCount=0;boundElCount<elementBinding.boundEls.length;boundElCount++){boundEl=elementBinding.boundEls[boundElCount];if(boundEl===findEl){elBindings.push(elementBinding);}}}}
return elBindings;},_onModelChange:function(){var changedAttribute,attributeBinding;for(changedAttribute in this._model.changedAttributes()){attributeBinding=this._attributeBindings[changedAttribute];if(attributeBinding){this._copyModelToView(attributeBinding);}}},_copyModelToView:function(attributeBinding){var elementBindingCount,elementBinding,boundElCount,boundEl,value,convertedValue;value=this._model.get(attributeBinding.attributeName);for(elementBindingCount=0;elementBindingCount<attributeBinding.elementBindings.length;elementBindingCount++){elementBinding=attributeBinding.elementBindings[elementBindingCount];for(boundElCount=0;boundElCount<elementBinding.boundEls.length;boundElCount++){boundEl=elementBinding.boundEls[boundElCount];if(!boundEl._isSetting){convertedValue=this._getConvertedValue(Backbone.ModelBinder.Constants.ModelToView,elementBinding,value);this._setEl($(boundEl),elementBinding,convertedValue);}}}},_setEl:function(el,elementBinding,convertedValue){if(elementBinding.elAttribute){this._setElAttribute(el,elementBinding,convertedValue);}
else{this._setElValue(el,convertedValue);}},_setElAttribute:function(el,elementBinding,convertedValue){switch(elementBinding.elAttribute){case'html':el.html(convertedValue);break;case'text':el.text(convertedValue);break;case'enabled':el.attr('disabled',!convertedValue);break;case'displayed':el[convertedValue?'show':'hide']();break;case'hidden':el[convertedValue?'hide':'show']();break;case'css':el.css(elementBinding.cssAttribute,convertedValue);break;case'class':var previousValue=this._model.previous(elementBinding.attributeBinding.attributeName);if(!_.isUndefined(previousValue)){previousValue=this._getConvertedValue(Backbone.ModelBinder.Constants.ModelToView,elementBinding,previousValue);el.removeClass(previousValue);}
if(convertedValue){el.addClass(convertedValue);}
break;default:el.attr(elementBinding.elAttribute,convertedValue);}},_setElValue:function(el,convertedValue){if(el.attr('type')){switch(el.attr('type')){case'radio':if(el.val()===convertedValue){el.attr('checked','checked');}
break;case'checkbox':if(convertedValue){el.attr('checked','checked');}
else{el.removeAttr('checked');}
break;default:el.val(convertedValue);}}
else if(el.is('input')||el.is('select')||el.is('textarea')){el.val(convertedValue);}
else{el.text(convertedValue);}},_copyViewToModel:function(elementBinding,el){var value,convertedValue;if(!el._isSetting){el._isSetting=true;this._setModel(elementBinding,$(el));el._isSetting=false;if(elementBinding.converter){value=this._model.get(elementBinding.attributeBinding.attributeName);convertedValue=this._getConvertedValue(Backbone.ModelBinder.Constants.ModelToView,elementBinding,value);this._setEl($(el),elementBinding,convertedValue);}}},_getElValue:function(elementBinding,el){switch(el.attr('type')){case'checkbox':return el.prop('checked')?true:false;default:if(el.attr('contenteditable')!==undefined){return el.html();}
else{return el.val();}}},_setModel:function(elementBinding,el){var data={};var elVal=this._getElValue(elementBinding,el);elVal=this._getConvertedValue(Backbone.ModelBinder.Constants.ViewToModel,elementBinding,elVal);data[elementBinding.attributeBinding.attributeName]=elVal;var opts=_.extend({},this._modelSetOptions,{changeSource:'ModelBinder'});this._model.set(data,opts);},_getConvertedValue:function(direction,elementBinding,value){if(elementBinding.converter){value=elementBinding.converter(direction,value,elementBinding.attributeBinding.attributeName,this._model);}
return value;}});Backbone.ModelBinder.CollectionConverter=function(collection){this._collection=collection;if(!this._collection){throw'Collection must be defined';}
_.bindAll(this,'convert');};_.extend(Backbone.ModelBinder.CollectionConverter.prototype,{convert:function(direction,value){if(direction===Backbone.ModelBinder.Constants.ModelToView){return value?value.id:undefined;}
else{return this._collection.get(value);}}});Backbone.ModelBinder.createDefaultBindings=function(rootEl,attributeType,converter,elAttribute){var foundEls,elCount,foundEl,attributeName;var bindings={};foundEls=$('['+attributeType+']',rootEl);for(elCount=0;elCount<foundEls.length;elCount++){foundEl=foundEls[elCount];attributeName=$(foundEl).attr(attributeType);if(!bindings[attributeName]){var attributeBinding={selector:'['+attributeType+'="'+attributeName+'"]'};bindings[attributeName]=attributeBinding;if(converter){bindings[attributeName].converter=converter;}
if(elAttribute){bindings[attributeName].elAttribute=elAttribute;}}}
return bindings;};Backbone.ModelBinder.combineBindings=function(destination,source){_.each(source,function(value,key){var elementBinding={selector:value.selector};if(value.converter){elementBinding.converter=value.converter;}
if(value.elAttribute){elementBinding.elAttribute=value.elAttribute;}
if(!destination[key]){destination[key]=elementBinding;}
else{destination[key]=[destination[key],elementBinding];}});};return Backbone.ModelBinder;}));var is={ie:navigator.appName=='Microsoft Internet Explorer',java:navigator.javaEnabled(),ns:navigator.appName=='Netscape',ua:navigator.userAgent.toLowerCase(),version:parseFloat(navigator.appVersion.substr(21))||parseFloat(navigator.appVersion),win:navigator.platform=='Win32'}
is.mac=is.ua.indexOf('mac')>=0;if(is.ua.indexOf('opera')>=0){is.ie=is.ns=false;is.opera=true;}
if(is.ua.indexOf('gecko')>=0){is.ie=is.ns=false;is.gecko=true;}