| /* |
| * "checkboxradio" plugin |
| */ |
| |
| //>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude); |
| //>>description: Consistent styling for checkboxes/radio buttons. |
| //>>label: Checkboxes & Radio Buttons |
| //>>group: Forms |
| //>>css.structure: ../css/structure/jquery.mobile.forms.checkboxradio.css |
| //>>css.theme: ../css/themes/default/jquery.mobile.theme.css |
| |
| define( [ "jquery", "../../jquery.mobile.core", "../../jquery.mobile.widget", "../../jquery.mobile.buttonMarkup" ], function( jQuery ) { |
| //>>excludeEnd("jqmBuildExclude"); |
| (function( $, undefined ) { |
| |
| $.widget( "mobile.checkboxradio", $.mobile.widget, { |
| options: { |
| theme: null, |
| initSelector: "input[type='checkbox'],input[type='radio']" |
| }, |
| _create: function() { |
| var self = this, |
| input = this.element, |
| inheritAttr = function( input, dataAttr ) { |
| return input.jqmData( dataAttr ) || input.closest( "form, fieldset" ).jqmData( dataAttr ); |
| }, |
| // NOTE: Windows Phone could not find the label through a selector |
| // filter works though. |
| parentLabel = $( input ).closest( "label" ), |
| label = parentLabel.length ? parentLabel : ( input[0].id ? $( input ).closest( "form, fieldset, :jqmData(role='page'), :jqmData(role='dialog')" ).find( "label" ).filter( "[for='" + input[0].id + "']" ) : [ ] ), |
| inputtype = input[0].type, |
| mini = inheritAttr( input, "mini" ), |
| checkedState = inputtype + "-on", |
| uncheckedState = inputtype + "-off", |
| icon = input.parents( ":jqmData(type='horizontal')" ).length ? undefined : uncheckedState, |
| iconpos = inheritAttr( input, "iconpos" ), |
| activeBtn = icon ? "" : " " + $.mobile.activeBtnClass, |
| checkedClass = "ui-" + checkedState + activeBtn, |
| uncheckedClass = "ui-" + uncheckedState, |
| checkedicon = "ui-icon-" + checkedState, |
| uncheckedicon = "ui-icon-" + uncheckedState, |
| ariaCheckedAttr = ""; |
| |
| if ( inputtype !== "checkbox" && inputtype !== "radio" ) { |
| return; |
| } |
| |
| ariaCheckedAttr = ( inputtype === "checkbox" ) ? "aria-checked" : "aria-selected"; |
| |
| // Support fake label |
| if ( label.length == 0 ) { |
| label = $( "<label for='" + input[ 0 ].id + |
| "'></label>" ); |
| } |
| |
| // Expose for other methods |
| $.extend( this, { |
| label: label, |
| inputtype: inputtype, |
| checkedClass: checkedClass, |
| uncheckedClass: uncheckedClass, |
| checkedicon: checkedicon, |
| uncheckedicon: uncheckedicon, |
| ariaCheckedAttr : ariaCheckedAttr |
| }); |
| |
| // If there's no selected theme check the data attr |
| if ( !this.options.theme ) { |
| this.options.theme = $.mobile.getInheritedTheme( this.element, "c" ); |
| } |
| |
| label.buttonMarkup({ |
| theme: this.options.theme, |
| icon: icon, |
| shadow: false, |
| mini: mini, |
| iconpos: iconpos |
| }); |
| |
| // Wrap the input + label in a div |
| var wrapper = document.createElement('div'); |
| wrapper.className = 'ui-' + inputtype; |
| wrapper.setAttribute( "role", inputtype ); |
| |
| if ( input.hasClass( "favorite" ) ) { |
| wrapper.className += ' favorite'; |
| } |
| |
| input.add( label ).wrapAll( wrapper ); |
| |
| label.bind({ |
| vmouseover: function( event ) { |
| if ( $( this ).parent().is( ".ui-disabled" ) ) { |
| event.stopPropagation(); |
| } |
| }, |
| |
| vclick: function( event ) { |
| if ( input.is( ":disabled" ) ) { |
| event.preventDefault(); |
| return; |
| } |
| |
| self._cacheVals(); |
| |
| input.prop( "checked", inputtype === "radio" && true || !input.prop( "checked" ) ); |
| |
| // trigger click handler's bound directly to the input as a substitute for |
| // how label clicks behave normally in the browsers |
| // TODO: it would be nice to let the browser's handle the clicks and pass them |
| // through to the associate input. we can swallow that click at the parent |
| // wrapper element level |
| input.triggerHandler( 'click' ); |
| |
| // Input set for common radio buttons will contain all the radio |
| // buttons, but will not for checkboxes. clearing the checked status |
| // of other radios ensures the active button state is applied properly |
| self._getInputSet().not( input ).prop( "checked", false ); |
| |
| self._updateAll(); |
| return false; |
| } |
| }); |
| |
| input |
| .bind({ |
| vmousedown: function() { |
| self._cacheVals(); |
| }, |
| |
| vclick: function() { |
| var $this = $( this ); |
| |
| // Adds checked attribute to checked input when keyboard is used |
| if ( $this.is( ":checked" ) ) { |
| |
| $this.prop( "checked", true); |
| self._getInputSet().not( $this ).prop( "checked", false ); |
| } else { |
| |
| $this.prop( "checked", false ); |
| } |
| |
| self._updateAll(); |
| }, |
| |
| focus: function() { |
| label.addClass( $.mobile.focusClass ); |
| }, |
| |
| blur: function() { |
| label.removeClass( $.mobile.focusClass ); |
| } |
| }); |
| |
| this.refresh(); |
| }, |
| |
| _cacheVals: function() { |
| this._getInputSet().each(function() { |
| $( this ).jqmData( "cacheVal", this.checked ); |
| }); |
| }, |
| |
| //returns either a set of radios with the same name attribute, or a single checkbox |
| _getInputSet: function() { |
| if ( this.inputtype === "checkbox" ) { |
| return this.element; |
| } |
| |
| return this.element.closest( "form, fieldset, :jqmData(role='page'), :jqmData(role='dialog')" ) |
| .find( "input[name='" + this.element[0].name + "'][type='" + this.inputtype + "']" ); |
| }, |
| |
| _updateAll: function() { |
| var self = this; |
| |
| this._getInputSet().each(function() { |
| var $this = $( this ); |
| |
| if ( this.checked || self.inputtype === "checkbox" ) { |
| $this.trigger( "change" ); |
| } |
| $this.focus(); |
| }) |
| .checkboxradio( "refresh" ); |
| }, |
| |
| refresh: function() { |
| var input = this.element[0], |
| label = this.label, |
| wrapper = input.parentNode, |
| icon = label.find( ".ui-icon" ); |
| |
| if ( input.checked ) { |
| label.addClass( this.checkedClass ).removeClass( this.uncheckedClass ); |
| icon.addClass( this.checkedicon ).removeClass( this.uncheckedicon ); |
| wrapper.setAttribute( this.ariaCheckedAttr, true ); |
| } else { |
| label.removeClass( this.checkedClass ).addClass( this.uncheckedClass ); |
| icon.removeClass( this.checkedicon ).addClass( this.uncheckedicon ); |
| wrapper.setAttribute( this.ariaCheckedAttr, false ); |
| } |
| |
| if ( input.disabled ) { |
| this.disable(); |
| } else { |
| this.enable(); |
| } |
| }, |
| |
| disable: function() { |
| this.element.prop( "disabled", true ).parent().addClass( "ui-disabled" ); |
| }, |
| |
| enable: function() { |
| this.element.prop( "disabled", false ).parent().removeClass( "ui-disabled" ); |
| } |
| }); |
| |
| //auto self-init widgets |
| $.mobile.$document.bind( "pagecreate create", function( e ) { |
| $.mobile.checkboxradio.prototype.enhanceWithin( e.target, true ); |
| }); |
| |
| })( jQuery ); |
| //>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude); |
| }); |
| //>>excludeEnd("jqmBuildExclude"); |