2 * "checkboxradio" plugin
5 //>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
6 //>>description: Consistent styling for checkboxes/radio buttons.
7 //>>label: Checkboxes & Radio Buttons
9 //>>css.structure: ../css/structure/jquery.mobile.forms.checkboxradio.css
10 //>>css.theme: ../css/themes/default/jquery.mobile.theme.css
12 define( [ "jquery", "../../jquery.mobile.core", "../../jquery.mobile.widget", "../../jquery.mobile.buttonMarkup" ], function( $ ) {
13 //>>excludeEnd("jqmBuildExclude");
14 (function( $, undefined ) {
16 $.widget( "mobile.checkboxradio", $.mobile.widget, {
19 initSelector: "input[type='checkbox'],input[type='radio']"
24 inheritAttr = function( input, dataAttr ) {
25 return input.jqmData( dataAttr ) || input.closest( "form, fieldset" ).jqmData( dataAttr );
27 // NOTE: Windows Phone could not find the label through a selector
28 // filter works though.
29 parentLabel = $( input ).closest( "label" ),
30 label = parentLabel.length ? parentLabel : $( input ).closest( "form, fieldset, :jqmData(role='page'), :jqmData(role='dialog')" ).find( "label" ).filter( "[for='" + input[0].id + "']" ).first(),
31 inputtype = input[0].type,
32 mini = inheritAttr( input, "mini" ),
33 checkedState = inputtype + "-on",
34 uncheckedState = inputtype + "-off",
35 icon = input.parents( ":jqmData(type='horizontal')" ).length ? undefined : uncheckedState,
36 iconpos = inheritAttr( input, "iconpos" ),
37 activeBtn = icon ? "" : " " + $.mobile.activeBtnClass,
38 checkedClass = "ui-" + checkedState + activeBtn,
39 uncheckedClass = "ui-" + uncheckedState,
40 checkedicon = "ui-icon-" + checkedState,
41 uncheckedicon = "ui-icon-" + uncheckedState;
43 if ( inputtype !== "checkbox" && inputtype !== "radio" ) {
47 // Expose for other methods
51 checkedClass: checkedClass,
52 uncheckedClass: uncheckedClass,
53 checkedicon: checkedicon,
54 uncheckedicon: uncheckedicon
57 // If there's no selected theme check the data attr
58 if ( !this.options.theme ) {
59 this.options.theme = $.mobile.getInheritedTheme( this.element, "c" );
63 theme: this.options.theme,
70 // Wrap the input + label in a div
71 var wrapper = document.createElement('div');
72 wrapper.className = 'ui-' + inputtype;
74 input.add( label ).wrapAll( wrapper );
77 vmouseover: function( event ) {
78 if ( $( this ).parent().is( ".ui-disabled" ) ) {
79 event.stopPropagation();
83 vclick: function( event ) {
84 if ( input.is( ":disabled" ) ) {
85 event.preventDefault();
91 input.prop( "checked", inputtype === "radio" && true || !input.prop( "checked" ) );
93 // trigger click handler's bound directly to the input as a substitute for
94 // how label clicks behave normally in the browsers
95 // TODO: it would be nice to let the browser's handle the clicks and pass them
96 // through to the associate input. we can swallow that click at the parent
97 // wrapper element level
98 input.triggerHandler( 'click' );
100 // Input set for common radio buttons will contain all the radio
101 // buttons, but will not for checkboxes. clearing the checked status
102 // of other radios ensures the active button state is applied properly
103 self._getInputSet().not( input ).prop( "checked", false );
112 vmousedown: function() {
117 var $this = $( this );
119 // Adds checked attribute to checked input when keyboard is used
120 if ( $this.is( ":checked" ) ) {
122 $this.prop( "checked", true);
123 self._getInputSet().not( $this ).prop( "checked", false );
126 $this.prop( "checked", false );
133 label.addClass( $.mobile.focusClass );
137 label.removeClass( $.mobile.focusClass );
144 _cacheVals: function() {
145 this._getInputSet().each(function() {
146 $( this ).jqmData( "cacheVal", this.checked );
150 //returns either a set of radios with the same name attribute, or a single checkbox
151 _getInputSet: function() {
152 if ( this.inputtype === "checkbox" ) {
156 return this.element.closest( "form, fieldset, :jqmData(role='page'), :jqmData(role='dialog')" )
157 .find( "input[name='" + this.element[0].name + "'][type='" + this.inputtype + "']" );
160 _updateAll: function() {
163 this._getInputSet().each(function() {
164 var $this = $( this );
166 if ( this.checked || self.inputtype === "checkbox" ) {
167 $this.trigger( "change" );
170 .checkboxradio( "refresh" );
173 refresh: function() {
174 var input = this.element[0],
176 icon = label.find( ".ui-icon" );
178 if ( input.checked ) {
179 label.addClass( this.checkedClass ).removeClass( this.uncheckedClass );
180 icon.addClass( this.checkedicon ).removeClass( this.uncheckedicon );
182 label.removeClass( this.checkedClass ).addClass( this.uncheckedClass );
183 icon.removeClass( this.checkedicon ).addClass( this.uncheckedicon );
186 if ( input.disabled ) {
193 disable: function() {
194 this.element.prop( "disabled", true ).parent().addClass( "ui-disabled" );
198 this.element.prop( "disabled", false ).parent().removeClass( "ui-disabled" );
202 //auto self-init widgets
203 $( document ).bind( "pagecreate create", function( e ) {
204 $.mobile.checkboxradio.prototype.enhanceWithin( e.target, true );
208 //>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
210 //>>excludeEnd("jqmBuildExclude");