diff options
author | Felix Nagel <info@felixnagel.com> | 2011-03-20 19:37:26 +0100 |
---|---|---|
committer | Felix Nagel <info@felixnagel.com> | 2011-03-20 23:40:17 +0100 |
commit | 58b3f2ce34b3e72b44b9b4cbb88fdc3922b17c76 (patch) | |
tree | e892950ca690f64449b18252dfc3d2465f79eae0 | |
parent | 7624538a97eef97be01ef72a65cc058aea70da43 (diff) | |
download | jquery-ui-58b3f2ce34b3e72b44b9b4cbb88fdc3922b17c76.tar.gz jquery-ui-58b3f2ce34b3e72b44b9b4cbb88fdc3922b17c76.zip |
improved: full disable / enable functionality for select, option, optgroup; see: https://github.com/fnagel/jquery-ui/issues#issue/18
-rw-r--r-- | demos/selectmenu/disable_enable.html | 85 | ||||
-rw-r--r-- | themes/base/jquery.ui.selectmenu.css | 1 | ||||
-rw-r--r-- | ui/jquery.ui.selectmenu.js | 113 |
3 files changed, 178 insertions, 21 deletions
diff --git a/demos/selectmenu/disable_enable.html b/demos/selectmenu/disable_enable.html index 0c0704bc5..ac49e9e3b 100644 --- a/demos/selectmenu/disable_enable.html +++ b/demos/selectmenu/disable_enable.html @@ -16,7 +16,7 @@ <style type="text/css"> /*demo styles*/ body {font-size: 62.5%; font-family:"Verdana",sans-serif; } - fieldset { border:0; margin: 50px 0 0 0;} + fieldset { border:0; margin: 30px 0 0 0;} label,select,.ui-select-menu { float: left; margin-right: 10px; } select { width: 200px; } @@ -32,7 +32,7 @@ </style> <script type="text/javascript"> $(function(){ - + // please note that option.event is always passed as a string, so do not test for true or 1 with if (options.value) // see this issue for more information http://github.com/fnagel/jquery-ui/issues#issue/12 var speedA_depends = $('select#speedA_depends').selectmenu(); @@ -54,9 +54,33 @@ speedB.selectmenu("disable"); }); + var speedB2 = $('select#speedB2').selectmenu(); + $("#optionSwitch").toggle( + function(){ + speedB2.selectmenu("disable", 2); + }, + function(){ + speedB2.selectmenu("enable", 2); + } + ); + var speedC = $('select#speedC').selectmenu(); - var speedD = $('select#speedD').selectmenu(); + var speedD = $('select#speedD').selectmenu(); + + var speedD2 = $('select#speedD2').selectmenu(); + $("#optgroupSwitch").toggle( + function(){ + speedD2.selectmenu("disable", 1, "optgroup"); + }, + function(){ + speedD2.selectmenu("enable", 1, "optgroup"); + } + ); + + var speedD3 = $('select#speedD3').selectmenu(); + + $('select').show(); }); </script> @@ -64,6 +88,8 @@ <body> <h2>Disable / Enable Testing</h2> <form action="#"> + <h3>API</h3> + <h4>selectmenu</h4> <label for="speedA">Disabled by select callback (does not change original select)</label> <fieldset> <select name="speedA" id="speedA"> @@ -76,11 +102,9 @@ <option value="Medium">Medium</option> <option value="Fast">Fast</option> </select> - </fieldset> - - + </fieldset> <fieldset> - <label for="speedB">Disble by links</label> + <label for="speedB">Disble whole select</label> <select name="speedB" id="speedB"> <option value="Slower" selected="selected">Slower</option> <option value="Slow">Slow</option> @@ -91,6 +115,37 @@ <a href="#nogo" id="on">on</a> | <a href="#nogo" id="off">off</a><br /> </fieldset> + <h4>option</h4> + <fieldset> + <label for="speedD2">Disabled option by HTML</label> + <select name="speedB2" id="speedB2"> + <option value="Slower" selected="selected">Slower</option> + <option value="Slow">Slow</option> + <option value="Medium">Medium</option> + <option value="Fast">Fast</option> + <option value="Faster">Faster</option> + </select> + Disable option 'Medium' <a href="#nogo" id="optionSwitch">on / off</a><br /> + </fieldset> + + <h4>optgroup</h4> + <fieldset> + <label for="speedD2">Disabled optgroup by HTML</label> + <select name="speedD2" id="speedD2"> + <optgroup label="scripts"> + <option value="jquery">jQuery.js</option> + <option value="jqueryui">ui.jQuery.js</option> + </optgroup> + <optgroup label="Label with space"> + <option value="somefile">Some unknown file</option> + <option value="someotherfile">Some other file</option> + </optgroup> + </select> + Disable option 'Label with space' <a href="#nogo" id="optgroupSwitch">on / off</a><br /> + </fieldset> + + + <h3>HTML</h3> <fieldset> <label for="speedC">Disabled by HTML (initial)</label> <select disabled="disabled" name="speedC" id="speedC"> @@ -103,7 +158,7 @@ </fieldset> <fieldset> - <label for="speedD">Disabled option by HTML (initial, does not work)</label> + <label for="speedD">Disabled option by HTML</label> <select name="speedD" id="speedD"> <option value="Slower" selected="selected">Slower</option> <option value="Slow">Slow</option> @@ -112,6 +167,20 @@ <option value="Faster">Faster</option> </select> </fieldset> + + <fieldset> + <label for="speedD3">Disabled optgroup by HTML</label> + <select name="speedD3" id="speedD3"> + <optgroup label="scripts"> + <option value="jquery">jQuery.js</option> + <option value="jqueryui">ui.jQuery.js</option> + </optgroup> + <optgroup disabled="disabled" label="Label with space"> + <option value="somefile">Some unknown file</option> + <option value="someotherfile">Some other file</option> + </optgroup> + </select> + </fieldset> </form> </body> </html>
\ No newline at end of file diff --git a/themes/base/jquery.ui.selectmenu.css b/themes/base/jquery.ui.selectmenu.css index 318941d6e..8a54f0a1b 100644 --- a/themes/base/jquery.ui.selectmenu.css +++ b/themes/base/jquery.ui.selectmenu.css @@ -8,6 +8,7 @@ .ui-selectmenu-menu-dropdown { } .ui-selectmenu-menu li { padding:0; margin:0; display: block; border-top: 1px dotted transparent; border-bottom: 1px dotted transparent; border-right-width: 0 !important; border-left-width: 0 !important; font-weight: normal !important; } .ui-selectmenu-menu li a,.ui-selectmenu-status { line-height: 1.4em; display: block; padding: .405em 1em; outline:none; text-decoration:none; } +.ui-selectmenu-menu li.ui-state-disabled a { cursor: default; } .ui-selectmenu-menu li.ui-selectmenu-hasIcon a, .ui-selectmenu-hasIcon .ui-selectmenu-status { padding-left: 20px; position: relative; margin-left: 5px; } .ui-selectmenu-menu li .ui-icon, .ui-selectmenu-status .ui-icon { position: absolute; top: 1em; margin-top: -8px; left: 0; } diff --git a/ui/jquery.ui.selectmenu.js b/ui/jquery.ui.selectmenu.js index a1ad54b4c..e06570c0a 100644 --- a/ui/jquery.ui.selectmenu.js +++ b/ui/jquery.ui.selectmenu.js @@ -245,6 +245,7 @@ $.widget("ui.selectmenu", { value: $(this).attr('value'), text: self._formatText($(this).text()), selected: $(this).attr('selected'), + disabled: $(this).attr('disabled'), classes: $(this).attr('class'), typeahead: $(this).attr('typeahead'), parentOptGroup: $(this).parent('optgroup'), @@ -260,20 +261,20 @@ $.widget("ui.selectmenu", { // write li's for (var i = 0; i < selectOptionData.length; i++) { - var thisLi = $('<li role="presentation"><a href="#" tabindex="-1" role="option" aria-selected="false"'+ (selectOptionData[i].typeahead ? ' typeahead="' + selectOptionData[i].typeahead + '"' : '' ) + '>'+ selectOptionData[i].text +'</a></li>') + var thisLi = $('<li role="presentation"' + (selectOptionData[i].disabled ? ' class="' + this.namespace + '-state-disabled' + '"' : '' ) + '><a href="#" tabindex="-1" role="option"' + (selectOptionData[i].disabled ? ' aria-disabled="true"' : '' ) + ' aria-selected="false"' + (selectOptionData[i].typeahead ? ' typeahead="' + selectOptionData[i].typeahead + '"' : '' ) + '>'+ selectOptionData[i].text +'</a></li>') .data('index', i) .addClass(selectOptionData[i].classes) .data('optionClasses', selectOptionData[i].classes || '') .bind("mouseup.selectmenu", function(event) { - if (self._safemouseup) { - var changed = $(this).data('index') != self._selectedIndex(); - self.index($(this).data('index')); - self.select(event); - if (changed) { - self.change(event); - } - self.close(event, true); + if (self._safemouseup && !self._disabled(event.currentTarget) && !self._disabled($( event.currentTarget ).parents( "ul>li." + self.widgetBaseClass + "-group " )) ) { + var changed = $(this).data('index') != self._selectedIndex(); + self.index($(this).data('index')); + self.select(event); + if (changed) { + self.change(event); } + self.close(event, true); + } return false; }) .bind("click.selectmenu", function() { @@ -297,7 +298,7 @@ $.widget("ui.selectmenu", { if (this.list.find( 'li.' + optGroupName ).length ) { this.list.find( 'li.' + optGroupName + ':last ul' ).append( thisLi ); } else { - $(' <li role="presentation" class="' + self.widgetBaseClass + '-group ' + optGroupName + '"><span class="' + self.widgetBaseClass + '-group-label">' + selectOptionData[i].parentOptGroup.attr('label') + '</span><ul></ul></li> ') + $(' <li role="presentation" class="' + self.widgetBaseClass + '-group ' + optGroupName + (selectOptionData[i].parentOptGroup.attr("disabled") ? ' ' + this.namespace + '-state-disabled" aria-disabled="true"' : '"' ) + '><span class="' + self.widgetBaseClass + '-group-label">' + selectOptionData[i].parentOptGroup.attr('label') + '</span><ul></ul></li> ') .appendTo( this.list ) .find( 'ul' ) .append( thisLi ); @@ -594,10 +595,24 @@ $.widget("ui.selectmenu", { if (newIndex > this._optionLis.size() - 1) { newIndex = this._optionLis.size() - 1; } + + //Occurs when a full loop has been made + if (newIndex === recIndex) { + return false; + } + var activeID = this.widgetBaseClass + '-item-' + Math.round(Math.random() * 1000); this._focusedOptionLi().find('a:eq(0)').attr('id', ''); - this._optionLis.eq(newIndex).find('a:eq(0)').attr('id', activeID).focus(); + + if (this._optionLis.eq(newIndex).hasClass( this.namespace + '-state-disabled' )) { + // if option at newIndex is disabled, call _moveFocus, incrementing amt by one + (amt > 0) ? amt++ : amt--; + this._moveFocus(amt, newIndex); + } else { + this._optionLis.eq(newIndex).find('a:eq(0)').attr('id',activeID).focus(); + } + this.list.attr('aria-activedescendant', activeID); }, @@ -609,6 +624,7 @@ $.widget("ui.selectmenu", { _setOption: function(key, value) { this.options[key] = value; + // set if (key == 'disabled') { this.close(); this.element @@ -620,10 +636,81 @@ $.widget("ui.selectmenu", { } }, + disable: function(index, type){ + //if options is not provided, call the parents disable function + if ( !index ) { + this._setOption( 'disabled', true ); + } else { + if ( type == "optgroup" ) { + this._disableOptgroup(index); + } else { + this._disableOption(index); + } + } + }, + + enable: function(index, type) { + //if options is not provided, call the parents enable function + if ( !index ) { + this._setOption('disabled', false); + } else { + if ( type == "optgroup" ) { + this._enableOptgroup(index); + } else { + this._enableOption(index); + } + } + }, + + _disabled: function(elem) { + return $(elem).hasClass( this.namespace + '-state-disabled' ); + }, + + + _disableOption: function(index) { + var optionElem = this._optionLis.eq(index); + if (optionElem) { + optionElem.addClass(this.namespace + '-state-disabled') + .find("a").attr("aria-disabled", true); + this.element.find("option").eq(index).attr("disabled", "disabled"); + } + }, + + _enableOption: function(index) { + var optionElem = this._optionLis.eq(index); + if (optionElem) { + optionElem.removeClass( this.namespace + '-state-disabled' ) + .find("a").attr("aria-disabled", false); + this.element.find("option").eq(index).removeAttr("disabled"); + } + }, + + _disableOptgroup: function(index) { + var optGroupElem = this.list.find( 'li.' + this.widgetBaseClass + '-group-' + index ); + if (optGroupElem) { + optGroupElem.addClass(this.namespace + '-state-disabled') + .attr("aria-disabled", true); + this.element.find("optgroup").eq(index).attr("disabled", "disabled"); + } + }, + + _enableOptgroup: function(index) { + var optGroupElem = this.list.find( 'li.' + this.widgetBaseClass + '-group-' + index ); + if (optGroupElem) { + optGroupElem.removeClass(this.namespace + '-state-disabled') + .attr("aria-disabled", false); + this.element.find("optgroup").eq(index).removeAttr("disabled"); + } + }, + index: function(newValue) { if (arguments.length) { - this.element[0].selectedIndex = newValue; - this._refreshValue(); + if (!this._disabled($(this._optionLis[newValue]))) { + this.element[0].selectedIndex = newValue; + this._refreshValue(); + } else { + return false; + } } else { return this._selectedIndex(); } |