Permalink
Browse files

Checkboxradio: Correctly assemble radio group

Closes gh-6659
Closes gh-7082
Fixes gh-7088
  • Loading branch information...
gabrielschulhof committed Feb 17, 2014
1 parent e306bb0 commit 70700a59114584198eaf76e7b6525e966a3442b3
@@ -10,12 +10,15 @@
//>>css.theme: ../css/themes/default/jquery.mobile.theme.css
define( [ "jquery",
+ "../../navigation/path",
"../../jquery.mobile.core",
"../../jquery.mobile.widget",
"./reset" ], function( jQuery ) {
//>>excludeEnd("jqmBuildExclude");
(function( $, undefined ) {
+var escapeId = $.mobile.path.hashToSelector;
+
$.widget( "mobile.checkboxradio", $.extend( {
initSelector: "input:not( :jqmData(role='flipswitch' ) )[type='checkbox'],input[type='radio']:not( :jqmData(role='flipswitch' ))",
@@ -42,7 +45,7 @@ $.widget( "mobile.checkboxradio", $.extend( {
input
.closest( "form, fieldset, :jqmData(role='page'), :jqmData(role='dialog')" )
.find( "label" )
- .filter( "[for='" + $.mobile.path.hashToSelector( input[0].id ) + "']" )
+ .filter( "[for='" + escapeId( input[0].id ) + "']" )
.first(),
inputtype = input[0].type,
checkedClass = "ui-" + inputtype + "-on",
@@ -182,14 +185,51 @@ $.widget( "mobile.checkboxradio", $.extend( {
});
},
- //returns either a set of radios with the same name attribute, or a single checkbox
+ // Returns those radio buttons that are supposed to be in the same group as
+ // this radio button. In the case of a checkbox or a radio lacking a name
+ // attribute, it returns this.element.
_getInputSet: function() {
- if ( this.inputtype === "checkbox" ) {
- return this.element;
+ var selector, formId,
+ radio = this.element[ 0 ],
+ name = radio.name,
+ form = radio.form,
+ doc = this.element.parents().last().get( 0 ),
+
+ // A radio is always a member of its own group
+ radios = this.element;
+
+ // Only start running selectors if this is an attached radio button with a name
+ if ( name && this.inputtype === "radio" && doc ) {
+ selector = "input[type='radio'][name='" + escapeId( name ) + "']";
+
+ // If we're inside a form
+ if ( form ) {
+ formId = form.id;
+
+ // If the form has an ID, collect radios scattered throught the document which
+ // nevertheless are part of the form by way of the value of their form attribute
+ if ( formId ) {
+ radios = $( selector + "[form='" + escapeId( formId ) + "']", doc );
+ }
+
+ // Also add to those the radios in the form itself
+ radios = $( form ).find( selector ).filter( function() {
+
+ // Some radios inside the form may belong to some other form by virtue of
+ // having a form attribute defined on them, so we must filter them out here
+ return ( this.form === form );
+ }).add( radios );
+
+ // If we're outside a form
+ } else {
+
+ // Collect all those radios which are also outside of a form and match our name
+ radios = $( selector, doc ).filter( function() {
+ return !this.form;
+ });
+ }
}
-
- return this.element.closest( "form, :jqmData(role='page'), :jqmData(role='dialog')" )
- .find( "input[name='" + this.element[ 0 ].name + "'][type='" + this.inputtype + "']" );
+ return radios;
},
_updateAll: function() {
@@ -0,0 +1,50 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8" />
+ <title>jQuery Mobile Checkboxradio Input Set Test Suite</title>
+
+ <script src="../../../external/requirejs/require.js"></script>
+ <script src="../../../js/requirejs.config.js"></script>
+ <script src="../../../js/jquery.tag.inserter.js"></script>
+ <script src="../../../tests/jquery.testHelper.js"></script>
+ <script src="../../../external/qunit/qunit.js"></script>
+ <script>
+ $.testHelper.asyncLoad([
+ [
+ "widgets/forms/checkboxradio",
+ ],
+ [
+ "input_set_tests_core.js"
+ ]
+ ]);
+ </script>
+
+ <link rel="stylesheet" href="../../../external/qunit/qunit.css"/>
+ <link rel="stylesheet" href="../../jqm-tests.css"/>
+
+ <script src="../../swarminject.js"></script>
+</head>
+<body>
+
+ <div id="qunit"></div>
+
+ <div data-nstest-role="page">
+ <label>Radio<input id="radio:1" type="radio" name="group1"></label>
+ <form id="the-[form]">
+ <label>Radio<input id="radio:2" type="radio" name="group1"></label>
+ <label>Radio<input id="radio:7" type="radio" name="group1" form="the-'other'-form"></label>
+ </form>
+ <label>Radio<input id="radio:3" type="radio" name="group1" form="the-[form]"></label>
+ <form id="the-'other'-form">
+ <label>Radio<input id="radio:6" type="radio" name="group1" form="the-[form]"></label>
+ <label>Radio<input id="radio:4" type="radio" name="group1"></label>
+ </form>
+
+ <!-- radio5 (below) is not supposed to have a name -->
+ <label>Radio<input id="radio:5" type="radio"></label>
+ </div>
+
+ <label>Radio<input id="radio:8" type="radio" name="group1"></label>
+</body>
+</html>
@@ -0,0 +1,36 @@
+( function( $, undefined ) {
+
+test( "Radio groups are correctly identified", function() {
+ var detached = $( "<input type='radio' name='group1' id='detached'>" ),
+ groups = {
+ "#radio\\:1": "#radio\\:1,#radio\\:8",
+ "#radio\\:2": "#radio\\:2,#radio\\:3,#radio\\:6",
+ "#radio\\:3": "#radio\\:2,#radio\\:3,#radio\\:6",
+ "#radio\\:6": "#radio\\:2,#radio\\:3,#radio\\:6",
+ "#radio\\:4": "#radio\\:4,#radio\\:7",
+ "#radio\\:7": "#radio\\:4,#radio\\:7",
+ "#radio\\:5": "#radio\\:5",
+ "#radio\\:8": "#radio\\:1,#radio\\:8"
+ },
+ checkGroup = function( radio, group ) {
+ var prefix = radio.attr( "id" ) + ": ",
+ result = $.mobile.checkboxradio.prototype._getInputSet.call({
+ element: radio,
+ inputtype: "radio"
+ });
+
+ deepEqual( group.length, result.length, prefix + "length of group is correct" );
+ group.each( function() {
+ deepEqual( result.filter( this ).length, 1,
+ prefix + $( this ).attr( "id" ) + " is correctly present in the result" );
+ });
+ };
+
+ $.each( groups, function( index, value ) {
+ checkGroup( $( index ), $( value ) );
+ });
+
+ checkGroup( detached, detached );
+});
+
+})( jQuery );

0 comments on commit 70700a5

Please sign in to comment.