diff --git a/lib/amd/backbone.syphon.js b/lib/amd/backbone.syphon.js
deleted file mode 100644
index a8ca441..0000000
--- a/lib/amd/backbone.syphon.js
+++ /dev/null
@@ -1,479 +0,0 @@
-// Backbone.Syphon, v0.4.1
-// Copyright (c)2012 Derick Bailey, Muted Solutions, LLC.
-// Distributed under MIT license
-// http://github.com/derickbailey/backbone.syphon
-(function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module.
- define(['underscore', "jquery", "backbone"], factory);
- }
-}(this, function (_, jQuery, Backbone) {
- Backbone.Syphon = (function(Backbone, $, _){
- var Syphon = {};
-
- // Ignore Element Types
- // --------------------
-
- // Tell Syphon to ignore all elements of these types. You can
- // push new types to ignore directly in to this array.
- Syphon.ignoredTypes = ["button", "submit", "reset", "fieldset"];
-
- // Syphon
- // ------
-
- // Get a JSON object that represents
- // all of the form inputs, in this view.
- // Alternately, pass a form element directly
- // in place of the view.
- Syphon.serialize = function(view, options){
- var data = {};
-
- // Build the configuration
- var config = buildConfig(options);
-
- // Get all of the elements to process
- var elements = getInputElements(view, config);
-
- // Process all of the elements
- _.each(elements, function(el){
- var $el = $(el);
- var type = getElementType($el);
-
- // Get the key for the input
- var keyExtractor = config.keyExtractors.get(type);
- var key = keyExtractor($el);
-
- // Get the value for the input
- var inputReader = config.inputReaders.get(type);
- var value = inputReader($el);
-
- // Get the key assignment validator and make sure
- // it's valid before assigning the value to the key
- var validKeyAssignment = config.keyAssignmentValidators.get(type);
- if (validKeyAssignment($el, key, value)){
- var keychain = config.keySplitter(key);
- data = assignKeyValue(data, keychain, value);
- }
- });
-
- // Done; send back the results.
- return data;
- };
-
- // Use the given JSON object to populate
- // all of the form inputs, in this view.
- // Alternately, pass a form element directly
- // in place of the view.
- Syphon.deserialize = function(view, data, options){
- // Build the configuration
- var config = buildConfig(options);
-
- // Get all of the elements to process
- var elements = getInputElements(view, config);
-
- // Flatten the data structure that we are deserializing
- var flattenedData = flattenData(config, data);
-
- // Process all of the elements
- _.each(elements, function(el){
- var $el = $(el);
- var type = getElementType($el);
-
- // Get the key for the input
- var keyExtractor = config.keyExtractors.get(type);
- var key = keyExtractor($el);
-
- // Get the input writer and the value to write
- var inputWriter = config.inputWriters.get(type);
- var value = flattenedData[key];
-
- // Write the value to the input
- inputWriter($el, value);
- });
- };
-
- // Helpers
- // -------
-
- // Retrieve all of the form inputs
- // from the form
- var getInputElements = function(view, config){
- var form = getForm(view);
- var elements = form.elements;
-
- elements = _.reject(elements, function(el){
- var reject;
- var type = getElementType(el);
- var extractor = config.keyExtractors.get(type);
- var identifier = extractor($(el));
-
- var foundInIgnored = _.include(config.ignoredTypes, type);
- var foundInInclude = _.include(config.include, identifier);
- var foundInExclude = _.include(config.exclude, identifier);
-
- if (foundInInclude){
- reject = false;
- } else {
- if (config.include){
- reject = true;
- } else {
- reject = (foundInExclude || foundInIgnored);
- }
- }
-
- return reject;
- });
-
- return elements;
- };
-
- // Determine what type of element this is. It
- // will either return the `type` attribute of
- // an `` element, or the `tagName` of
- // the element when the element is not an ``.
- var getElementType = function(el){
- var typeAttr;
- var $el = $(el);
- var tagName = $el[0].tagName;
- var type = tagName;
-
- if (tagName.toLowerCase() === "input"){
- typeAttr = $el.attr("type");
- if (typeAttr){
- type = typeAttr;
- } else {
- type = "text";
- }
- }
-
- // Always return the type as lowercase
- // so it can be matched to lowercase
- // type registrations.
- return type.toLowerCase();
- };
-
- // If a form element is given, just return it.
- // Otherwise, get the form element from the view.
- var getForm = function(viewOrForm){
- if (_.isUndefined(viewOrForm.$el) && viewOrForm.tagName.toLowerCase() === 'form'){
- return viewOrForm;
- } else {
- return viewOrForm.$el.is("form") ? viewOrForm.el : viewOrForm.$("form")[0];
- }
- };
-
- // Build a configuration object and initialize
- // default values.
- var buildConfig = function(options){
- var config = _.clone(options) || {};
-
- config.ignoredTypes = _.clone(Syphon.ignoredTypes);
- config.inputReaders = config.inputReaders || Syphon.InputReaders;
- config.inputWriters = config.inputWriters || Syphon.InputWriters;
- config.keyExtractors = config.keyExtractors || Syphon.KeyExtractors;
- config.keySplitter = config.keySplitter || Syphon.KeySplitter;
- config.keyJoiner = config.keyJoiner || Syphon.KeyJoiner;
- config.keyAssignmentValidators = config.keyAssignmentValidators || Syphon.KeyAssignmentValidators;
-
- return config;
- };
-
- // Assigns `value` to a parsed JSON key.
- //
- // The first parameter is the object which will be
- // modified to store the key/value pair.
- //
- // The second parameter accepts an array of keys as a
- // string with an option array containing a
- // single string as the last option.
- //
- // The third parameter is the value to be assigned.
- //
- // Examples:
- //
- // `["foo", "bar", "baz"] => {foo: {bar: {baz: "value"}}}`
- //
- // `["foo", "bar", ["baz"]] => {foo: {bar: {baz: ["value"]}}}`
- //
- // When the final value is an array with a string, the key
- // becomes an array, and values are pushed in to the array,
- // allowing multiple fields with the same name to be
- // assigned to the array.
- var assignKeyValue = function(obj, keychain, value) {
- if (!keychain){ return obj; }
-
- var key = keychain.shift();
-
- // build the current object we need to store data
- if (!obj[key]){
- obj[key] = _.isArray(key) ? [] : {};
- }
-
- // if it's the last key in the chain, assign the value directly
- if (keychain.length === 0){
- if (_.isArray(obj[key])){
- obj[key].push(value);
- } else {
- obj[key] = value;
- }
- }
-
- // recursive parsing of the array, depth-first
- if (keychain.length > 0){
- assignKeyValue(obj[key], keychain, value);
- }
-
- return obj;
- };
-
- // Flatten the data structure in to nested strings, using the
- // provided `KeyJoiner` function.
- //
- // Example:
- //
- // This input:
- //
- // ```js
- // {
- // widget: "wombat",
- // foo: {
- // bar: "baz",
- // baz: {
- // quux: "qux"
- // },
- // quux: ["foo", "bar"]
- // }
- // }
- // ```
- //
- // With a KeyJoiner that uses [ ] square brackets,
- // should produce this output:
- //
- // ```js
- // {
- // "widget": "wombat",
- // "foo[bar]": "baz",
- // "foo[baz][quux]": "qux",
- // "foo[quux]": ["foo", "bar"]
- // }
- // ```
- var flattenData = function(config, data, parentKey){
- var flatData = {};
-
- _.each(data, function(value, keyName){
- var hash = {};
-
- // If there is a parent key, join it with
- // the current, child key.
- if (parentKey){
- keyName = config.keyJoiner(parentKey, keyName);
- }
-
- if (_.isArray(value)){
- keyName += "[]";
- hash[keyName] = value;
- } else if (_.isObject(value)){
- hash = flattenData(config, value, keyName);
- } else {
- hash[keyName] = value;
- }
-
- // Store the resulting key/value pairs in the
- // final flattened data object
- _.extend(flatData, hash);
- });
-
- return flatData;
- };
-
- return Syphon;
- })(Backbone, jQuery, _);
-
- // Type Registry
- // -------------
-
- // Type Registries allow you to register something to
- // an input type, and retrieve either the item registered
- // for a specific type or the default registration
- Backbone.Syphon.TypeRegistry = function(){
- this.registeredTypes = {};
- };
-
- // Borrow Backbone's `extend` keyword for our TypeRegistry
- Backbone.Syphon.TypeRegistry.extend = Backbone.Model.extend;
-
- _.extend(Backbone.Syphon.TypeRegistry.prototype, {
-
- // Get the registered item by type. If nothing is
- // found for the specified type, the default is
- // returned.
- get: function(type){
- var item = this.registeredTypes[type];
-
- if (!item){
- item = this.registeredTypes["default"];
- }
-
- return item;
- },
-
- // Register a new item for a specified type
- register: function(type, item){
- this.registeredTypes[type] = item;
- },
-
- // Register a default item to be used when no
- // item for a specified type is found
- registerDefault: function(item){
- this.registeredTypes["default"] = item;
- },
-
- // Remove an item from a given type registration
- unregister: function(type){
- if (this.registeredTypes[type]){
- delete this.registeredTypes[type];
- }
- }
- });
-
-
-
-
- // Key Extractors
- // --------------
-
- // Key extractors produce the "key" in `{key: "value"}`
- // pairs, when serializing.
- Backbone.Syphon.KeyExtractorSet = Backbone.Syphon.TypeRegistry.extend();
-
- // Built-in Key Extractors
- Backbone.Syphon.KeyExtractors = new Backbone.Syphon.KeyExtractorSet();
-
- // The default key extractor, which uses the
- // input element's "id" attribute
- Backbone.Syphon.KeyExtractors.registerDefault(function($el){
- return $el.prop("name");
- });
-
-
- // Input Readers
- // -------------
-
- // Input Readers are used to extract the value from
- // an input element, for the serialized object result
- Backbone.Syphon.InputReaderSet = Backbone.Syphon.TypeRegistry.extend();
-
- // Built-in Input Readers
- Backbone.Syphon.InputReaders = new Backbone.Syphon.InputReaderSet();
-
- // The default input reader, which uses an input
- // element's "value"
- Backbone.Syphon.InputReaders.registerDefault(function($el){
- return $el.val();
- });
-
- // Checkbox reader, returning a boolean value for
- // whether or not the checkbox is checked.
- Backbone.Syphon.InputReaders.register("checkbox", function($el){
- var checked = $el.prop("checked");
- return checked;
- });
-
-
- // Input Writers
- // -------------
-
- // Input Writers are used to insert a value from an
- // object into an input element.
- Backbone.Syphon.InputWriterSet = Backbone.Syphon.TypeRegistry.extend();
-
- // Built-in Input Writers
- Backbone.Syphon.InputWriters = new Backbone.Syphon.InputWriterSet();
-
- // The default input writer, which sets an input
- // element's "value"
- Backbone.Syphon.InputWriters.registerDefault(function($el, value){
- $el.val(value);
- });
-
- // Checkbox writer, set whether or not the checkbox is checked
- // depending on the boolean value.
- Backbone.Syphon.InputWriters.register("checkbox", function($el, value){
- $el.prop("checked", value);
- });
-
- // Radio button writer, set whether or not the radio button is
- // checked. The button should only be checked if it's value
- // equals the given value.
- Backbone.Syphon.InputWriters.register("radio", function($el, value){
- $el.prop("checked", $el.val() === value);
- });
-
- // Key Assignment Validators
- // -------------------------
-
- // Key Assignment Validators are used to determine whether or not a
- // key should be assigned to a value, after the key and value have been
- // extracted from the element. This is the last opportunity to prevent
- // bad data from getting serialized to your object.
-
- Backbone.Syphon.KeyAssignmentValidatorSet = Backbone.Syphon.TypeRegistry.extend();
-
- // Build-in Key Assignment Validators
- Backbone.Syphon.KeyAssignmentValidators = new Backbone.Syphon.KeyAssignmentValidatorSet();
-
- // Everything is valid by default
- Backbone.Syphon.KeyAssignmentValidators.registerDefault(function(){ return true; });
-
- // But only the "checked" radio button for a given
- // radio button group is valid
- Backbone.Syphon.KeyAssignmentValidators.register("radio", function($el, key, value){
- return $el.prop("checked");
- });
-
-
- // Backbone.Syphon.KeySplitter
- // ---------------------------
-
- // This function is used to split DOM element keys in to an array
- // of parts, which are then used to create a nested result structure.
- // returning `["foo", "bar"]` results in `{foo: { bar: "value" }}`.
- //
- // Override this method to use a custom key splitter, such as:
- // ``, `return key.split(".")`
- Backbone.Syphon.KeySplitter = function(key){
- var matches = key.match(/[^\[\]]+/g);
-
- if (key.indexOf("[]") === key.length - 2){
- lastKey = matches.pop();
- matches.push([lastKey]);
- }
-
- return matches;
- }
-
-
- // Backbone.Syphon.KeyJoiner
- // -------------------------
-
- // Take two segments of a key and join them together, to create the
- // de-normalized key name, when deserializing a data structure back
- // in to a form.
- //
- // Example:
- //
- // With this data strucutre `{foo: { bar: {baz: "value", quux: "another"} } }`,
- // the key joiner will be called with these parameters, and assuming the
- // join happens with "[ ]" square brackets, the specified output:
- //
- // `KeyJoiner("foo", "bar")` //=> "foo[bar]"
- // `KeyJoiner("foo[bar]", "baz")` //=> "foo[bar][baz]"
- // `KeyJoiner("foo[bar]", "quux")` //=> "foo[bar][quux]"
-
- Backbone.Syphon.KeyJoiner = function(parentKey, childKey){
- return parentKey + "[" + childKey + "]";
- }
-
-
- return Backbone.Syphon;
-}));
\ No newline at end of file
diff --git a/lib/amd/backbone.syphon.min.js b/lib/amd/backbone.syphon.min.js
deleted file mode 100644
index a0409fc..0000000
--- a/lib/amd/backbone.syphon.min.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// Backbone.Syphon, v0.4.1
-// Copyright (c)2012 Derick Bailey, Muted Solutions, LLC.
-// Distributed under MIT license
-// http://github.com/derickbailey/backbone.syphon
-(function(a,b){typeof define=="function"&&define.amd&&define(["underscore","jquery","backbone"],b)})(this,function(a,b,c){return c.Syphon=function(a,b,c){var d={};d.ignoredTypes=["button","submit","reset","fieldset"],d.serialize=function(a,d){var g={},j=h(d),k=e(a,j);return c.each(k,function(a){var c=b(a),d=f(c),e=j.keyExtractors.get(d),h=e(c),k=j.inputReaders.get(d),l=k(c),m=j.keyAssignmentValidators.get(d);if(m(c,h,l)){var n=j.keySplitter(h);g=i(g,n,l)}}),g},d.deserialize=function(a,d,g){var i=h(g),k=e(a,i),l=j(i,d);c.each(k,function(a){var c=b(a),d=f(c),e=i.keyExtractors.get(d),g=e(c),h=i.inputWriters.get(d),j=l[g];h(c,j)})};var e=function(a,d){var e=g(a),h=e.elements;return h=c.reject(h,function(a){var e,g=f(a),h=d.keyExtractors.get(g),i=h(b(a)),j=c.include(d.ignoredTypes,g),k=c.include(d.include,i),l=c.include(d.exclude,i);return k?e=!1:d.include?e=!0:e=l||j,e}),h},f=function(a){var c,d=b(a),e=d[0].tagName,f=e;return e.toLowerCase()==="input"&&(c=d.attr("type"),c?f=c:f="text"),f.toLowerCase()},g=function(a){return c.isUndefined(a.$el)&&a.tagName.toLowerCase()==="form"?a:a.$el.is("form")?a.el:a.$("form")[0]},h=function(a){var b=c.clone(a)||{};return b.ignoredTypes=c.clone(d.ignoredTypes),b.inputReaders=b.inputReaders||d.InputReaders,b.inputWriters=b.inputWriters||d.InputWriters,b.keyExtractors=b.keyExtractors||d.KeyExtractors,b.keySplitter=b.keySplitter||d.KeySplitter,b.keyJoiner=b.keyJoiner||d.KeyJoiner,b.keyAssignmentValidators=b.keyAssignmentValidators||d.KeyAssignmentValidators,b},i=function(a,b,d){if(!b)return a;var e=b.shift();return a[e]||(a[e]=c.isArray(e)?[]:{}),b.length===0&&(c.isArray(a[e])?a[e].push(d):a[e]=d),b.length>0&&i(a[e],b,d),a},j=function(a,b,d){var e={};return c.each(b,function(b,f){var g={};d&&(f=a.keyJoiner(d,f)),c.isArray(b)?(f+="[]",g[f]=b):c.isObject(b)?g=j(a,b,f):g[f]=b,c.extend(e,g)}),e};return d}(c,b,a),c.Syphon.TypeRegistry=function(){this.registeredTypes={}},c.Syphon.TypeRegistry.extend=c.Model.extend,a.extend(c.Syphon.TypeRegistry.prototype,{get:function(a){var b=this.registeredTypes[a];return b||(b=this.registeredTypes["default"]),b},register:function(a,b){this.registeredTypes[a]=b},registerDefault:function(a){this.registeredTypes["default"]=a},unregister:function(a){this.registeredTypes[a]&&delete this.registeredTypes[a]}}),c.Syphon.KeyExtractorSet=c.Syphon.TypeRegistry.extend(),c.Syphon.KeyExtractors=new c.Syphon.KeyExtractorSet,c.Syphon.KeyExtractors.registerDefault(function(a){return a.prop("name")}),c.Syphon.InputReaderSet=c.Syphon.TypeRegistry.extend(),c.Syphon.InputReaders=new c.Syphon.InputReaderSet,c.Syphon.InputReaders.registerDefault(function(a){return a.val()}),c.Syphon.InputReaders.register("checkbox",function(a){var b=a.prop("checked");return b}),c.Syphon.InputWriterSet=c.Syphon.TypeRegistry.extend(),c.Syphon.InputWriters=new c.Syphon.InputWriterSet,c.Syphon.InputWriters.registerDefault(function(a,b){a.val(b)}),c.Syphon.InputWriters.register("checkbox",function(a,b){a.prop("checked",b)}),c.Syphon.InputWriters.register("radio",function(a,b){a.prop("checked",a.val()===b)}),c.Syphon.KeyAssignmentValidatorSet=c.Syphon.TypeRegistry.extend(),c.Syphon.KeyAssignmentValidators=new c.Syphon.KeyAssignmentValidatorSet,c.Syphon.KeyAssignmentValidators.registerDefault(function(){return!0}),c.Syphon.KeyAssignmentValidators.register("radio",function(a,b,c){return a.prop("checked")}),c.Syphon.KeySplitter=function(a){var b=a.match(/[^\[\]]+/g);return a.indexOf("[]")===a.length-2&&(lastKey=b.pop(),b.push([lastKey])),b},c.Syphon.KeyJoiner=function(a,b){return a+"["+b+"]"},c.Syphon});
\ No newline at end of file
diff --git a/lib/backbone.syphon.js b/lib/backbone.syphon.js
index 3cd1537..a3816fe 100644
--- a/lib/backbone.syphon.js
+++ b/lib/backbone.syphon.js
@@ -1,46 +1,70 @@
-// Backbone.Syphon, v0.4.1
-// Copyright (c)2012 Derick Bailey, Muted Solutions, LLC.
-// Distributed under MIT license
-// http://github.com/derickbailey/backbone.syphon
-Backbone.Syphon = (function(Backbone, $, _){
- var Syphon = {};
+(function(root, factory) {
+ if (typeof define === 'function' && define.amd) {
+ define(['underscore', 'backbone', 'jquery'], function(_, Backbone, $) {
+ return factory(_, Backbone, $);
+ });
+ } else if (typeof exports !== 'undefined') {
+ var _ = require('underscore');
+ var Backbone = require('backbone');
+ var $ = require('jquery');
+ module.exports = factory(_, Backbone, $);
+ } else {
+ factory(root._, root.Backbone, root.jQuery);
+ }
+
+}(this, function(_, Backbone, $) {
+ 'use strict';
+
+ var previousSyphon = Backbone.Syphon;
+
+ var Syphon = Backbone.Syphon = {};
+
+ Syphon.VERSION = '0.5.0';
+
+ Syphon.noConflict = function() {
+ Backbone.Syphon = previousSyphon;
+ return this;
+ };
+
+ /* jshint maxstatements: 13, maxlen: 102, maxcomplexity: 8, latedef: false */
+
// Ignore Element Types
// --------------------
-
+
// Tell Syphon to ignore all elements of these types. You can
// push new types to ignore directly in to this array.
- Syphon.ignoredTypes = ["button", "submit", "reset", "fieldset"];
-
+ Syphon.ignoredTypes = ['button', 'submit', 'reset', 'fieldset'];
+
// Syphon
// ------
-
+
// Get a JSON object that represents
// all of the form inputs, in this view.
// Alternately, pass a form element directly
// in place of the view.
Syphon.serialize = function(view, options){
var data = {};
-
+
// Build the configuration
var config = buildConfig(options);
-
+
// Get all of the elements to process
var elements = getInputElements(view, config);
-
+
// Process all of the elements
_.each(elements, function(el){
var $el = $(el);
- var type = getElementType($el);
-
+ var type = getElementType($el);
+
// Get the key for the input
var keyExtractor = config.keyExtractors.get(type);
var key = keyExtractor($el);
-
+
// Get the value for the input
var inputReader = config.inputReaders.get(type);
var value = inputReader($el);
-
+
// Get the key assignment validator and make sure
// it's valid before assigning the value to the key
var validKeyAssignment = config.keyAssignmentValidators.get(type);
@@ -49,7 +73,7 @@ Backbone.Syphon = (function(Backbone, $, _){
data = assignKeyValue(data, keychain, value);
}
});
-
+
// Done; send back the results.
return data;
};
@@ -61,50 +85,50 @@ Backbone.Syphon = (function(Backbone, $, _){
Syphon.deserialize = function(view, data, options){
// Build the configuration
var config = buildConfig(options);
-
+
// Get all of the elements to process
var elements = getInputElements(view, config);
-
+
// Flatten the data structure that we are deserializing
var flattenedData = flattenData(config, data);
-
+
// Process all of the elements
_.each(elements, function(el){
var $el = $(el);
- var type = getElementType($el);
-
+ var type = getElementType($el);
+
// Get the key for the input
var keyExtractor = config.keyExtractors.get(type);
var key = keyExtractor($el);
-
+
// Get the input writer and the value to write
var inputWriter = config.inputWriters.get(type);
var value = flattenedData[key];
-
+
// Write the value to the input
inputWriter($el, value);
});
};
-
+
// Helpers
// -------
-
+
// Retrieve all of the form inputs
// from the form
var getInputElements = function(view, config){
var form = getForm(view);
var elements = form.elements;
-
+
elements = _.reject(elements, function(el){
var reject;
var type = getElementType(el);
var extractor = config.keyExtractors.get(type);
var identifier = extractor($(el));
-
+
var foundInIgnored = _.include(config.ignoredTypes, type);
var foundInInclude = _.include(config.include, identifier);
var foundInExclude = _.include(config.exclude, identifier);
-
+
if (foundInInclude){
reject = false;
} else {
@@ -114,13 +138,13 @@ Backbone.Syphon = (function(Backbone, $, _){
reject = (foundInExclude || foundInIgnored);
}
}
-
+
return reject;
});
-
+
return elements;
};
-
+
// Determine what type of element this is. It
// will either return the `type` attribute of
// an `` element, or the `tagName` of
@@ -130,37 +154,37 @@ Backbone.Syphon = (function(Backbone, $, _){
var $el = $(el);
var tagName = $el[0].tagName;
var type = tagName;
-
- if (tagName.toLowerCase() === "input"){
- typeAttr = $el.attr("type");
+
+ if (tagName.toLowerCase() === 'input'){
+ typeAttr = $el.attr('type');
if (typeAttr){
type = typeAttr;
} else {
- type = "text";
+ type = 'text';
}
}
-
+
// Always return the type as lowercase
// so it can be matched to lowercase
// type registrations.
return type.toLowerCase();
};
- // If a form element is given, just return it.
+ // If a form element is given, just return it.
// Otherwise, get the form element from the view.
var getForm = function(viewOrForm){
if (_.isUndefined(viewOrForm.$el) && viewOrForm.tagName.toLowerCase() === 'form'){
return viewOrForm;
} else {
- return viewOrForm.$el.is("form") ? viewOrForm.el : viewOrForm.$("form")[0];
+ return viewOrForm.$el.is('form') ? viewOrForm.el : viewOrForm.$('form')[0];
}
};
-
+
// Build a configuration object and initialize
// default values.
var buildConfig = function(options){
var config = _.clone(options) || {};
-
+
config.ignoredTypes = _.clone(Syphon.ignoredTypes);
config.inputReaders = config.inputReaders || Syphon.InputReaders;
config.inputWriters = config.inputWriters || Syphon.InputWriters;
@@ -168,41 +192,41 @@ Backbone.Syphon = (function(Backbone, $, _){
config.keySplitter = config.keySplitter || Syphon.KeySplitter;
config.keyJoiner = config.keyJoiner || Syphon.KeyJoiner;
config.keyAssignmentValidators = config.keyAssignmentValidators || Syphon.KeyAssignmentValidators;
-
+
return config;
};
-
- // Assigns `value` to a parsed JSON key.
+
+ // Assigns `value` to a parsed JSON key.
//
// The first parameter is the object which will be
// modified to store the key/value pair.
//
- // The second parameter accepts an array of keys as a
- // string with an option array containing a
+ // The second parameter accepts an array of keys as a
+ // string with an option array containing a
// single string as the last option.
//
// The third parameter is the value to be assigned.
//
// Examples:
//
- // `["foo", "bar", "baz"] => {foo: {bar: {baz: "value"}}}`
- //
- // `["foo", "bar", ["baz"]] => {foo: {bar: {baz: ["value"]}}}`
- //
+ // `['foo', 'bar', 'baz'] => {foo: {bar: {baz: 'value'}}}`
+ //
+ // `['foo', 'bar', ['baz']] => {foo: {bar: {baz: ['value']}}}`
+ //
// When the final value is an array with a string, the key
// becomes an array, and values are pushed in to the array,
- // allowing multiple fields with the same name to be
+ // allowing multiple fields with the same name to be
// assigned to the array.
var assignKeyValue = function(obj, keychain, value) {
if (!keychain){ return obj; }
-
+
var key = keychain.shift();
-
+
// build the current object we need to store data
if (!obj[key]){
obj[key] = _.isArray(key) ? [] : {};
}
-
+
// if it's the last key in the chain, assign the value directly
if (keychain.length === 0){
if (_.isArray(obj[key])){
@@ -211,15 +235,15 @@ Backbone.Syphon = (function(Backbone, $, _){
obj[key] = value;
}
}
-
+
// recursive parsing of the array, depth-first
if (keychain.length > 0){
assignKeyValue(obj[key], keychain, value);
}
-
+
return obj;
};
-
+
// Flatten the data structure in to nested strings, using the
// provided `KeyJoiner` function.
//
@@ -229,241 +253,231 @@ Backbone.Syphon = (function(Backbone, $, _){
//
// ```js
// {
- // widget: "wombat",
+ // widget: 'wombat',
// foo: {
- // bar: "baz",
+ // bar: 'baz',
// baz: {
- // quux: "qux"
+ // quux: 'qux'
// },
- // quux: ["foo", "bar"]
+ // quux: ['foo', 'bar']
// }
// }
// ```
//
- // With a KeyJoiner that uses [ ] square brackets,
+ // With a KeyJoiner that uses [ ] square brackets,
// should produce this output:
//
// ```js
// {
- // "widget": "wombat",
- // "foo[bar]": "baz",
- // "foo[baz][quux]": "qux",
- // "foo[quux]": ["foo", "bar"]
+ // 'widget': 'wombat',
+ // 'foo[bar]': 'baz',
+ // 'foo[baz][quux]': 'qux',
+ // 'foo[quux]': ['foo', 'bar']
// }
// ```
var flattenData = function(config, data, parentKey){
var flatData = {};
-
+
_.each(data, function(value, keyName){
var hash = {};
-
+
// If there is a parent key, join it with
// the current, child key.
if (parentKey){
keyName = config.keyJoiner(parentKey, keyName);
}
-
+
if (_.isArray(value)){
- keyName += "[]";
+ keyName += '[]';
hash[keyName] = value;
} else if (_.isObject(value)){
hash = flattenData(config, value, keyName);
} else {
hash[keyName] = value;
}
-
+
// Store the resulting key/value pairs in the
// final flattened data object
_.extend(flatData, hash);
});
-
+
return flatData;
};
-
- return Syphon;
-})(Backbone, jQuery, _);
-
-// Type Registry
-// -------------
-
-// Type Registries allow you to register something to
-// an input type, and retrieve either the item registered
-// for a specific type or the default registration
-Backbone.Syphon.TypeRegistry = function(){
- this.registeredTypes = {};
-};
-
-// Borrow Backbone's `extend` keyword for our TypeRegistry
-Backbone.Syphon.TypeRegistry.extend = Backbone.Model.extend;
-
-_.extend(Backbone.Syphon.TypeRegistry.prototype, {
-
- // Get the registered item by type. If nothing is
- // found for the specified type, the default is
- // returned.
- get: function(type){
- var item = this.registeredTypes[type];
-
- if (!item){
- item = this.registeredTypes["default"];
+
+ // Type Registry
+ // -------------
+
+ // Type Registries allow you to register something to
+ // an input type, and retrieve either the item registered
+ // for a specific type or the default registration
+ var TypeRegistry = Syphon.TypeRegistry = function() {
+ this.registeredTypes = {};
+ };
+
+ // Borrow Backbone's `extend` keyword for our TypeRegistry
+ TypeRegistry.extend = Backbone.Model.extend;
+
+ _.extend(TypeRegistry.prototype, {
+
+ // Get the registered item by type. If nothing is
+ // found for the specified type, the default is
+ // returned.
+ get: function(type){
+ return this.registeredTypes[type] || this.registeredTypes['default'];
+ },
+
+ // Register a new item for a specified type
+ register: function(type, item) {
+ this.registeredTypes[type] = item;
+ },
+
+ // Register a default item to be used when no
+ // item for a specified type is found
+ registerDefault: function(item) {
+ this.registeredTypes['default'] = item;
+ },
+
+ // Remove an item from a given type registration
+ unregister: function(type) {
+ if (this.registeredTypes[type]) {
+ delete this.registeredTypes[type];
+ }
}
-
- return item;
- },
-
- // Register a new item for a specified type
- register: function(type, item){
- this.registeredTypes[type] = item;
- },
-
- // Register a default item to be used when no
- // item for a specified type is found
- registerDefault: function(item){
- this.registeredTypes["default"] = item;
- },
-
- // Remove an item from a given type registration
- unregister: function(type){
- if (this.registeredTypes[type]){
- delete this.registeredTypes[type];
+ });
+
+ // Key Extractors
+ // --------------
+
+ // Key extractors produce the "key" in `{key: "value"}`
+ // pairs, when serializing.
+ var KeyExtractorSet = Syphon.KeyExtractorSet = TypeRegistry.extend();
+
+ // Built-in Key Extractors
+ var KeyExtractors = Syphon.KeyExtractors = new KeyExtractorSet();
+
+ // The default key extractor, which uses the
+ // input element's "name" attribute
+ KeyExtractors.registerDefault(function($el) {
+ return $el.prop('name') || '';
+ });
+
+ // Input Readers
+ // -------------
+
+ // Input Readers are used to extract the value from
+ // an input element, for the serialized object result
+ var InputReaderSet = Syphon.InputReaderSet = TypeRegistry.extend();
+
+ // Built-in Input Readers
+ var InputReaders = Syphon.InputReaders = new InputReaderSet();
+
+ // The default input reader, which uses an input
+ // element's "value"
+ InputReaders.registerDefault(function($el){
+ return $el.val();
+ });
+
+ // Checkbox reader, returning a boolean value for
+ // whether or not the checkbox is checked.
+ InputReaders.register('checkbox', function($el) {
+ return $el.prop('checked');
+ });
+
+ // Input Writers
+ // -------------
+
+ // Input Writers are used to insert a value from an
+ // object into an input element.
+ var InputWriterSet = Syphon.InputWriterSet = TypeRegistry.extend();
+
+ // Built-in Input Writers
+ var InputWriters = Syphon.InputWriters = new InputWriterSet();
+
+ // The default input writer, which sets an input
+ // element's "value"
+ InputWriters.registerDefault(function($el, value) {
+ $el.val(value);
+ });
+
+ // Checkbox writer, set whether or not the checkbox is checked
+ // depending on the boolean value.
+ InputWriters.register('checkbox', function($el, value) {
+ $el.prop('checked', value);
+ });
+
+ // Radio button writer, set whether or not the radio button is
+ // checked. The button should only be checked if it's value
+ // equals the given value.
+ InputWriters.register('radio', function($el, value) {
+ $el.prop('checked', $el.val() === value.toString());
+ });
+
+ // Key Assignment Validators
+ // -------------------------
+
+ // Key Assignment Validators are used to determine whether or not a
+ // key should be assigned to a value, after the key and value have been
+ // extracted from the element. This is the last opportunity to prevent
+ // bad data from getting serialized to your object.
+
+ var KeyAssignmentValidatorSet = Syphon.KeyAssignmentValidatorSet = TypeRegistry.extend();
+
+ // Build-in Key Assignment Validators
+ var KeyAssignmentValidators = Syphon.KeyAssignmentValidators = new KeyAssignmentValidatorSet();
+
+ // Everything is valid by default
+ KeyAssignmentValidators.registerDefault(function() {
+ return true;
+ });
+
+ // But only the "checked" radio button for a given
+ // radio button group is valid
+ KeyAssignmentValidators.register('radio', function($el, key, value) {
+ return $el.prop('checked');
+ });
+
+ // Backbone.Syphon.KeySplitter
+ // ---------------------------
+
+ // This function is used to split DOM element keys in to an array
+ // of parts, which are then used to create a nested result structure.
+ // returning `["foo", "bar"]` results in `{foo: { bar: "value" }}`.
+ //
+ // Override this method to use a custom key splitter, such as:
+ // ``, `return key.split(".")`
+ Syphon.KeySplitter = function(key) {
+ var matches = key.match(/[^\[\]]+/g);
+ var lastKey;
+
+ if (key.indexOf('[]') === key.length - 2) {
+ lastKey = matches.pop();
+ matches.push([lastKey]);
}
- }
-});
-
-
-
-
-// Key Extractors
-// --------------
-
-// Key extractors produce the "key" in `{key: "value"}`
-// pairs, when serializing.
-Backbone.Syphon.KeyExtractorSet = Backbone.Syphon.TypeRegistry.extend();
-
-// Built-in Key Extractors
-Backbone.Syphon.KeyExtractors = new Backbone.Syphon.KeyExtractorSet();
-
-// The default key extractor, which uses the
-// input element's "id" attribute
-Backbone.Syphon.KeyExtractors.registerDefault(function($el){
- return $el.prop("name");
-});
-
-
-// Input Readers
-// -------------
-
-// Input Readers are used to extract the value from
-// an input element, for the serialized object result
-Backbone.Syphon.InputReaderSet = Backbone.Syphon.TypeRegistry.extend();
-
-// Built-in Input Readers
-Backbone.Syphon.InputReaders = new Backbone.Syphon.InputReaderSet();
-
-// The default input reader, which uses an input
-// element's "value"
-Backbone.Syphon.InputReaders.registerDefault(function($el){
- return $el.val();
-});
-
-// Checkbox reader, returning a boolean value for
-// whether or not the checkbox is checked.
-Backbone.Syphon.InputReaders.register("checkbox", function($el){
- var checked = $el.prop("checked");
- return checked;
-});
-
-
-// Input Writers
-// -------------
-
-// Input Writers are used to insert a value from an
-// object into an input element.
-Backbone.Syphon.InputWriterSet = Backbone.Syphon.TypeRegistry.extend();
-
-// Built-in Input Writers
-Backbone.Syphon.InputWriters = new Backbone.Syphon.InputWriterSet();
-
-// The default input writer, which sets an input
-// element's "value"
-Backbone.Syphon.InputWriters.registerDefault(function($el, value){
- $el.val(value);
-});
-
-// Checkbox writer, set whether or not the checkbox is checked
-// depending on the boolean value.
-Backbone.Syphon.InputWriters.register("checkbox", function($el, value){
- $el.prop("checked", value);
-});
-
-// Radio button writer, set whether or not the radio button is
-// checked. The button should only be checked if it's value
-// equals the given value.
-Backbone.Syphon.InputWriters.register("radio", function($el, value){
- $el.prop("checked", $el.val() === value);
-});
-
-// Key Assignment Validators
-// -------------------------
-
-// Key Assignment Validators are used to determine whether or not a
-// key should be assigned to a value, after the key and value have been
-// extracted from the element. This is the last opportunity to prevent
-// bad data from getting serialized to your object.
-
-Backbone.Syphon.KeyAssignmentValidatorSet = Backbone.Syphon.TypeRegistry.extend();
-
-// Build-in Key Assignment Validators
-Backbone.Syphon.KeyAssignmentValidators = new Backbone.Syphon.KeyAssignmentValidatorSet();
-
-// Everything is valid by default
-Backbone.Syphon.KeyAssignmentValidators.registerDefault(function(){ return true; });
-
-// But only the "checked" radio button for a given
-// radio button group is valid
-Backbone.Syphon.KeyAssignmentValidators.register("radio", function($el, key, value){
- return $el.prop("checked");
-});
-
-
-// Backbone.Syphon.KeySplitter
-// ---------------------------
-
-// This function is used to split DOM element keys in to an array
-// of parts, which are then used to create a nested result structure.
-// returning `["foo", "bar"]` results in `{foo: { bar: "value" }}`.
-//
-// Override this method to use a custom key splitter, such as:
-// ``, `return key.split(".")`
-Backbone.Syphon.KeySplitter = function(key){
- var matches = key.match(/[^\[\]]+/g);
-
- if (key.indexOf("[]") === key.length - 2){
- lastKey = matches.pop();
- matches.push([lastKey]);
- }
-
- return matches;
-}
-
-
-// Backbone.Syphon.KeyJoiner
-// -------------------------
-
-// Take two segments of a key and join them together, to create the
-// de-normalized key name, when deserializing a data structure back
-// in to a form.
-//
-// Example:
-//
-// With this data strucutre `{foo: { bar: {baz: "value", quux: "another"} } }`,
-// the key joiner will be called with these parameters, and assuming the
-// join happens with "[ ]" square brackets, the specified output:
-//
-// `KeyJoiner("foo", "bar")` //=> "foo[bar]"
-// `KeyJoiner("foo[bar]", "baz")` //=> "foo[bar][baz]"
-// `KeyJoiner("foo[bar]", "quux")` //=> "foo[bar][quux]"
+
+ return matches;
+ };
+
+ // Backbone.Syphon.KeyJoiner
+ // -------------------------
+
+ // Take two segments of a key and join them together, to create the
+ // de-normalized key name, when deserializing a data structure back
+ // in to a form.
+ //
+ // Example:
+ //
+ // With this data strucutre `{foo: { bar: {baz: "value", quux: "another"} } }`,
+ // the key joiner will be called with these parameters, and assuming the
+ // join happens with "[ ]" square brackets, the specified output:
+ //
+ // `KeyJoiner("foo", "bar")` //=> "foo[bar]"
+ // `KeyJoiner("foo[bar]", "baz")` //=> "foo[bar][baz]"
+ // `KeyJoiner("foo[bar]", "quux")` //=> "foo[bar][quux]"
+
+ Syphon.KeyJoiner = function(parentKey, childKey) {
+ return parentKey + '[' + childKey + ']';
+ };
+
-Backbone.Syphon.KeyJoiner = function(parentKey, childKey){
- return parentKey + "[" + childKey + "]";
-}
+ return Backbone.Syphon;
+}));
diff --git a/lib/backbone.syphon.min.js b/lib/backbone.syphon.min.js
index e9cb073..752ffae 100644
--- a/lib/backbone.syphon.min.js
+++ b/lib/backbone.syphon.min.js
@@ -1,5 +1,7 @@
-// Backbone.Syphon, v0.4.1
-// Copyright (c)2012 Derick Bailey, Muted Solutions, LLC.
+// Backbone.Syphon, v0.5.0
+// Copyright (c) 2014 Derick Bailey, Muted Solutions, LLC.
// Distributed under MIT license
-// http://github.com/derickbailey/backbone.syphon
-Backbone.Syphon=function(a,b,c){var d={};d.ignoredTypes=["button","submit","reset","fieldset"],d.serialize=function(a,d){var g={},j=h(d),k=e(a,j);return c.each(k,function(a){var c=b(a),d=f(c),e=j.keyExtractors.get(d),h=e(c),k=j.inputReaders.get(d),l=k(c),m=j.keyAssignmentValidators.get(d);if(m(c,h,l)){var n=j.keySplitter(h);g=i(g,n,l)}}),g},d.deserialize=function(a,d,g){var i=h(g),k=e(a,i),l=j(i,d);c.each(k,function(a){var c=b(a),d=f(c),e=i.keyExtractors.get(d),g=e(c),h=i.inputWriters.get(d),j=l[g];h(c,j)})};var e=function(a,d){var e=g(a),h=e.elements;return h=c.reject(h,function(a){var e,g=f(a),h=d.keyExtractors.get(g),i=h(b(a)),j=c.include(d.ignoredTypes,g),k=c.include(d.include,i),l=c.include(d.exclude,i);return k?e=!1:d.include?e=!0:e=l||j,e}),h},f=function(a){var c,d=b(a),e=d[0].tagName,f=e;return e.toLowerCase()==="input"&&(c=d.attr("type"),c?f=c:f="text"),f.toLowerCase()},g=function(a){return c.isUndefined(a.$el)&&a.tagName.toLowerCase()==="form"?a:a.$el.is("form")?a.el:a.$("form")[0]},h=function(a){var b=c.clone(a)||{};return b.ignoredTypes=c.clone(d.ignoredTypes),b.inputReaders=b.inputReaders||d.InputReaders,b.inputWriters=b.inputWriters||d.InputWriters,b.keyExtractors=b.keyExtractors||d.KeyExtractors,b.keySplitter=b.keySplitter||d.KeySplitter,b.keyJoiner=b.keyJoiner||d.KeyJoiner,b.keyAssignmentValidators=b.keyAssignmentValidators||d.KeyAssignmentValidators,b},i=function(a,b,d){if(!b)return a;var e=b.shift();return a[e]||(a[e]=c.isArray(e)?[]:{}),b.length===0&&(c.isArray(a[e])?a[e].push(d):a[e]=d),b.length>0&&i(a[e],b,d),a},j=function(a,b,d){var e={};return c.each(b,function(b,f){var g={};d&&(f=a.keyJoiner(d,f)),c.isArray(b)?(f+="[]",g[f]=b):c.isObject(b)?g=j(a,b,f):g[f]=b,c.extend(e,g)}),e};return d}(Backbone,jQuery,_),Backbone.Syphon.TypeRegistry=function(){this.registeredTypes={}},Backbone.Syphon.TypeRegistry.extend=Backbone.Model.extend,_.extend(Backbone.Syphon.TypeRegistry.prototype,{get:function(a){var b=this.registeredTypes[a];return b||(b=this.registeredTypes["default"]),b},register:function(a,b){this.registeredTypes[a]=b},registerDefault:function(a){this.registeredTypes["default"]=a},unregister:function(a){this.registeredTypes[a]&&delete this.registeredTypes[a]}}),Backbone.Syphon.KeyExtractorSet=Backbone.Syphon.TypeRegistry.extend(),Backbone.Syphon.KeyExtractors=new Backbone.Syphon.KeyExtractorSet,Backbone.Syphon.KeyExtractors.registerDefault(function(a){return a.prop("name")}),Backbone.Syphon.InputReaderSet=Backbone.Syphon.TypeRegistry.extend(),Backbone.Syphon.InputReaders=new Backbone.Syphon.InputReaderSet,Backbone.Syphon.InputReaders.registerDefault(function(a){return a.val()}),Backbone.Syphon.InputReaders.register("checkbox",function(a){var b=a.prop("checked");return b}),Backbone.Syphon.InputWriterSet=Backbone.Syphon.TypeRegistry.extend(),Backbone.Syphon.InputWriters=new Backbone.Syphon.InputWriterSet,Backbone.Syphon.InputWriters.registerDefault(function(a,b){a.val(b)}),Backbone.Syphon.InputWriters.register("checkbox",function(a,b){a.prop("checked",b)}),Backbone.Syphon.InputWriters.register("radio",function(a,b){a.prop("checked",a.val()===b)}),Backbone.Syphon.KeyAssignmentValidatorSet=Backbone.Syphon.TypeRegistry.extend(),Backbone.Syphon.KeyAssignmentValidators=new Backbone.Syphon.KeyAssignmentValidatorSet,Backbone.Syphon.KeyAssignmentValidators.registerDefault(function(){return!0}),Backbone.Syphon.KeyAssignmentValidators.register("radio",function(a,b,c){return a.prop("checked")}),Backbone.Syphon.KeySplitter=function(a){var b=a.match(/[^\[\]]+/g);return a.indexOf("[]")===a.length-2&&(lastKey=b.pop(),b.push([lastKey])),b},Backbone.Syphon.KeyJoiner=function(a,b){return a+"["+b+"]"};
\ No newline at end of file
+// http://github.com/marionettejs/backbone.syphon
+
+!function(a,b){if("function"==typeof define&&define.amd)define(["underscore","backbone","jquery"],function(a,c,d){return b(a,c,d)});else if("undefined"!=typeof exports){var c=require("underscore"),d=require("backbone"),e=require("jquery");module.exports=b(c,d,e)}else b(a._,a.Backbone,a.jQuery)}(this,function(a,b,c){"use strict";var d=b.Syphon,e=b.Syphon={};e.VERSION="0.5.0",e.noConflict=function(){return b.Syphon=d,this},e.ignoredTypes=["button","submit","reset","fieldset"],e.serialize=function(b,d){var e={},h=i(d),k=f(b,h);return a.each(k,function(a){var b=c(a),d=g(b),f=h.keyExtractors.get(d),i=f(b),k=h.inputReaders.get(d),l=k(b),m=h.keyAssignmentValidators.get(d);if(m(b,i,l)){var n=h.keySplitter(i);e=j(e,n,l)}}),e},e.deserialize=function(b,d,e){var h=i(e),j=f(b,h),l=k(h,d);a.each(j,function(a){var b=c(a),d=g(b),e=h.keyExtractors.get(d),f=e(b),i=h.inputWriters.get(d),j=l[f];i(b,j)})};var f=function(b,d){var e=h(b),f=e.elements;return f=a.reject(f,function(b){var e,f=g(b),h=d.keyExtractors.get(f),i=h(c(b)),j=a.include(d.ignoredTypes,f),k=a.include(d.include,i),l=a.include(d.exclude,i);return e=k?!1:d.include?!0:l||j})},g=function(a){var b,d=c(a),e=d[0].tagName,f=e;return"input"===e.toLowerCase()&&(b=d.attr("type"),f=b?b:"text"),f.toLowerCase()},h=function(b){return a.isUndefined(b.$el)&&"form"===b.tagName.toLowerCase()?b:b.$el.is("form")?b.el:b.$("form")[0]},i=function(b){var c=a.clone(b)||{};return c.ignoredTypes=a.clone(e.ignoredTypes),c.inputReaders=c.inputReaders||e.InputReaders,c.inputWriters=c.inputWriters||e.InputWriters,c.keyExtractors=c.keyExtractors||e.KeyExtractors,c.keySplitter=c.keySplitter||e.KeySplitter,c.keyJoiner=c.keyJoiner||e.KeyJoiner,c.keyAssignmentValidators=c.keyAssignmentValidators||e.KeyAssignmentValidators,c},j=function(b,c,d){if(!c)return b;var e=c.shift();return b[e]||(b[e]=a.isArray(e)?[]:{}),0===c.length&&(a.isArray(b[e])?b[e].push(d):b[e]=d),c.length>0&&j(b[e],c,d),b},k=function(b,c,d){var e={};return a.each(c,function(c,f){var g={};d&&(f=b.keyJoiner(d,f)),a.isArray(c)?(f+="[]",g[f]=c):a.isObject(c)?g=k(b,c,f):g[f]=c,a.extend(e,g)}),e},l=e.TypeRegistry=function(){this.registeredTypes={}};l.extend=b.Model.extend,a.extend(l.prototype,{get:function(a){return this.registeredTypes[a]||this.registeredTypes["default"]},register:function(a,b){this.registeredTypes[a]=b},registerDefault:function(a){this.registeredTypes["default"]=a},unregister:function(a){this.registeredTypes[a]&&delete this.registeredTypes[a]}});var m=e.KeyExtractorSet=l.extend(),n=e.KeyExtractors=new m;n.registerDefault(function(a){return a.prop("name")||""});var o=e.InputReaderSet=l.extend(),p=e.InputReaders=new o;p.registerDefault(function(a){return a.val()}),p.register("checkbox",function(a){return a.prop("checked")});var q=e.InputWriterSet=l.extend(),r=e.InputWriters=new q;r.registerDefault(function(a,b){a.val(b)}),r.register("checkbox",function(a,b){a.prop("checked",b)}),r.register("radio",function(a,b){a.prop("checked",a.val()===b.toString())});var s=e.KeyAssignmentValidatorSet=l.extend(),t=e.KeyAssignmentValidators=new s;return t.registerDefault(function(){return!0}),t.register("radio",function(a){return a.prop("checked")}),e.KeySplitter=function(a){var b,c=a.match(/[^\[\]]+/g);return a.indexOf("[]")===a.length-2&&(b=c.pop(),c.push([b])),c},e.KeyJoiner=function(a,b){return a+"["+b+"]"},b.Syphon});
+//# sourceMappingURL=backbone.syphon.min.map
\ No newline at end of file
diff --git a/lib/backbone.syphon.min.map b/lib/backbone.syphon.min.map
new file mode 100644
index 0000000..833e277
--- /dev/null
+++ b/lib/backbone.syphon.min.map
@@ -0,0 +1 @@
+{"version":3,"file":"backbone.syphon.min.js","sources":["backbone.syphon.js"],"names":["root","factory","define","amd","_","Backbone","$","exports","require","module","jQuery","this","previousSyphon","Syphon","VERSION","noConflict","ignoredTypes","serialize","view","options","data","config","buildConfig","elements","getInputElements","each","el","$el","type","getElementType","keyExtractor","keyExtractors","get","key","inputReader","inputReaders","value","validKeyAssignment","keyAssignmentValidators","keychain","keySplitter","assignKeyValue","deserialize","flattenedData","flattenData","inputWriter","inputWriters","form","getForm","reject","extractor","identifier","foundInIgnored","include","foundInInclude","foundInExclude","exclude","typeAttr","tagName","toLowerCase","attr","viewOrForm","isUndefined","is","clone","InputReaders","InputWriters","KeyExtractors","KeySplitter","keyJoiner","KeyJoiner","KeyAssignmentValidators","obj","shift","isArray","length","push","parentKey","flatData","keyName","hash","isObject","extend","TypeRegistry","registeredTypes","Model","prototype","register","item","registerDefault","unregister","KeyExtractorSet","prop","InputReaderSet","val","InputWriterSet","toString","KeyAssignmentValidatorSet","lastKey","matches","match","indexOf","pop","childKey"],"mappings":";;;;;CAAC,SAASA,EAAMC,GAEd,GAAsB,kBAAXC,SAAyBA,OAAOC,IACzCD,QAAQ,aAAc,WAAY,UAAW,SAASE,EAAGC,EAAUC,GACjE,MAAOL,GAAQG,EAAGC,EAAUC,SAEzB,IAAuB,mBAAZC,SAAyB,CACzC,GAAIH,GAAII,QAAQ,cACZH,EAAWG,QAAQ,YACnBF,EAAIE,QAAQ,SAChBC,QAAOF,QAAUN,EAAQG,EAAGC,EAAUC,OAEtCL,GAAQD,EAAKI,EAAGJ,EAAKK,SAAUL,EAAKU,SAGtCC,KAAM,SAASP,EAAGC,EAAUC,GAC5B,YAEA,IAAIM,GAAiBP,EAASQ,OAE1BA,EAASR,EAASQ,SAEtBA,GAAOC,QAAU,QAEjBD,EAAOE,WAAa,WAElB,MADAV,GAASQ,OAASD,EACXD,MAUTE,EAAOG,cAAgB,SAAU,SAAU,QAAS,YASpDH,EAAOI,UAAY,SAASC,EAAMC,GAChC,GAAIC,MAGAC,EAASC,EAAYH,GAGrBI,EAAWC,EAAiBN,EAAMG,EAyBtC,OAtBAjB,GAAEqB,KAAKF,EAAU,SAASG,GACxB,GAAIC,GAAMrB,EAAEoB,GACRE,EAAOC,EAAeF,GAGtBG,EAAeT,EAAOU,cAAcC,IAAIJ,GACxCK,EAAMH,EAAaH,GAGnBO,EAAcb,EAAOc,aAAaH,IAAIJ,GACtCQ,EAAQF,EAAYP,GAIpBU,EAAqBhB,EAAOiB,wBAAwBN,IAAIJ,EAC5D,IAAIS,EAAmBV,EAAKM,EAAKG,GAAO,CACtC,GAAIG,GAAWlB,EAAOmB,YAAYP,EAClCb,GAAOqB,EAAerB,EAAMmB,EAAUH,MAKnChB,GAOTP,EAAO6B,YAAc,SAASxB,EAAME,EAAMD,GAExC,GAAIE,GAASC,EAAYH,GAGrBI,EAAWC,EAAiBN,EAAMG,GAGlCsB,EAAgBC,EAAYvB,EAAQD,EAGxChB,GAAEqB,KAAKF,EAAU,SAASG,GACxB,GAAIC,GAAMrB,EAAEoB,GACRE,EAAOC,EAAeF,GAGtBG,EAAeT,EAAOU,cAAcC,IAAIJ,GACxCK,EAAMH,EAAaH,GAGnBkB,EAAcxB,EAAOyB,aAAad,IAAIJ,GACtCQ,EAAQO,EAAcV,EAG1BY,GAAYlB,EAAKS,KASrB,IAAIZ,GAAmB,SAASN,EAAMG,GACpC,GAAI0B,GAAOC,EAAQ9B,GACfK,EAAWwB,EAAKxB,QAyBpB,OAvBAA,GAAWnB,EAAE6C,OAAO1B,EAAU,SAASG,GACrC,GAAIuB,GACArB,EAAOC,EAAeH,GACtBwB,EAAY7B,EAAOU,cAAcC,IAAIJ,GACrCuB,EAAaD,EAAU5C,EAAEoB,IAEzB0B,EAAiBhD,EAAEiD,QAAQhC,EAAOL,aAAcY,GAChD0B,EAAiBlD,EAAEiD,QAAQhC,EAAOgC,QAASF,GAC3CI,EAAiBnD,EAAEiD,QAAQhC,EAAOmC,QAASL,EAY/C,OATEF,GADEK,GACO,EAELjC,EAAOgC,SACA,EAECE,GAAkBH,KAchCvB,EAAiB,SAASH,GAC5B,GAAI+B,GACA9B,EAAMrB,EAAEoB,GACRgC,EAAU/B,EAAI,GAAG+B,QACjB9B,EAAO8B,CAcX,OAZ8B,UAA1BA,EAAQC,gBACVF,EAAW9B,EAAIiC,KAAK,QAElBhC,EADE6B,EACKA,EAEA,QAOJ7B,EAAK+B,eAKVX,EAAU,SAASa,GACrB,MAAIzD,GAAE0D,YAAYD,EAAWlC,MAA6C,SAArCkC,EAAWH,QAAQC,cAC/CE,EAEAA,EAAWlC,IAAIoC,GAAG,QAAUF,EAAWnC,GAAKmC,EAAWvD,EAAE,QAAQ,IAMxEgB,EAAc,SAASH,GACzB,GAAIE,GAASjB,EAAE4D,MAAM7C,MAUrB,OARAE,GAAOL,aAAeZ,EAAE4D,MAAMnD,EAAOG,cACrCK,EAAOc,aAAed,EAAOc,cAAgBtB,EAAOoD,aACpD5C,EAAOyB,aAAezB,EAAOyB,cAAgBjC,EAAOqD,aACpD7C,EAAOU,cAAgBV,EAAOU,eAAiBlB,EAAOsD,cACtD9C,EAAOmB,YAAcnB,EAAOmB,aAAe3B,EAAOuD,YAClD/C,EAAOgD,UAAYhD,EAAOgD,WAAaxD,EAAOyD,UAC9CjD,EAAOiB,wBAA0BjB,EAAOiB,yBAA2BzB,EAAO0D,wBAEnElD,GAwBLoB,EAAiB,SAAS+B,EAAKjC,EAAUH,GAC3C,IAAKG,EAAW,MAAOiC,EAEvB,IAAIvC,GAAMM,EAASkC,OAqBnB,OAlBKD,GAAIvC,KACPuC,EAAIvC,GAAO7B,EAAEsE,QAAQzC,UAIC,IAApBM,EAASoC,SACPvE,EAAEsE,QAAQF,EAAIvC,IAChBuC,EAAIvC,GAAK2C,KAAKxC,GAEdoC,EAAIvC,GAAOG,GAKXG,EAASoC,OAAS,GACpBlC,EAAe+B,EAAIvC,GAAMM,EAAUH,GAG9BoC,GAkCL5B,EAAc,SAASvB,EAAQD,EAAMyD,GACvC,GAAIC,KAyBJ,OAvBA1E,GAAEqB,KAAKL,EAAM,SAASgB,EAAO2C,GAC3B,GAAIC,KAIAH,KACFE,EAAU1D,EAAOgD,UAAUQ,EAAWE,IAGpC3E,EAAEsE,QAAQtC,IACZ2C,GAAW,KACXC,EAAKD,GAAW3C,GACPhC,EAAE6E,SAAS7C,GACpB4C,EAAOpC,EAAYvB,EAAQe,EAAO2C,GAElCC,EAAKD,GAAW3C,EAKlBhC,EAAE8E,OAAOJ,EAAUE,KAGdF,GASLK,EAAetE,EAAOsE,aAAe,WACvCxE,KAAKyE,mBAIPD,GAAaD,OAAS7E,EAASgF,MAAMH,OAErC9E,EAAE8E,OAAOC,EAAaG,WAKpBtD,IAAK,SAASJ,GACZ,MAAOjB,MAAKyE,gBAAgBxD,IAASjB,KAAKyE,gBAAgB,YAI5DG,SAAU,SAAS3D,EAAM4D,GACvB7E,KAAKyE,gBAAgBxD,GAAQ4D,GAK/BC,gBAAiB,SAASD,GACxB7E,KAAKyE,gBAAgB,WAAaI,GAIpCE,WAAY,SAAS9D,GACfjB,KAAKyE,gBAAgBxD,UAChBjB,MAAKyE,gBAAgBxD,KAUlC,IAAI+D,GAAkB9E,EAAO8E,gBAAkBR,EAAaD,SAGxDf,EAAgBtD,EAAOsD,cAAgB,GAAIwB,EAI/CxB,GAAcsB,gBAAgB,SAAS9D,GACrC,MAAOA,GAAIiE,KAAK,SAAW,IAQ7B,IAAIC,GAAiBhF,EAAOgF,eAAiBV,EAAaD,SAGtDjB,EAAepD,EAAOoD,aAAe,GAAI4B,EAI7C5B,GAAawB,gBAAgB,SAAS9D,GACpC,MAAOA,GAAImE,QAKb7B,EAAasB,SAAS,WAAY,SAAS5D,GACzC,MAAOA,GAAIiE,KAAK,YAQlB,IAAIG,GAAiBlF,EAAOkF,eAAiBZ,EAAaD,SAGtDhB,EAAerD,EAAOqD,aAAe,GAAI6B,EAI7C7B,GAAauB,gBAAgB,SAAS9D,EAAKS,GACzCT,EAAImE,IAAI1D,KAKV8B,EAAaqB,SAAS,WAAY,SAAS5D,EAAKS,GAC9CT,EAAIiE,KAAK,UAAWxD,KAMtB8B,EAAaqB,SAAS,QAAS,SAAS5D,EAAKS,GAC3CT,EAAIiE,KAAK,UAAWjE,EAAImE,QAAU1D,EAAM4D,aAW1C,IAAIC,GAA4BpF,EAAOoF,0BAA4Bd,EAAaD,SAG5EX,EAA0B1D,EAAO0D,wBAA0B,GAAI0B,EAwDnE,OArDA1B,GAAwBkB,gBAAgB,WACtC,OAAO,IAKTlB,EAAwBgB,SAAS,QAAS,SAAS5D,GACjD,MAAOA,GAAIiE,KAAK,aAYlB/E,EAAOuD,YAAc,SAASnC,GAC5B,GACIiE,GADAC,EAAUlE,EAAImE,MAAM,YAQxB,OALInE,GAAIoE,QAAQ,QAAUpE,EAAI0C,OAAS,IACrCuB,EAAUC,EAAQG,MAClBH,EAAQvB,MAAMsB,KAGTC,GAoBTtF,EAAOyD,UAAY,SAASO,EAAW0B,GACrC,MAAO1B,GAAY,IAAM0B,EAAW,KAI/BlG,EAASQ"}
\ No newline at end of file