{"_id":"backbone.modelbinder","_rev":"3-9fd0cba755f6b835f52cd0f3249724e7","name":"backbone.modelbinder","description":"Simple, flexible and powerful Model-View binding for Backbone.","dist-tags":{"latest":"1.1.0"},"versions":{"1.1.0":{"name":"backbone.modelbinder","description":"Simple, flexible and powerful Model-View binding for Backbone.","version":"1.1.0","author":{"name":"Bart Wood"},"bugs":{"url":"https://github.com/theironcook/Backbone.ModelBinder/issues"},"dependencies":{"backbone":">=0.9.0","jquery":">=1.7.1","underscore":">=1.3.1"},"directories":{"example":"examples"},"files":["Backbone.ModelBinder.js","Backbone.CollectionBinder.js"],"homepage":"https://github.com/theironcook/Backbone.ModelBinder#readme","keywords":["backbone","model","view"],"license":"MIT","main":"Backbone.ModelBinder.js","repository":{"type":"git","url":"git+https://github.com/theironcook/Backbone.ModelBinder.git"},"scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"url":"https://github.com/theironcook/Backbone.ModelBinder","gitHead":"f490f9e1f92b0aa427caef43d3591fc79b2188d0","_id":"backbone.modelbinder@1.1.0","_shasum":"2d209338fe37303366035c382abafd2bc74c8994","_from":".","_npmVersion":"2.7.4","_nodeVersion":"0.12.2","_npmUser":{"name":"theironcook","email":"bartwood@gmail.com"},"dist":{"shasum":"2d209338fe37303366035c382abafd2bc74c8994","tarball":"https://registry.npmjs.org/backbone.modelbinder/-/backbone.modelbinder-1.1.0.tgz","integrity":"sha512-bBdpzLvqHj8pGTpm6aaOYKKgJjFhPWXihXa6Tajjk7uquR+0sl+hbTR90dhZ3CC/TmUUMadwh+oEJDIvmgGlkQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIC/EnZCF3hqQ6Q5pq4qlazt+uUNm0WEEvO1w37yrXXc8AiAwzl+fExj6kslTNZGp2+uXlXbGJeI5ZBX1DusLU3+9Dg=="}]},"maintainers":[{"name":"theironcook","email":"bartwood@gmail.com"}]}},"readme":"Special thanks to [Derick Bailey](http://lostechies.com/derickbailey) for creating predecessor to this plugin.\r\nI've been able to reuse unit tests he created for his [Backbone.ModelBinding](https://github.com/derickbailey/backbone.modelbinding) plugin.\r\n\r\n\r\n### Rationale\r\nBackbone is a great platform for writing client side applications but I've found that as views grow in complexity, synchronizing my models and views can be a pain.\r\nI've spent the past few months trying to use existing view-model binding libraries that others were kind enough to create and share with the world.\r\nUnfortunately in the majority of my backbone application I wasn't able to leverage the existing view-model binding libraries due to various limitations.\r\n\r\nI created a new `Backbone.ModelBinder` class that I have leveraged in the majority of a large client side application.\r\nThe ModelBinder class helped me remove a lot of cluttered boilerplate code that existed to synchronize my models and views.\r\nAs my application became more asynchronous, the ModelBinder saves me from a lot of pain by automatically displaying model attributes in the view as they are asynchronously loaded.\r\nHopefully you'll find the ModelBinder useful too.\r\n\r\nThe `Backbone.ModelBinder` class:\r\n\r\n* Is as simple as possible yet still flexible and powerful\r\n* Leverages the exact same jQuery syntax that the Backbone.View event blocks use\r\n* Allows you to define type formatting and type conversion in your bindings\r\n* Provides a simple javascript only solution rather than mixing binding syntax in html templates and javascript files.  I personally find mixing binding logic in my html files to be messy and confusing.\r\n\r\n<br>\r\nYou can use this ModelBinder class to bind backbone model attributes to:\r\n\r\n* Read-only html elements such as `<span>`, `<div>` etc.\r\n* Html element attributes such as enabled, displayed, style etc.\r\n* Editable form elements such as `<input>`, `<textarea>` etc. This type of binding is bidirectional between the html elements and the Model's attributes.\r\n\r\n<br>\r\n###The ModelBinder is more efficient###\r\nIt seems like many of the backbone view examples I've seen register for the model's change event and then re-render the entire view like the example shown below.\r\n\r\n````\r\nSomeView = Backbone.View.extend({\r\n    initialize: function(){\r\n        this.model.on('change', this.render, this);\r\n    },\r\n\r\n    render: function() {\r\n        this.$el.html(this.template(this.model.toJSON()));\r\n        return this;\r\n    }\r\n});\r\n````\r\nIf the model changes frequently the above type of code will be wasteful because so many DOM elements are just thrown away. Converting the model to json is also an unnecessary conversion.\r\n\r\nThe ModelBinder eliminates these ineffeciencies by listening for model changes like the above code. But it doesn't recreate the entire set of DOM elements. Instead, it will change the content of existing DOM elements.\r\n\r\n\r\n<br>\r\n## Prerequisites\r\n\r\n* Backbone.js v1.0.0 or higher\r\n* Underscore.js v1.4.4 or higher\r\n* jQuery v1.8.3 or higher\r\n\r\n\r\n<br>\r\n### Availability\r\nYou can download the zip/tarball as normal and include it with your other JS assets, but you can now alternatively link to it on [CDNJS](http://www.cdnjs.com/), the free to use, community maintained CDN.\r\n\r\nTo do this, just drop a reference to the minified version of the plugin into your document's `<head>` as follows, replacing the version number with whatever the latest one is:\r\n````\r\n<script type=\"text/javascript\" src=\"//cdnjs.cloudflare.com/ajax/libs/backbone.modelbinder/1.0.4/Backbone.ModelBinder.min.js\"></script>\r\n````\r\n\r\n\r\n<br>\r\n##Defining Binding Scope with jQuery##\r\n\r\nOne of the most powerful capabilities of the ModelBinder class is that it allows you to define scope when you create your bindings using jQuery.\r\n\r\n* If your views are simple (no nested Views etc.) you can rely on default scoping rules that are based off of the html `name` attribute.\r\n* If your views are more complex you can explicitly define scoping rules with jQuery selectors. Scoping will allow you to handle nested views or have the ModelBinder only manage parts of your Views and your own custom code can handle the more complicated problems.\r\n\r\nBoth scoping mechanisms will be discussed throughout the rest of this document.\r\n\r\n***\r\n\r\n##Basic ModelBinder functionality##\r\n\r\nThe `ModelBinder` class contains all of the logic to facilitate bi-directional view-model binding.\r\n\r\nThe ModelBinder class exposes 3 public functions shown below:\r\n\r\n```javascript\r\n// no arguments passed to the constructor\r\nconstructor();\r\n\r\n// model is required, it is the backbone Model you're binding to\r\n// rootEl is required, is the root html element containing the elements you want to bind to\r\n// bindings is optional, it's discussed a bit later\r\n// options, discussed at the bottom of the document\r\nbind(model, rootEl, bindings, options);\r\n\r\n// unbinds the Model with the elements found under rootEl - defined when calling bind()\r\nunbind();\r\n```\r\n\r\n<br>\r\nThe `bind()` function's 3rd argument `bindings` is optional.  The `bindings` arg is useful for defining binding scope and formatting and will be discussed later.\r\nIf `bindings` is not defined, then `bind()` will locate all of the child elements under the rootEl that define a `name` attribute.\r\nEach of the elements with a `name` attribute will be bound to the model's attributes - the value of the element's name attribute will be used as the model's attribute name.\r\n\r\nIn the example below, the model's address attribute will be bound to the input text field with the name of 'address'.  This binding is bi-directional between the view and the model.\r\n\r\n````\r\n<!-- The html -->\r\n<input type=\"text\" name=\"address\"/>\r\n````\r\n\r\n````\r\n<!-- The javascript -->\r\nSomeView = Backbone.View.extend({\r\n    render: function(){\r\n        this.modelBinder.bind(this.model, this.el);\r\n    }\r\n});\r\n````\r\n\r\n<br>\r\n## Binding after elements created, rootEl ##\r\n\r\nThe bind() functions `rootEl` parameter should contain all of the elements that you want to bind to.\r\nYour rootEl might be the view.el property or it could be any valid html element.  It does not matter if the rootEl is displayed in a browser.\r\n\r\nThe example below shows how the rootEl argument is the result of the jQuery selection \"#outerDiv\".  This will work just like the previous example.\r\n\r\n````\r\n<!-- The html -->\r\n<div id=\"outerDiv\">\r\n    <input type=\"text\" name=\"address\"/>\r\n</div>\r\n````\r\n\r\n````\r\n<!-- The javascript -->\r\nSomeView = Backbone.View.extend({\r\n    render: function(){\r\n        this.modelBinder.bind(this.model, this.$('#outerDiv'));\r\n    }\r\n});\r\n````\r\n\r\n<br>\r\n## Elements are recursively bound ##\r\n\r\nIf you do not pass the `bindings` 3rd parameter to the bind() function, <b>all</b> child elements under the rootEl with a \"name\" attribute are bound.\r\nThis includes any nested child elements that define the \"name\" attribute.\r\n\r\nIn the example below, the \"address\" and the \"city\" elements will be bound to the model.\r\n\r\n````\r\n<!-- The html -->\r\n<div id=\"outerDiv\">\r\n    <input type=\"text\" name=\"address\"/>\r\n        <div id=\"divTwo\">\r\n            <input type=\"text\" name=\"city\"/>\r\n        </div>\r\n</div>\r\n````\r\n\r\n````\r\n<!-- The javascript -->\r\nSomeView = Backbone.View.extend({\r\n    render: function(){\r\n        this.modelBinder.bind(this.model, this.el);\r\n    }\r\n});\r\n````\r\n\r\n\r\n<br>\r\n## Binding multiple html elements to the same model attribute ##\r\n\r\nIn the example below, the `<span>` and the `<input>` elements are both bound to the model.firstName attribute.\r\nIf you modified the firstName input element you would see the span automatically updated because the Model would have been updated.\r\n\r\n````\r\n<!-- The html -->\r\nWelcome, <span name=\"firstName\"></span>\r\n\r\nEdit your information:\r\n<input type=\"text\" name=\"firstName\"/>\r\n````\r\n\r\n````\r\n<!-- The javascript -->\r\nSomeView = Backbone.View.extend({\r\n    render: function(){\r\n        this.modelBinder.bind(this.model, this.el);\r\n    }\r\n});\r\n````\r\n\r\n<br>\r\nIf your View element definitions are simple you can rely on having properly defined \"name\" attributes in your html elements that match your Model attribute names.\r\nRemember that **all** of the rootEl's child elements (recursive) with a \"name\" attribute will be bound to your Model.\r\n\r\nIf your views require formatting, conversion or more scoping due to nested or complex views you'll need to define a `bindings` parameter to the `bind()` function as discussed in the next section.\r\n\r\n\r\n***\r\n\r\n##The bindings parameter to the bind() function##\r\n\r\nFor more complicated things like formatting or defining scope for composite or nested Views you'll need to define a `bindings` parameter - the optional 3rd parameter to the `bind()` function.\r\nThe bindings parameter is a javascript hash object.\r\n\r\nThe bindings hash keys are the model's attribute names and the values, in the simplest case, are jQuery selectors that must return at least 1 html element.\r\n\r\nThe example below binds model.address to the element with the id=\"address\":\r\n\r\n````\r\n<input type='text' id='address'/>\r\n\r\nvar bindings = {address: '#address'};\r\nmodelBinder.bind(this.model, this.el, bindings);\r\n````\r\n\r\nThe example below binds model.homeAddress to the element with name=\"homeAddress\" and model.workAddress to the element with name=\"workAddress\":\r\n\r\n````\r\n<input type=\"text\" name=\"homeAddress\"/>\r\n<input type=\"text\" name=\"workAddress \"/>\r\n\r\nvar bindings = {homeAddress: '[name=homeAddress]', workAddress : '[name=workAddress ]'};\r\nmodelBinder.bind(this.model, this.el, bindings);\r\n````\r\n\r\nThe example below binds model.city to `<input type=\"text\" id=\"city\"/>`:\r\n\r\n````\r\nvar bindings = {city: '#city'};\r\nmodelBinder.bind(this.model, this.el, bindings);\r\n````\r\n\r\nYou can use any jQuery selector that you like, as long as the selector returns at least a single element.\r\nIn the example below, both the `<span>` and the `<input>` elements are bound to the model.firstName attribute.\r\nIn this situation, you could also eliminate the bindings and get the same behavior.\r\n\r\n````\r\n<!-- The html -->\r\nWelcome, <span name=\"firstName\"></span>\r\n\r\nEdit your information:\r\n<input type=\"text\" name=\"firstName\"/>\r\n````\r\n\r\n````\r\n<!-- The javascript -->\r\nvar bindings = {firstName: '[name=firstName]'};\r\nmodelBinder.bind(this.model, this.el, bindings);\r\n````\r\n\r\n<br>\r\nHere are a few more examples of the bindings hash syntax.\r\n\r\n````\r\n    Html                                            bindings entry\r\n    -----------------------------------------------------------------------------------------------\r\n    <input type=\"text\" id=\"firstName\"/>             firstName: '#firstName'\r\n\r\n    <input type=\"text\" name=\"firstName\"/>           firstName: '[name=firstName]'\r\n\r\n    <select name=\"operatorSelectEl\">                operator: '[name=operatorSelectEl]'\r\n      <option value=\"1\">Dan</option>\r\n      <option value=\"2\">Eli</option>\r\n      <option value=\"3\">Frank</option>\r\n    </select>\r\n\r\n    <input type=\"radio\" name=\"isOk\" value=\"yes\">    isOk: '[name=isOk]'\r\n\r\n    <input type=\"text\" class=\"myTestClass\"          myTestAttribute: '[class~=myTestClass]'\r\n        name=\"address\"/>\r\n````\r\n\r\n<br>\r\n## You can define multiple jQuery selectors ##\r\n\r\nThe binding entries can be defined as strings as shown in all previous examples but internally the string is converted to the type of entry shown below.\r\n\r\n````\r\n firstName: {selector: '#firstName'}\r\n````\r\n\r\nThe jQuery string is a hash parameter named `selector`.\r\nYou can define arrays of `selector` arguments in your bindings as shown in the example below.\r\n\r\n````\r\n firstName: [{selector: '#firstName'}, {selector: '#title'}]\r\n````\r\n\r\nIn the example above, model.firstName is bound to an element with the id of \"firstName\" and an element with the id of \"title\".\r\nTo define multiple selectors, just define them as an array.\r\n\r\nThe jQuery bindings leverage the jQuery delegate mechanism - which means they should be fairly efficient.\r\n\r\n##Binding to the Root Element##\r\n\r\nSometimes, in rare cases, your views are so simple that you just want to bind\r\nto the root element itself. For example, if your view is an `<li>` tag, it\r\nmakes sense to have the inner HTML simply be the appropriate model value.\r\n\r\nIn those cases, simply use an empty string as your selector:\r\n\r\n````\r\n firstName: { selector: '' }\r\n````\r\n\r\n<br>\r\n***\r\n\r\n##Formatting and converting values##\r\n\r\nThe bindings can also define a `converter` parameter.\r\nA converter is simply a function that is called whenever a model's attribute is copied to an html element or when an html elements value is copied into a model's attribute.\r\n\r\nConverters help you format values in your views but help keep them clean in your models.\r\n\r\nA simple of example of using a converter to format a phone number is shown below.\r\n\r\n````\r\nvar phoneConverter = function(direction, value){\r\n  // direction is either ModelToView or ViewToModel\r\n  // Return either a formatted value for the view or an un-formatted value for the model\r\n};\r\n\r\nvar bindings = {phoneNumber: {selector: '[name=phoneNumber]', converter: phoneConverter}}\r\nmodelBinder.bind(this.model, this.el, bindings );\r\n````\r\n\r\n<br>\r\nA converter function is passed 4 parameters.\r\n\r\n* direction - either ModelToView or ViewToModel\r\n* value - the model's attribute value or the view element's value\r\n* attribute Name\r\n* model - this is more useful when you're dealing with calculated attributes\r\n* els - an array of the els that were bound to the converter\r\n\r\nIf your binding to a read-only element like a `<div>` you'll just ignore the direction parameter - it's always ModelToView.\r\nIn most cases, you'll be able to ignore the attribute name and model parameters but they can be helpful in some situations discussed later.\r\n\r\nThe Model parameter can be quite helpful in complicated situations.\r\nThe els array allows a developer to manually modify the els directly when a converter is invoked.\r\nBe very careful when accessing the els directly because any state you set into the els might be overwritten by the ModelBinder after the converter is finished.\r\nFor example, if a converter is called with the direction 'ModelToView' and inside the converter the code updates the el values directly those values will be overwritten with the value returned from the converter function.\r\nThe els array is more valuable if you need to set other properties etc. on the els.  In most situations you should not need the els parameter.\r\n\r\n\r\n<br>\r\nConverters can be used for simple formatting operations like phone numbers but they can also be used for more advanced situations like when you want to convert between a model and some description of the model.\r\nYou might want to display a list of models in a `<select>` element - a converter could allow you to convert between a model and a model's id making this type of binding easy to do.\r\n\r\nThe example below shows how this could work.  The `CollectionConverter` shown is defined in the ModelBinder.js file.\r\n\r\n````\r\n<!-- The html -->\r\n    <select name=\"nestedModel\">\r\n        <option value=\"\">Please Select Something</option>\r\n        <% _.each(nestedModelChoices, function (modelChoice) { %>\r\n          <option value=\"<%= modelChoice.id %>\"><%= modelChoice.description %></option>\r\n        <% }); %>\r\n    </select>\r\n````\r\n\r\n````\r\n<!-- The javascript -->\r\nSomeView = Backbone.View.extend({\r\n    render: function(){\r\n        // An example of what might be passed to the template function\r\n        var nestedModelChoices = [{id: 1, description: 'This is One'}, {id: 2, description: 'This is Two'}];\r\n\r\n        $(this.el).html(this.template({nestedModelChoices: nestedModelChoices}));\r\n\r\n        var binder = new Backbone.ModelBinder();\r\n\r\n        var bindingsHash = {nestedModel: { selector: '[name=nestedModel]',\r\n                                           converter: new Backbone.ModelBinder.CollectionConverter(nestedModelChoices).convert} };\r\n\r\n        binder.bind(this.model, this.el, bindingsHash);\r\n````\r\n\r\n<br>\r\n## Converters can display calculated attributes ##\r\n\r\nSometimes your models will have computed attributes.\r\nYou could cache computed values inside a model's attribute collection and it would be bound like any other attribute.\r\nI favor this solution but it's not perfect because when you save models back to the server, the calculated attributes are sent.\r\n\r\nIf your model's computed attribute is calculated via a function we can use a converter for the binding.\r\nIn the example below, we have a simple computed attribute named hoursLeft calculated by the function calculateHoursLeft().\r\n\r\n````\r\nSomeModel = Backbone.Model.extend({\r\n    defaults: {currentHours: 3, totalHours: 8},\r\n\r\n    calculateHoursLeft: function(){\r\n        return this.get('totalHours') - this.get('currentHours');\r\n    }\r\n})\r\n\r\n// Here is how how we could create a binding for a calculated attribute\r\nvar bindings = {currentHours: {selector: '[name=hoursLeft]', converter: this.model.calculateHoursLeft}};\r\nmodelBinder.bind(this.model, this.el, bindings);\r\n````\r\n\r\nIn the example above, we are binding to the model's attribute 'currentHours' because when currentHours changes the hoursLeft calculated value will change - the converter will be invoked at that time.\r\nThe converter is simply the model's calculateHoursLeft() function. The function just ignores the parameters passed to it and calculates the hours left.\r\n\r\n<br>\r\nIf the currentHours attribute is also bound to another html element you could specify an array of element bindings in the binding definition like the example shown below.\r\n\r\n````\r\nvar bindings = {currentHours: [ {selector: '[name=hoursLeft]', converter: this.model.calculateHoursLeft},\r\n                                {selector: '[name=currentHours]']};\r\nmodelBinder.bind(this.model, this.el, bindings);\r\n````\r\n\r\nIf converters need any other special logic they can be defined in another function outside of the Model because the converter function is passed the Model as a parameter.\r\n\r\n\r\n\r\n<br>\r\n\r\n***\r\n\r\n##Binding to html element attributes##\r\n\r\nYou can also define bindings to be bound to any html element's attribute like enabled, class, style or any other attribute you define.\r\nThe example below shows how to use the `elAttribute` option.  In this example, the address element will be enabled depending on what the Model.isAddressEnabled attribute is.\r\n\r\n````\r\nvar bindings = {isAddressEnabled: {selector: '[name=address]',  elAttribute: 'enabled'}};\r\nmodelBinder.bind(this.model, this.el, bindings);\r\n````\r\n\r\n<br>\r\nYou could also extend the example above to be a bit more complicated.  Let's pretend the Model has an attribute called customerType and if customerType == 'residential' we want the address to enabled, otherwise we want it disabled.  We can handle this type of binding by leveraging both `converter` and `elAttribute`.  The example below shows how this would work.  When the Model.customerType is updated, the address input element's enabled attribute would be updated.\r\n\r\n````\r\nvar addressEnabledConverter = function(direction, value) { return value === 'residential'; };\r\n\r\nvar bindings = {customerType: {selector: '[name=address]',  elAttribute: 'enabled', converter: addressEnabledConverter}};\r\nmodelBinder.bind(this.model, this.el, bindings);\r\n````\r\n\r\n<br>\r\nYou could also bind to an element's class property as shown in the example below.\r\n\r\n````\r\n<!-- The html -->\r\n<div id=\"patientPic\" class=\"patientPic\"></div>\r\n````\r\n\r\n````\r\n<!-- The javascript -->\r\nvar bindings = {gender: {selector: '#patientPicture',  elAttribute: 'class'}};\r\nmodelBinder.bind(this.model, this.el, bindings);\r\n````\r\n\r\nIn this example, the model.gender value is either \"M\" or \"F\".  The CSS files define styles for \"patientPic\" with either \"M\" or \"F\" to show the correct type of avatar.\r\n\r\n\r\n<br>\r\n\r\n***\r\n\r\n##Proper scope helps you bind to complex nested views##\r\n\r\nSometimes you'll have nested models displayed in nested views.\r\nAn example of a nested backbone model is shown below.  The personModel has a nested homeAddressModel.\r\n\r\n````\r\nvar personModel = new Backbone.Model({firstName: 'Herman', lastName: 'Munster'});\r\nvar homeAddressModel = new Backbone.Model({street: '1313 Mockingbird Lane', city: 'Mockingbird Heights'});\r\n\r\npersonModel.set({homeAddress: homeAddressModel});\r\n````\r\n\r\nIn the example above, the nested model is also a backbone.Model but sometimes your nested models are raw javascript objects.  I'll talk about that situation a bit later.\r\n\r\nYou can bind to this type of nested backbone model fairly easily with the ModelBinder.\r\n\r\nThere are 2 basic ways to bind nested Models in a View:\r\n\r\n1. With a scoped `rootEl` that only contains html elements specific to the nested Model.\r\n2. With scoped bindings selectors in the bindings hash.\r\n\r\n<br>\r\n##Nested View option 1: A scoped `rootEl`##\r\n\r\nIf your nested view can be defined under a single parent element such as a `<div>` you can pass that parent element as the `rootEl` for your nested ModelBinder as shown in the example below.\r\nIt refers to the personModel and homeAddressModels defined in a previous code snippet.\r\n\r\n````\r\n<!-- html -->\r\n<div id=\"personFields\">\r\n  <input type=\"text\" name=\"firstName\"/>\r\n  <input type=\"text\" name=\"lastName\"/>\r\n</div>\r\n<div id=\"homeAddressFields\">\r\n  <input type=\"text\" name=\"street\"/>\r\n  <input type=\"text\" name=\"city\"/>\r\n</div>\r\n````\r\n\r\n````\r\n<!-- javascript -->\r\npersonBinder.bind(this.personModel, this.$('#personFields'));\r\naddressBinder.bind(this.personModel.get('homeAddress'), this.$('#homeAddressFields'));\r\n````\r\n\r\nIn the example above, the nested homeAddressModel is bound to the correct fields because they are scoped by a single parent element.\r\nThe personModel bindings also needed to be separately scoped as well.\r\n\r\nIf the personModel fields were defined on a level that also included the homeAddressFields then the homeAddressFields would have appeared in the personModel.\r\nThe next option shows how to avoid that situation.\r\n\r\n<br>\r\n##Nested View option 2: scoped bindings##\r\n\r\nIf your parent and nested Model html elements cannot live under their own parent elements then you'll need to define the `bindings` with jQuery selectors that are properly scoped as shown in the example below.\r\n\r\n````\r\n<!-- Html -->\r\n<input type=\"text\" name=\"firstName\"/>\r\n<input type=\"text\" name=\"lastName\"/>\r\n<input type=\"text\" name=\"street\"/>\r\n<input type=\"text\" name=\"city\"/>\r\n````\r\n\r\n````\r\n<!-- javascript -->\r\nvar personBindings = {firstName: '[name=firstName]', lastName: '[name=lastName]'};\r\npersonBinder.bind(this.personModel, this.el, personBindings);\r\n\r\nvar addressBindings = {street: '[name=street]', city: '[name=city]'};\r\naddressBinder.bind(this.personModel.get('homeAddress'), this.el, addressBindings);\r\n````\r\n\r\n\r\n<br>\r\n\r\n***\r\n\r\n##The ModelBinder can be a partial solution##\r\n\r\nIn some situations, you might have very complex views where you only want some of your view's elements bound by the ModelBinder.\r\nTo limit the scope of which fields are bound, you just need to properly scope your bindings hash.\r\n\r\nIn the example below, the modelBinder will ignore the \"phone\" and \"fax\" elements.\r\n\r\n````\r\n<!-- Html -->\r\n<input type=\"text\" name=\"firstName\"/>\r\n<input type=\"text\" name=\"lastName\"/>\r\n<input type=\"text\" name=\"phone\"/>\r\n<input type=\"text\" name=\"fax\"/>\r\n````\r\n\r\n````\r\n<!-- javascript -->\r\nvar personBindings = {firstName: '[name=firstName]', lastName: '[name=lastName]'};\r\nmodelBinder.bind(this.personModel, this.el, personBindings);\r\n````\r\n\r\n\r\n<br>\r\n\r\n***\r\n\r\n##Quickly create and modify bindings##\r\n\r\nIn some situations, you might have a large amount of elements that need to be bound but only a few of them need a converter or elAttribute defined.\r\nYou probably don't want to define all of the element bindings manually just to add a converter to a few of them.\r\nThe utility function Backbone.ModelBinder.createDefaultBindings can help you in this situation.\r\n\r\nThe Backbone.ModelBinder.createDefaultBindings( ) is shown below.\r\n\r\n````\r\n// A static helper function to create a default set of bindings that you can customize before calling the bind() function\r\n// rootEl - where to find all of the bound elements\r\n// attributeType - probably 'name' or 'id' in most cases\r\n// converter(optional) - the default converter you want applied to all your bindings\r\n// elAttribute(optional) - the default elAttribute you want applied to all your bindings\r\nBackbone.ModelBinder.createDefaultBindings = function(rootEl, attributeType, converter, elAttribute){\r\n    ...\r\n}\r\n````\r\n\r\nYou can use this function to gather all of the elements under the rootEl with a \"name\" or \"id\" attribute and quickly create all of the bindings and then modify those bindings.\r\nYou might want to delete one or more of the bindings, add converters or elAttributes to bindings etc.\r\nBe careful when you use this with radio buttons - you might not get the proper selectors if you're not careful.\r\n\r\nAn example of how you might use createDefaultBindings( ) is shown below.\r\n\r\n````\r\n// The view has several form element with a name attribute that should be bound\r\n// but one binding requires a converter and one of the bindings should be removed\r\nvar bindings = Backbone.ModelBinder.createDefaultBindings(this.el, 'name');\r\nbindings['phone'].converter = this._phoneConverterFunction;\r\ndelete bindings['complicatedAttribute'];\r\n\r\nthis._modelBinder.bind(this.model, this.el, bindings);\r\n````\r\n\r\n###Change attribute used for binding###\r\n\r\nBy default, the `name` attribute of your elements is used to create bindings.  Changing this can be accomplished easily in one of two ways.  First, by using `createDefaultBindings`:\r\n\r\n````\r\nvar bindings = Backbone.ModelBinder.createDefaultBindings(this.el, 'data-custom');\r\nthis._modelBinder.bind(this.model, this.el, bindings);\r\n````\r\n\r\nAlternatively, setting `boundAttribute` on the options hash given to bind can point it at any attribute.\r\n\r\n````\r\n// Set the default bindings based on the data-custom attribute rather than name.\r\nthis._modelBinder.bind(this.model, this.el, null, { boundAttribute: 'data-custom' });\r\n````\r\n\r\n<br>\r\n\r\n***\r\n\r\n<br>\r\n\r\n## The Power of jQuery ##\r\nYour jQuery selectors can be based off of a class attribute or anything else you'd like as shown in the example below.\r\n\r\n````\r\n<!-- html -->\r\n    <input type=\"text\" class=\"partOne\" name=\"address\"/>\r\n    <input type=\"text\" class=\"partOne\" name=\"phone\"/>\r\n    <input type=\"text\" class=\"partOne\" name=\"fax\"/>\r\n````\r\n\r\n````\r\n<!-- javascript -->\r\nSomeView = Backbone.View.extend({\r\n    render: function(){\r\n        $(this.el).html(this.template({model: this.model.toJSON()}));\r\n\r\n        var bindingsHash = {isPartOneEnabled: {selector: '[class~=partOne]',  elAttribute: 'enabled'}};\r\n\r\n        this.modelBinder.bind(this.model, this.el, bindingsHash);\r\n    }\r\n````\r\n\r\nIn this example, all 3 html elements enabled attribute are bound to the Model's isPartOneEnabled attribute.\r\nThis is because the jQuery selector '[class~=partOne]' returned all 3 elements.\r\n\r\n\r\n<br>\r\n\r\n***\r\n\r\n## Calling bind() multiple times ##\r\n\r\nCalling ModelBinder.bind() will automatically internally call the unbind() function to unbind the previous model.\r\nYou can reuse the same ModelBinder instance with multiple models or even rootEls - just be aware that all previous bindings will be removed.\r\n\r\n<br>\r\n## Model values are copied to views when bind() is called ##\r\n\r\nThe model's attributes are bound are copied from the model to bound elements when the bind() function is called.\r\nView element default values are not copied to the model when bind() is called. That type of behavior usually belongs in the Backbone.Model defaults block.\r\n\r\nIf you do need to have values copied from the view to the model when bind() is called I would first question why.\r\nIn most situations, especially for single page web apps, it's almost always better to let your models drive the behavior of the app instead of the views.\r\nIf you need this behavior, you can use the 4th optional parameter to the bind() function. {initialCopyDirection: Backbone.ModelBinder.Constants.ViewToModel}\r\nYou can also specify this behavior as the default for all ModelBinder's by calling Backbone.ModelBinder.SetOptions({initialCopyDirection: Backbone.ModelBinder.Constants.ViewToModel});\r\n\r\nYou can also directly invoke the function modelBinder.copyViewValuesToModel() at any time to copy values from the view into the model.  In most cases, this is not necessary.\r\n\r\nWhen you copy explicitly from the view to the model on bind() or via copyViewValuesToModel() text values and checkboxes will be inserted into the model as blank strings or false if the values have not been set.\r\n\r\n\r\n<br>\r\n## Cleaning up with unbind() ##\r\n\r\nWhen your views are closed you should always call the unbind() function.  The unbind() function will un-register from the model's change events and the view's jQuery change delegate.\r\n\r\nIf you don't call unbind() you might end up with zombie views and ModelBinders.  This is particularly important for large client side applications that are not frequently refreshed.\r\n\r\n\r\n\r\n<br>\r\n## The '.' syntax for nested models ##\r\n\r\nThe ModelBinder doesn't directly support '.' to reference nested Models when binding.\r\nIf you have a Backbone.Model implementation that is able to support the '.' syntax for nested models you'll be able to use the ModelBinder.\r\n\r\nI've done a bit of testing with the [backbone-deep-model](https://github.com/powmedia/backbone-deep-model) and it seems to work well with the ModelBinder.\r\n[Here](https://github.com/theironcook/Backbone.ModelBinder/blob/master/sandbox/Example_NestedAttributes.html) is a simple example showing how to use backbone-deep-model with the ModelBinder.\r\n\r\nThe nested models are just plain javascript objects with the deep-model plugin.  If your nested objects are Backbone.Models you'll need something similar to the deep-model plugin.\r\n\r\n<br>\r\nThe [backbone-nested](https://github.com/afeld/backbone-nested) project also seems to work with the ModelBinder.\r\n\r\n\r\n***\r\n\r\n<br>\r\n## AMD / Require.js support\r\n\r\nAMD / Require.js support was added in version 0.1.4\r\n\r\n\r\n***\r\n\r\n<br>\r\n### Binding to Collections\r\nI've also created a collection binder that automatically creates/removes views when models are added/removed to a collection.\r\nIt can be used with the ModelBinder.  The collection binder has saved me just as much time as the model binder.  It's a very handy utility.\r\n\r\nYou can read about it [here](https://github.com/theironcook/Backbone.ModelBinder/wiki/A-new-Class-to-Bind-Backbone-Collections-to-Views:-Javascript-Weekly-May-18th)\r\n\r\n<br><br>\r\n\r\n## Examples\r\nSome JSFiddle examples can be found [here](https://github.com/theironcook/Backbone.ModelBinder/wiki/Interactive-JSFiddle-Examples).\r\n<br>The same examples are also under the (examples)[https://github.com/theironcook/Backbone.ModelBinder/tree/master/examples] directory.\r\n\r\n\r\n<br><br>\r\n\r\n## Configuration Options\r\n* initialCopyDirection\r\n* changeTriggers\r\n* modelSetOptions\r\n* suppressThrows\r\n* boundAttribute\r\n* converter\r\n\r\nConfiguration options can either be set for all ModelBinder instances via Backbone.ModelBinder.SetOptions() or for individual ModelBinder instances via the 4th parameter to the bind() function.\r\nValues set at the instance level will eclipse / override values that are set with the SetOptions() function.\r\n\r\n* initialCopyDirection - can either be Backbone.ModelBinder.Constants.ModelToView or Backbone.ModelBinder.Constants.ViewToModel.  This property is dicussed in a previous section\r\n\r\n* changeTriggers - an object where the keys are jQuery selectors and the values are jQuery events.  These are the events that trigger when values are copied from the view into the model.\r\nThe default for change triggers is added below.  You can define your own if needed.\r\n\r\n````\r\n{'': 'change', '[contenteditable]': 'blur'}\r\n````\r\n\r\n* modelSetOptions - this is an option that you might want sent by default to the Model.set function.\r\nWhenever a bound element changes, it will call the Model.set function as pass the modelSetOptions as the options to the set() function.\r\nIf you wanted to turn on backbone model validation for your entire project you might do something like this.\r\n\r\n````\r\nBackbone.ModelBinder.SetOptions({modelSetOptions: {validate: true}});\r\n````\r\n\r\nThe ModelBinder injects this value into the set options for every set() function.\r\nchangeSource = 'ModelBinder'\r\nThis allows custom logic to determine if the source of the model attribute change is from the ModelBinder.\r\n\r\n* suppressThrows - set to true if you don't want the ModelBinder to throw exceptions but instead it will show errors via the console.error\r\n\r\n* boundAttribute - change the default attribute used to create bindings.  Default value is \"name,\" but can be set to any valid attribute selector that fits the form `$('[' + boundAttribute + ']')`.\r\n\r\n* converter - a default converter for all binders or a single binder.  Probably only really useful for when you want view empty strings to map to nulls or undefined. The default is empty string.\r\nIf you define a converter, you might want to pay attention to the converter's 5th parameter of bound els.  You might want to only convert values for specific element types.\r\n\r\n<br>\r\n<br>\r\n\r\n## Release Notes / Versions\r\n### v 1.1.0 June 1, 2015\r\n* Fixed createEl code not to require that Backbone.View#render returns this\r\n* Don't sort elements on add event (only do so on sort)\r\n* Fixed package.json to make NPM publishing possible (fixes #195)\r\n* Use jQuery .on instead of .delegate for event binding (to move off of deprecated .delegate function)\r\n* Use .prop(\"checked\") instead of .attr(\"checked\") (fixes #199)\r\n* Fixed autoSort behavior to actually work when the collection changes\r\n\r\n### v 1.0.6 November 5, 2014\r\n* Made the CollectionBinder loadable via AMD\r\n\r\n### v 1.0.5 September 30, 2013\r\n* Fixed issue 164 - Works with jQuery.noConflict\r\n* Added the ability to set static and instance options for the CollectionBinder.  As of now, there is only one option: 'autoSort'.  You can set the option globally via Backbone.CollectionBinder.SetOptions.\r\n* Added the ability to use template functions with the CollectionBinder.ElManagerFactory.  Normally, I wouldn't use the ElManagerFactory except for very simple situations - especially because the content of the data isn't updated.\r\nIf you would like to use this option, simply pass a compiled _.template instead of html to the ElManagerFactory constructor. Internally the ElManagerFactory will call the template and pass {model: this._model.toJSON()} to the template function.\r\n* Fix for issue 162.  Undid fix for 133.  Unnecessary Model.set calls for checkboxes and radio buttons.\r\n\r\n### v 1.0.4 August 19, 2013\r\n* Fixed the _.bindAll function calls to specify the function names being bound to.\r\n* Added the ability to add a global converter via Backbone.ModelBinder.SetOptions({converter: xxx});\r\n\r\n### v 1.0.2 April 18, 2013\r\n* Fixed the _unbindViewToModel to use the changeTrigger options\r\n* Fixed the default jQuery selector for all elements to be '*' instead of ''.  The undelegate events no longer works in jQuery 1.8.3 with the ''\r\n\r\n### v 1.0.1 April 15, 2013\r\n* Added suppressThrows configuration option\r\n\r\n### v 1.0.0 April 11, 2013\r\n* Updated to use backbone v1.0.0, underscore v1.4.4 and jQuery v1.8.3\r\n* Pull requests 96, 67, 85, 80, 78, 67, 66\r\n* Options are now configurable at the ModelBinder class level via Backbone.ModelBinder.SetOptions() or at the instance level via the bind() 4th parameter\r\n* ModelSetOptions have now been incorporated to the generic options argument at the class or instance level.\r\n  For example: to set model options globally for all binders Backbone.ModelBinder.SetOptions({modelSetOptions: {validate: true}});\r\n  or for a single instance modelBinder.bind(this.model, this.el, bindings, {modelSetOptions: {validate: true}});\r\n  For single instance options, the bindings can be a fully configured set of bindings or the value of null if you want the default bindings.\r\n* bindCustomTriggers() has now been incorporated to the generic options argument at the class or instance level.\r\n  For example: to set custom triggers options globally for all binders Backbone.ModelBinder.SetOptions({changeTriggers: {'': 'change keyup'}});\r\n  or for a single instance modelBinder.bind(this.model, this.el, {changeTriggers: {'': 'change keyup'}});\r\n* Added the els parameter to the converter functions\r\n* Added the changeTriggers to customize which view events trigger the model binder copies values from the view to the model\r\n* Added the modelSetOptions to allow the ModelBinder to send messages to the Model.set function and corresponding callbacks\r\n\r\n\r\n### v 0.1.6 August 27, 2012\r\n\r\n* Bugfix for issue 51\r\n\r\n\r\n### v 0.1.5 June 20, 2012\r\n\r\n* Upgraded model binder to allow single DOM element to be bound to multiple model attributes\r\n* Exposed the model binder copyModelAttributesToView to be public and take an optional array of attribute names to copy\r\n\r\n### v 0.1.4 May 11, 2012\r\n\r\n* AMD / Require.js support added\r\n* Initial version of the CollectionViewBinder added\r\n\r\n### v 0.1.3 May 9, 2012\r\n\r\n* Started properly tagging my versions :)\r\n\r\n### v 0.1.2\r\n\r\n* Added the {source: 'ModelBinder'} option to the model.set call - allows you to know the source of a model's change event\r\n* Bug fix - when binding the elAttribute to class I wasn't going through the converter function\r\n\r\n### v 0.1.1\r\n\r\n* An empty selector string will now bind to the rootEl\r\n* Removed elementBinding.isSetting guard which was unnecessary and short circuited updating multiple bound elements with the same name\r\n\r\n### v 0.1.0\r\n\r\n* Initial version starting April 16th.  Future api changes will have updated version numbers.\r\n\r\n\r\n\r\n# Legal Info (MIT License)\r\n\r\nCopyright (c) 2012 Bart Wood\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in\r\nall copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\nTHE SOFTWARE.\r\n","maintainers":[{"name":"theironcook","email":"bartwood@gmail.com"}],"time":{"modified":"2022-06-13T04:10:59.207Z","created":"2015-06-01T22:02:14.206Z","1.1.0":"2015-06-01T22:02:14.206Z"},"homepage":"https://github.com/theironcook/Backbone.ModelBinder#readme","keywords":["backbone","model","view"],"repository":{"type":"git","url":"git+https://github.com/theironcook/Backbone.ModelBinder.git"},"author":{"name":"Bart Wood"},"bugs":{"url":"https://github.com/theironcook/Backbone.ModelBinder/issues"},"license":"MIT","readmeFilename":"README.md"}