diff --git a/README b/README index 19b1dfba..f5535b09 100644 --- a/README +++ b/README @@ -22,3 +22,4 @@ A. How to get (and contribute) JMVC 5. Make changes in steal or jquerymx, and push them back to your fork. 6. Make a pull request to your fork. + diff --git a/class/class.js b/class/class.js index 18854c74..b48d1d00 100644 --- a/class/class.js +++ b/class/class.js @@ -61,7 +61,7 @@ steal("jquery","jquery/lang/string",function( $ ) { * @test jquery/class/qunit.html * @description Easy inheritance in JavaScript. * - * Class provides simulated inheritance in JavaScript. Use clss to bridge the gap between + * Class provides simulated inheritance in JavaScript. Use Class to bridge the gap between * jQuery's functional programming style and Object Oriented Programming. It * is based off John Resig's [http://ejohn.org/blog/simple-javascript-inheritance/|Simple Class] * Inheritance library. Besides prototypal inheritance, it includes a few important features: @@ -349,7 +349,7 @@ steal("jquery","jquery/lang/string",function( $ ) { clss = $.Class = function() { if (arguments.length) { - clss.extend.apply(clss, arguments); + return clss.extend.apply(clss, arguments); } }; diff --git a/dom/fixture/fixture.js b/dom/fixture/fixture.js index d2355033..672b5a7b 100644 --- a/dom/fixture/fixture.js +++ b/dom/fixture/fixture.js @@ -35,7 +35,10 @@ steal('jquery/dom', var url = settings.fixture; if (/^\/\//.test(url) ) { - url = steal.root.mapJoin(settings.fixture.substr(2))+''; + var sub = settings.fixture.substr(2) + ''; + url = typeof steal === "undefined" ? + url = "/" + sub : + steal.root.mapJoin(sub) +''; } //!steal-remove-start steal.dev.log("looking for fixture in " + url); diff --git a/dom/form_params/form_params.js b/dom/form_params/form_params.js index 69f56ac2..0234c4d4 100644 --- a/dom/form_params/form_params.js +++ b/dom/form_params/form_params.js @@ -2,22 +2,58 @@ * @add jQuery.fn */ steal("jquery/dom").then(function( $ ) { - var radioCheck = /radio|checkbox/i, - keyBreaker = /[^\[\]]+/g, - numberMatcher = /^[\-+]?[0-9]*\.?[0-9]+([eE][\-+]?[0-9]+)?$/; + var keyBreaker = /[^\[\]]+/g, + convertValue = function( value ) { + if ( $.isNumeric( value )) { + return parseFloat( value ); + } else if ( value === 'true') { + return true; + } else if ( value === 'false' ) { + return false; + } else if ( value === '' ) { + return undefined; + } + return value; + }, + nestData = function( elem, type, data, parts, value, seen ) { + var name = parts.shift(); + + if ( parts.length ) { + if ( ! data[ name ] ) { + data[ name ] = {}; + } + // Recursive call + nestData( elem, type, data[ name ], parts, value, seen ); + } else { + + // Handle same name case, as well as "last checkbox checked" + // case + if ( name in seen && type != "radio" && ! $.isArray( data[ name ] )) { + if ( name in data ) { + data[ name ] = [ data[name] ]; + } else { + data[ name ] = []; + } + } else { + seen[ name ] = true; + } - var isNumber = function( value ) { - if ( typeof value == 'number' ) { - return true; - } + // Finally, assign data + if ( ( type == "radio" || type == "checkbox" ) && ! elem.is(":checked") ) { + return + } - if ( typeof value != 'string' ) { - return false; - } + if ( ! data[ name ] ) { + data[ name ] = value; + } else { + data[ name ].push( value ); + } + - return value.match(numberMatcher); - }; + } + }; + $.fn.extend({ /** * @parent dom @@ -53,7 +89,9 @@ steal("jquery/dom").then(function( $ ) { * to the result. Defaults to false. * @return {Object} An object of name-value pairs. */ - formParams: function( params, convert ) { + formParams: function( params ) { + + var convert; // Quick way to determine if something is a boolean if ( !! params === params ) { @@ -63,10 +101,9 @@ steal("jquery/dom").then(function( $ ) { if ( params ) { return this.setParams( params ); - } else if ( this[0].nodeName.toLowerCase() == 'form' && this[0].elements ) { - return jQuery(jQuery.makeArray(this[0].elements)).getParams(convert); + } else { + return this.getParams( convert ); } - return jQuery("input[name], textarea[name], select[name]", this[0]).getParams(convert); }, setParams: function( params ) { @@ -100,63 +137,41 @@ steal("jquery/dom").then(function( $ ) { }, getParams: function( convert ) { var data = {}, + // This is used to keep track of the checkbox names that we've + // already seen, so we know that we should return an array if + // we see it multiple times. Fixes last checkbox checked bug. + seen = {}, current; - convert = convert === undefined ? false : convert; - this.each(function() { - var el = this, - type = el.type && el.type.toLowerCase(); - //if we are submit, ignore - if ((type == 'submit') || !el.name ) { + this.find("[name]").each(function() { + var $this = $(this), + type = $this.attr("type"), + name = $this.attr("name"), + value = $this.val(), + parts; + + // Don't accumulate submit buttons and nameless elements + if ( type == "submit" || ! name ) { return; } - var key = el.name, - value = $.data(el, "value") || $.fn.val.call([el]), - isRadioCheck = radioCheck.test(el.type), - parts = key.match(keyBreaker), - write = !isRadioCheck || !! el.checked, - //make an array of values - lastPart; - - if ( convert ) { - if ( isNumber(value) ) { - value = parseFloat(value); - } else if ( value === 'true') { - value = true; - } else if ( value === 'false' ) { - value = false; - } - if(value === '') { - value = undefined; - } + // Figure out name parts + parts = name.match( keyBreaker ); + if ( ! parts.length ) { + parts = [name]; } - // go through and create nested objects - current = data; - for ( var i = 0; i < parts.length - 1; i++ ) { - if (!current[parts[i]] ) { - current[parts[i]] = {}; - } - current = current[parts[i]]; + // Convert the value + if ( convert ) { + value = convertValue( value ); } - lastPart = parts[parts.length - 1]; - - //now we are on the last part, set the value - if (current[lastPart]) { - if (!$.isArray(current[lastPart]) ) { - current[lastPart] = current[lastPart] === undefined ? [] : [current[lastPart]]; - } - if ( write ) { - current[lastPart].push(value); - } - } else if ( write || !current[lastPart] ) { - current[lastPart] = write ? value : undefined; - } + // Assign data recursively + nestData( $this, type, data, parts, value, seen ); }); + return data; } }); diff --git a/dom/form_params/form_params_test.js b/dom/form_params/form_params_test.js index 93d50fd1..2a9e2f3c 100644 --- a/dom/form_params/form_params_test.js +++ b/dom/form_params/form_params_test.js @@ -10,6 +10,7 @@ module("jquery/dom/form_params") test("with a form", function(){ $("#qunit-test-area").html("//jquery/dom/form_params/test/basics.micro",{}) + var formParams = $("#qunit-test-area form").formParams() ; ok(formParams.params.one === "1","one is right"); @@ -17,12 +18,26 @@ test("with a form", function(){ ok(formParams.params.three === "3","three is right"); same(formParams.params.four,["4","1"],"four is right"); same(formParams.params.five,["2","3"],"five is right"); - equal(typeof formParams.id , 'string', "Id value is empty"); + equal( typeof formParams.singleRadio, "string", "Type of single named radio is string" ); + equal( formParams.singleRadio, "2", "Value of single named radio is right" ); + + ok( $.isArray(formParams.lastOneChecked), "Type of checkbox with last option checked is array" ); + equal( formParams.lastOneChecked, "4", "Value of checkbox with the last option checked is 4" ); }); +test("With a non-form element", function() { + + $("#qunit-test-area").html("//jquery/dom/form_params/test/non-form.micro",{}) + + var formParams = $("#divform").formParams() ; + + equal( formParams.id , "foo-bar-baz", "ID input read correctly" ); + +}); + test("with true false", function(){ $("#qunit-test-area").html("//jquery/dom/form_params/test/truthy.micro",{}); diff --git a/dom/form_params/test/basics.micro b/dom/form_params/test/basics.micro index dfc247ff..14e76957 100644 --- a/dom/form_params/test/basics.micro +++ b/dom/form_params/test/basics.micro @@ -11,6 +11,10 @@ + + + +