Skip to content
This repository was archived by the owner on Oct 8, 2021. It is now read-only.

Commit 70700a5

Browse files
author
Gabriel Schulhof
committed
Checkboxradio: Correctly assemble radio group
Closes gh-6659 Closes gh-7082 Fixes gh-7088
1 parent e306bb0 commit 70700a5

File tree

3 files changed

+133
-7
lines changed

3 files changed

+133
-7
lines changed

js/widgets/forms/checkboxradio.js

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@
1010
//>>css.theme: ../css/themes/default/jquery.mobile.theme.css
1111

1212
define( [ "jquery",
13+
"../../navigation/path",
1314
"../../jquery.mobile.core",
1415
"../../jquery.mobile.widget",
1516
"./reset" ], function( jQuery ) {
1617
//>>excludeEnd("jqmBuildExclude");
1718
(function( $, undefined ) {
1819

20+
var escapeId = $.mobile.path.hashToSelector;
21+
1922
$.widget( "mobile.checkboxradio", $.extend( {
2023

2124
initSelector: "input:not( :jqmData(role='flipswitch' ) )[type='checkbox'],input[type='radio']:not( :jqmData(role='flipswitch' ))",
@@ -42,7 +45,7 @@ $.widget( "mobile.checkboxradio", $.extend( {
4245
input
4346
.closest( "form, fieldset, :jqmData(role='page'), :jqmData(role='dialog')" )
4447
.find( "label" )
45-
.filter( "[for='" + $.mobile.path.hashToSelector( input[0].id ) + "']" )
48+
.filter( "[for='" + escapeId( input[0].id ) + "']" )
4649
.first(),
4750
inputtype = input[0].type,
4851
checkedClass = "ui-" + inputtype + "-on",
@@ -182,14 +185,51 @@ $.widget( "mobile.checkboxradio", $.extend( {
182185
});
183186
},
184187

185-
//returns either a set of radios with the same name attribute, or a single checkbox
188+
// Returns those radio buttons that are supposed to be in the same group as
189+
// this radio button. In the case of a checkbox or a radio lacking a name
190+
// attribute, it returns this.element.
186191
_getInputSet: function() {
187-
if ( this.inputtype === "checkbox" ) {
188-
return this.element;
192+
var selector, formId,
193+
radio = this.element[ 0 ],
194+
name = radio.name,
195+
form = radio.form,
196+
doc = this.element.parents().last().get( 0 ),
197+
198+
// A radio is always a member of its own group
199+
radios = this.element;
200+
201+
// Only start running selectors if this is an attached radio button with a name
202+
if ( name && this.inputtype === "radio" && doc ) {
203+
selector = "input[type='radio'][name='" + escapeId( name ) + "']";
204+
205+
// If we're inside a form
206+
if ( form ) {
207+
formId = form.id;
208+
209+
// If the form has an ID, collect radios scattered throught the document which
210+
// nevertheless are part of the form by way of the value of their form attribute
211+
if ( formId ) {
212+
radios = $( selector + "[form='" + escapeId( formId ) + "']", doc );
213+
}
214+
215+
// Also add to those the radios in the form itself
216+
radios = $( form ).find( selector ).filter( function() {
217+
218+
// Some radios inside the form may belong to some other form by virtue of
219+
// having a form attribute defined on them, so we must filter them out here
220+
return ( this.form === form );
221+
}).add( radios );
222+
223+
// If we're outside a form
224+
} else {
225+
226+
// Collect all those radios which are also outside of a form and match our name
227+
radios = $( selector, doc ).filter( function() {
228+
return !this.form;
229+
});
230+
}
189231
}
190-
191-
return this.element.closest( "form, :jqmData(role='page'), :jqmData(role='dialog')" )
192-
.find( "input[name='" + this.element[ 0 ].name + "'][type='" + this.inputtype + "']" );
232+
return radios;
193233
},
194234

195235
_updateAll: function() {
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>jQuery Mobile Checkboxradio Input Set Test Suite</title>
6+
7+
<script src="../../../external/requirejs/require.js"></script>
8+
<script src="../../../js/requirejs.config.js"></script>
9+
<script src="../../../js/jquery.tag.inserter.js"></script>
10+
<script src="../../../tests/jquery.testHelper.js"></script>
11+
<script src="../../../external/qunit/qunit.js"></script>
12+
<script>
13+
$.testHelper.asyncLoad([
14+
[
15+
"widgets/forms/checkboxradio",
16+
],
17+
[
18+
"input_set_tests_core.js"
19+
]
20+
]);
21+
</script>
22+
23+
<link rel="stylesheet" href="../../../external/qunit/qunit.css"/>
24+
<link rel="stylesheet" href="../../jqm-tests.css"/>
25+
26+
<script src="../../swarminject.js"></script>
27+
</head>
28+
<body>
29+
30+
<div id="qunit"></div>
31+
32+
<div data-nstest-role="page">
33+
<label>Radio<input id="radio:1" type="radio" name="group1"></label>
34+
<form id="the-[form]">
35+
<label>Radio<input id="radio:2" type="radio" name="group1"></label>
36+
<label>Radio<input id="radio:7" type="radio" name="group1" form="the-'other'-form"></label>
37+
</form>
38+
<label>Radio<input id="radio:3" type="radio" name="group1" form="the-[form]"></label>
39+
<form id="the-'other'-form">
40+
<label>Radio<input id="radio:6" type="radio" name="group1" form="the-[form]"></label>
41+
<label>Radio<input id="radio:4" type="radio" name="group1"></label>
42+
</form>
43+
44+
<!-- radio5 (below) is not supposed to have a name -->
45+
<label>Radio<input id="radio:5" type="radio"></label>
46+
</div>
47+
48+
<label>Radio<input id="radio:8" type="radio" name="group1"></label>
49+
</body>
50+
</html>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
( function( $, undefined ) {
2+
3+
test( "Radio groups are correctly identified", function() {
4+
var detached = $( "<input type='radio' name='group1' id='detached'>" ),
5+
groups = {
6+
"#radio\\:1": "#radio\\:1,#radio\\:8",
7+
"#radio\\:2": "#radio\\:2,#radio\\:3,#radio\\:6",
8+
"#radio\\:3": "#radio\\:2,#radio\\:3,#radio\\:6",
9+
"#radio\\:6": "#radio\\:2,#radio\\:3,#radio\\:6",
10+
"#radio\\:4": "#radio\\:4,#radio\\:7",
11+
"#radio\\:7": "#radio\\:4,#radio\\:7",
12+
"#radio\\:5": "#radio\\:5",
13+
"#radio\\:8": "#radio\\:1,#radio\\:8"
14+
},
15+
checkGroup = function( radio, group ) {
16+
var prefix = radio.attr( "id" ) + ": ",
17+
result = $.mobile.checkboxradio.prototype._getInputSet.call({
18+
element: radio,
19+
inputtype: "radio"
20+
});
21+
22+
deepEqual( group.length, result.length, prefix + "length of group is correct" );
23+
group.each( function() {
24+
deepEqual( result.filter( this ).length, 1,
25+
prefix + $( this ).attr( "id" ) + " is correctly present in the result" );
26+
});
27+
};
28+
29+
$.each( groups, function( index, value ) {
30+
checkGroup( $( index ), $( value ) );
31+
});
32+
33+
checkGroup( detached, detached );
34+
});
35+
36+
})( jQuery );

0 commit comments

Comments
 (0)