diff options
author | Alexander Schmitz <arschmitz@gmail.com> | 2014-08-28 15:16:51 -0400 |
---|---|---|
committer | Alexander Schmitz <arschmitz@gmail.com> | 2015-10-07 10:57:59 -0400 |
commit | 25d0c857188c19347c869f803530289762199f92 (patch) | |
tree | 768afcbc456f878fb35e96546f468f9ffaa46b80 /ui | |
parent | 02033262ee0fb1d9f33c361b3c2ddfa168604854 (diff) | |
download | jquery-ui-25d0c857188c19347c869f803530289762199f92.tar.gz jquery-ui-25d0c857188c19347c869f803530289762199f92.zip |
Checkboxradio: Initial commit of new widget
Diffstat (limited to 'ui')
-rw-r--r-- | ui/checkboxradio.js | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/ui/checkboxradio.js b/ui/checkboxradio.js new file mode 100644 index 000000000..84f69afaa --- /dev/null +++ b/ui/checkboxradio.js @@ -0,0 +1,289 @@ +/*! + * jQuery UI Checkboxradio @VERSION + * http://jqueryui.com + * + * Copyright 2014 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/checkboxradio/ + */ +( function( factory ) { + if ( typeof define === "function" && define.amd ) { + + // AMD. Register as an anonymous module. + define( [ + "jquery", + "./core", + "./widget" + ], factory ); + } else { + + // Browser globals + factory( jQuery ); + } +}( function( $ ) { + +// Remove and replace with reset handler extension +var formResetHandler = function() { + var form = $( this ); + + // Wait for the form reset to actually happen before refreshing + setTimeout( function() { + + // We dont filter for css only versions since css only is not supported + form.find( ".ui-checkboxradio" ).checkboxradio( "refresh" ); + } ); + }; + +$.widget( "ui.checkboxradio", { + version: "@VERSION", + options: { + disabled: null, + label: null, + icon: true, + classes: { + "ui-checkboxradio-label": "ui-corner-all", + "ui-checkboxradio-icon": "ui-corner-all" + } + }, + + _getCreateOptions: function() { + var disabled, labels, + that = this, + options = this._super() || {}; + + // We read the type here, because it makes more sense to throw a element type error first, + // rather then the error for lack of a label. Often if its the wrong type, it + // won't have a label (e.g. calling on a div, btn, etc) + this._readType(); + + labels = this.element.labels(); + + // Todo: For now we will use the last label we need to check about the best + // way to handle multiple labels with some accessability experts + this.label = $( labels[ labels.length - 1 ] ); + if ( !this.label.length ) { + $.error( "No label found for checkboxradio widget" ); + } + + this.originalLabel = ""; + + // We need to get the label text but this may also need to make sure it does not contain the + // input itself. + this.label.contents().not( this.element ).each( function() { + + // The label contents could be text html or a mix we concat each element to get a string + // representation of the label without the input as part of it. + that.originalLabel += this.nodeType === 3 ? $( this ).text() : this.outerHTML; + } ); + + // Set the label option if we found label text + if ( this.originalLabel ) { + options.label = this.originalLabel; + } + + disabled = this.element[ 0 ].disabled; + if ( disabled != null ) { + options.disabled = disabled; + } + return options; + }, + + _create: function() { + var formCount, + checked = this.element[ 0 ].checked, + form = this.element.form(); + this.formParent = !!form.length ? form : $( "body" ); + + formCount = this.formParent.data( "uiCheckboxradioCount" ) || 0; + + // We don't use _on and _off here because we want all the checkboxes in the same form to use + // single handler which handles all the checkboxradio widgets in the form + if ( formCount === 0 ) { + this.formParent.on( "reset." + this.widgetFullName, formResetHandler ); + } + + this.formParent.data( "uiCheckboxradioCount", formCount + 1 ); + + if ( this.options.disabled == null ) { + this.options.disabled = this.element[ 0 ].disabled || false; + } + + this._setOption( "disabled", this.options.disabled ); + this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" ); + this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" ); + + if ( this.type === "radio" ) { + this._addClass( this.label, "ui-checkboxradio-radio-label" ); + } + + if ( this.options.label && this.options.label !== this.originalLabel ) { + this._updateLabel(); + } else if ( this.originalLabel ) { + this.options.label = this.originalLabel; + } + + this._enhance(); + + if ( checked ) { + this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" ); + this._addClass( this.icon, null, "ui-state-hover" ); + } + + this._on( { + "change": "_toggleClasses", + "focus": function() { + this._addClass( this.label, null, "ui-state-focus ui-visual-focus" ); + }, + "blur": function() { + this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" ); + } + } ); + }, + + _readType: function() { + var nodeName = this.element[ 0 ].nodeName.toLowerCase(); + this.type = this.element[ 0 ].type; + if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) { + $.error( "Can't create checkboxradio on element.nodeName=" + nodeName + + " and element.type=" + this.type ); + } + }, + + // Support jQuery Mobile enhanced option + _enhance: function() { + this._updateIcon( this.element[ 0 ].checked ); + }, + + widget: function() { + return this.label; + }, + + _getRadioGroup: function() { + var name = this.element[ 0 ].name, + that = this, + radios = $( [] ); + + if ( name ) { + name = $.ui.escapeSelector( name ); + radios = this.formParent.find( "[name='" + $.ui.escapeSelector( name ) + "']" ).filter( function() { + var form = $( this ).form(); + return ( form.length ? form : $( "body" ) )[ 0 ] === that.formParent[ 0 ]; + } ); + } + return radios.not( this.element ); + }, + + _toggleClasses: function() { + var checked = this.element[ 0 ].checked; + this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked ); + + if ( this.options.icon && this.type === "checkbox" ) { + + // We add ui-state-highlight to change the icon color + this._toggleClass( this.icon, null, "ui-icon-check ui-state-highlight", checked ) + ._toggleClass( this.icon, null, "ui-icon-blank", !checked ); + } + if ( this.type === "radio" ) { + this._getRadioGroup() + .each( function() { + var instance = $( this ).checkboxradio( "instance" ); + + if ( instance ) { + instance._removeClass( instance.label, + "ui-checkboxradio-checked", "ui-state-active" ); + } + } ); + } + }, + + _destroy: function() { + var formCount = this.formParent.data( "uiCheckboxradioCount" ) - 1; + + this.formParent.data( "uiCheckboxradioCount", formCount ); + + if ( formCount === 0 ) { + this.formParent.off( "reset." + this.widgetFullName, formResetHandler ); + } + + if ( this.icon ) { + this.icon.remove(); + this.iconSpace.remove(); + } + }, + + _setOption: function( key, value ) { + + // We don't alow the value to be set to nothing + if ( key === "label" && !value ) { + return; + } + + this._super( key, value ); + + if ( key === "disabled" ) { + this._toggleClass( this.label, null, "ui-state-disabled", value ); + this.element[ 0 ].disabled = value; + + // Don't refresh if disabled + return; + } + this.refresh(); + }, + + _updateIcon: function( checked ) { + var toAdd = "ui-icon ui-icon-background "; + + if ( this.options.icon ) { + if ( !this.icon ) { + this.icon = $( "<span>" ); + this.iconSpace = $( "<span> </span>" ); + this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" ); + } + + if ( this.type === "checkbox" ) { + toAdd += checked ? "ui-icon-check" : "ui-icon-blank"; + this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" ); + } else { + toAdd += "ui-icon-blank"; + } + this._addClass( this.icon, "ui-checkboxradio-icon", toAdd ); + if ( !checked ) { + this._removeClass( this.icon, null, "ui-icon-check" ); + } + this.icon.prependTo( this.label ).after( this.iconSpace ); + } else if ( this.icon !== undefined ) { + this.icon.remove(); + this.iconSpace.remove(); + delete this.icon; + } + }, + + _updateLabel: function() { + + // Remove the contents of the label ( minus the icon, icon space, and input ) + this.label.contents().not( this.element.add( this.icon ).add( this.iconSpace ) ).remove(); + this.label.append( this.options.label ); + }, + + refresh: function() { + var checked = this.element[ 0 ].checked, + isDisabled = this.element[ 0 ].disabled; + + this._updateIcon( checked ); + this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked ); + if ( this.options.label !== null ) { + this._updateLabel(); + } + + if ( isDisabled !== this.options.disabled ) { + this._setOptions( { "disabled": isDisabled } ); + } + } + +} ); + +return $.ui.checkboxradio; + +} ) ); |