]> source.dussan.org Git - jquery-ui.git/commitdiff
added: possibility to refresh from original select element, please see https://github...
authorFelix Nagel <info@felixnagel.com>
Wed, 1 Dec 2010 22:42:28 +0000 (23:42 +0100)
committerFelix Nagel <info@felixnagel.com>
Wed, 15 Dec 2010 16:18:24 +0000 (17:18 +0100)
fixed: problem when manually selecting an option from original select element
fixed: demo wrapper class

demos/selectmenu/default.html
ui/jquery.ui.selectmenu.js

index 28ec1c3bdddeab041924be348520e9fcb4946bb4..4202a1bc99ac10a41821aa5ae04514f459f5448b 100644 (file)
                fieldset { border:0; }  
                label,select,.ui-select-menu { float: left; margin-right: 10px; }
                select { width: 200px; }                
+               .wrap span.ui-selectmenu-item-header,
+               .wrap ul.ui-selectmenu-menu li a { text-decoration: underline !important; }
        </style>
        <script type="text/javascript"> 
                $(function(){                   
                        $('select#speedA').selectmenu({style:'popup'});
-                       
+                                               
                        $('select#speedAa').selectmenu({
                                style:'popup', 
-                               maxHeight: 150
+                               maxHeight: 150,
+                               wrapperElement: "<div class='wrap' />"
                        });
                        
                        $('select#speedB').selectmenu({
                        }
                        return newText;
                }               
+               
+               // add themeswitcher
+               $(function(){ 
+                       var ts = $('<div class="ui-button ui-widget ui-state-default ui-corner-all" style="padding: 5px; position: absolute; top: 20px; right: 10px;">Click here to add Themeswitcher!</div>')
+                       .appendTo('body')
+                       .bind("click", function() {
+                               ts.text("Loading Themeswitcher...");
+                               $.getScript('http://ui.jquery.com/applications/themeroller/themeswitchertool/', function() {
+                                       ts.removeClass("ui-button ui-widget ui-state-default ui-corner-all").text("").unbind("click").themeswitcher(); 
+                               });
+                       }); 
+               });
        </script>
-       <!--
-       <script type="text/javascript" src="http://ui.jquery.com/applications/themeroller/themeswitchertool/"></script>
-       <script type="text/javascript"> $(function(){ $('<div style="position: absolute; top: 20px; right: 10px;" />').appendTo('body').themeswitcher(); }); </script>
-       -->
 </head>
 <body>
        <br />
                                <option value="Faster">Faster</option>
                        </select>
                </fieldset>
-               <h2>"default popup" Style with maxHeight set </h2>
+               <h2>"default popup" Style with maxHeight set and custom wrapper</h2>
                <fieldset>
                        <label for="speedAa">Select a Speed:</label>
                        <select name="speedAa" id="speedAa">
index d984e18655a17be9f0b76dc6e289adbe29a4e7ab..b1cfd790b45b569d342bb5f59b2357ee32c59754 100644 (file)
@@ -24,11 +24,12 @@ $.widget("ui.selectmenu", {
                },
                width: null, 
                menuWidth: null, 
-               handleWidth: 26, 
+               handleWidth: 26,
                maxHeight: null,
                icons: null, 
                format: null,
-               bgImage: function() {}
+               bgImage: function() {},
+               wrapperElement: ""
        },      
        
        _create: function() {
@@ -46,19 +47,21 @@ $.widget("ui.selectmenu", {
                //create menu button wrapper
                this.newelement = $('<a class="'+ this.widgetBaseClass +' ui-widget ui-state-default ui-corner-all" id="'+this.ids[0]+'" role="button" href="#" tabindex="0" aria-haspopup="true" aria-owns="'+this.ids[1]+'"></a>')
                        .insertAfter(this.element);
+               this.newelement.wrap(o.wrapperElement);
                
                //transfer tabindex
                var tabindex = this.element.attr('tabindex');
-               if(tabindex){ this.newelement.attr('tabindex', tabindex); }
+               if (tabindex){ this.newelement.attr('tabindex', tabindex); }
                
                //save reference to select in data for ease in calling methods
                this.newelement.data('selectelement', this.element);
                
                //menu icon
                this.selectmenuIcon = $('<span class="'+ this.widgetBaseClass +'-icon ui-icon"></span>')
-                       .prependTo(this.newelement)
-                       .addClass( (o.style == "popup")? 'ui-icon-triangle-2-n-s' : 'ui-icon-triangle-1-s' );   
-
+                       .prependTo(this.newelement);
+                       
+               //append status span to button
+               this.newelement.prepend('<span class="'+self.widgetBaseClass+'-status" />');
                        
                //make associated form label trigger focus
                $('label[for='+this.element.attr('id')+']')
@@ -67,13 +70,13 @@ $.widget("ui.selectmenu", {
                                self.newelement[0].focus();
                                return false;
                        });     
-
+                       
                //click toggle for menu visibility
                this.newelement
                        .bind('mousedown', function(event){
                                self._toggle(event, true);
-                               //make sure a click won't open/close instantly
-                               if(o.style == "popup"){
+                               // make sure a click won't open/close instantly
+                               if (o.style == "popup"){
                                        self._safemouseup = false;
                                        setTimeout(function(){self._safemouseup = true;}, 300);
                                }       
@@ -83,28 +86,37 @@ $.widget("ui.selectmenu", {
                                return false;
                        })
                        .keydown(function(event){
-                               var ret = true;
+                               var ret = false;
                                switch (event.keyCode) {
                                        case $.ui.keyCode.ENTER:
                                                ret = true;
                                                break;
                                        case $.ui.keyCode.SPACE:
-                                               ret = false;
                                                self._toggle(event);    
                                                break;
                                        case $.ui.keyCode.UP:
+                                               if (event.altKey) {
+                                                       self.open(event);
+                                               } else {
+                                                       self._moveSelection(-1);
+                                               }
+                                               break;
+                                       case $.ui.keyCode.DOWN:
+                                               if (event.altKey) {
+                                                       self.open(event);
+                                               } else {
+                                                       self._moveSelection(1);
+                                               }
+                                               break;
                                        case $.ui.keyCode.LEFT:
-                                               ret = false;
                                                self._moveSelection(-1);
                                                break;
-                                       case $.ui.keyCode.DOWN:
                                        case $.ui.keyCode.RIGHT:
-                                               ret = false;
                                                self._moveSelection(1);
-                                               break;  
+                                               break;
                                        case $.ui.keyCode.TAB:
                                                ret = true;
-                                               break;  
+                                               break;
                                        default:
                                                ret = true;
                                                self._typeAhead(event.keyCode, 'mouseup');
@@ -126,13 +138,85 @@ $.widget("ui.selectmenu", {
 
                //change event on original selectmenu
                this.element
-                       .click(function(){ this._refreshValue(); })
+                       .click(function(){ self._refreshValue(); })
             // newelement can be null under unclear circumstances in IE8 
                        .focus(function () { if (this.newelement) { this.newelement[0].focus(); } });
                
+               //original selectmenu width
+               var selectWidth = this.element.width();         
+               //set menu button width
+               this.newelement.width( (o.width) ? o.width : selectWidth);
+                               
+               //hide original selectmenu element
+               this.element.hide();            
+                               
                //create menu portion, append to body
-               var cornerClass = (o.style == "dropdown")? " ui-corner-bottom" : " ui-corner-all";
-               this.list = $('<ul class="' + self.widgetBaseClass + '-menu ui-widget ui-widget-content'+cornerClass+'" aria-hidden="true" role="listbox" aria-labelledby="'+this.ids[0]+'" id="'+this.ids[1]+'"></ul>').appendTo('body');                              
+               this.list = $('<ul class="' + self.widgetBaseClass + '-menu ui-widget ui-widget-content" aria-hidden="true" role="listbox" aria-labelledby="'+this.ids[0]+'" id="'+this.ids[1]+'"></ul>').appendTo('body');                             
+               this.list.wrap(o.wrapperElement);                               
+                               
+               //transfer menu click to menu button
+               this.list
+                       .keydown(function(event){
+                               var ret = false;
+                               switch (event.keyCode) {
+                                       case $.ui.keyCode.UP:
+                                               if (event.altKey) {
+                                                       self.close(event, true);
+                                               } else {
+                                                       self._moveFocus(-1);
+                                               }
+                                               break;
+                                       case $.ui.keyCode.DOWN:
+                                               if (event.altKey) {
+                                                       self.close(event, true);
+                                               } else {
+                                                       self._moveFocus(1);
+                                               }
+                                               break;  
+                                       case $.ui.keyCode.LEFT:
+                                               self._moveFocus(-1);
+                                               break;
+                                       case $.ui.keyCode.RIGHT:
+                                               self._moveFocus(1);
+                                               break;  
+                                       case $.ui.keyCode.HOME:
+                                               self._moveFocus(':first');
+                                               break;          
+                                       case $.ui.keyCode.PAGE_UP:
+                                               self._scrollPage('up');
+                                               break;  
+                                       case $.ui.keyCode.PAGE_DOWN:
+                                               self._scrollPage('down');
+                                               break;
+                                       case $.ui.keyCode.END:
+                                               self._moveFocus(':last');
+                                               break;          
+                                       case $.ui.keyCode.ENTER:
+                                       case $.ui.keyCode.SPACE:
+                                               self.close(event,true);
+                                               $(event.target).parents('li:eq(0)').trigger('mouseup');
+                                               break;          
+                                       case $.ui.keyCode.TAB:
+                                               ret = true;
+                                               self.close(event,true);
+                                               break;  
+                                       case $.ui.keyCode.ESCAPE:
+                                               self.close(event,true);
+                                               break;
+                                       default:
+                                               ret = true;
+                                               break;  
+                               }
+                               return ret;
+                       });                     
+               
+               // needed when window is resized
+               $(window).resize(function(){
+                       self._refreshPosition();
+               });                     
+       },
+       _init: function() {
+               var self = this, o = this.options;
                
                //serialize selectmenu element options  
                var selectOptionData = [];
@@ -141,7 +225,7 @@ $.widget("ui.selectmenu", {
                        .each(function(){
                                selectOptionData.push({
                                        value: $(this).attr('value'),
-                                       text: self._formatText(jQuery(this).text()),
+                                       text: self._formatText($(this).text()),
                                        selected: $(this).attr('selected'),
                                        classes: $(this).attr('class'),
                                        parentOptGroup: $(this).parent('optgroup').attr('label'),
@@ -152,6 +236,9 @@ $.widget("ui.selectmenu", {
                //active state class is only used in popup style
                var activeClass = (self.options.style == "popup") ? " ui-state-active" : "";
                
+               // empty list so we can refresh the selectmenu via selectmenu()
+               this.list.html("");
+               
                //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].text +'</a></li>')
@@ -159,11 +246,11 @@ $.widget("ui.selectmenu", {
                                .addClass(selectOptionData[i].classes)
                                .data('optionClasses', selectOptionData[i].classes|| '')
                                .mouseup(function(event){
-                                               if(self._safemouseup){
+                                               if (self._safemouseup){
                                                        var changed = $(this).data('index') != self._selectedIndex();
                                                        self.index($(this).data('index'));
                                                        self.select(event);
-                                                       if(changed){ self.change(event); }
+                                                       if (changed){ self.change(event); }
                                                        self.close(event,true);
                                                }
                                        return false;
@@ -182,30 +269,28 @@ $.widget("ui.selectmenu", {
                                });
                                
                        //optgroup or not...
-                       if(selectOptionData[i].parentOptGroup){
+                       if (selectOptionData[i].parentOptGroup){
                                // whitespace in the optgroupname must be replaced, otherwise the li of existing optgroups are never found
                                var optGroupName = self.widgetBaseClass + '-group-' + selectOptionData[i].parentOptGroup.replace(/[^a-zA-Z0-9]/g, "");
                                if(this.list.find('li.' + optGroupName).size()){
                                        this.list.find('li.' + optGroupName + ':last ul').append(thisLi);
-                               }
-                               else{
+                               } else {
                                        $('<li role="presentation" class="'+self.widgetBaseClass+'-group '+optGroupName+'"><span class="'+self.widgetBaseClass+'-group-label">'+selectOptionData[i].parentOptGroup+'</span><ul></ul></li>')
                                                .appendTo(this.list)
                                                .find('ul')
                                                .append(thisLi);
                                }
-                       }
-                       else{
+                       } else {
                                thisLi.appendTo(this.list);
                        }
                        
                        //this allows for using the scrollbar in an overflowed list
-                       this.list.bind('mousedown mouseup', function(){return false;});
+                       this.list.bind('mousedown mouseup', function(){ return false; });
                        
                        //append icon if option is specified
-                       if(o.icons){
-                               for(var j in o.icons){
-                                       if(thisLi.is(o.icons[j].find)){
+                       if (o.icons){
+                               for (var j in o.icons){
+                                       if (thisLi.is(o.icons[j].find)){
                                                thisLi
                                                        .data('optionClasses', selectOptionData[i].classes + ' ' + self.widgetBaseClass + '-hasIcon')
                                                        .addClass(self.widgetBaseClass + '-hasIcon');
@@ -220,13 +305,26 @@ $.widget("ui.selectmenu", {
                                }
                        }
                }       
-               
-               //add corners to top and bottom menu items
-               this.list.find('li:last').addClass("ui-corner-bottom");
-               if(o.style == 'popup'){ this.list.find('li:first').addClass("ui-corner-top"); }
-               
+                               
+               // we need to set and unset the CSS classes for dropdown and popup style
+               var isDropDown = (o.style == 'dropdown') ? true : false;
+               this.newelement
+                       .toggleClass(self.widgetBaseClass+"-dropdown", isDropDown)
+                       .toggleClass(self.widgetBaseClass+"-popup", !isDropDown);
+               this.list
+                       .toggleClass(self.widgetBaseClass+"-menu-dropdown ui-corner-bottom", isDropDown)
+                       .toggleClass(self.widgetBaseClass+"-menu-popup ui-corner-all", !isDropDown)
+               // add corners to top and bottom menu items
+               .find('li:first')
+                       .toggleClass("ui-corner-top", !isDropDown)
+               .find('li:last')
+                       .addClass("ui-corner-bottom");
+               this.selectmenuIcon
+                       .toggleClass('ui-icon-triangle-1-s', isDropDown)
+                       .toggleClass('ui-icon-triangle-2-n-s', !isDropDown);
+                                       
                //transfer classes to selectmenu and list
-               if(o.transferClasses){
+               if (o.transferClasses){
                        var transferClasses = this.element.attr('class') || ''; 
                        this.newelement.add(this.list).addClass(transferClasses);
                }
@@ -234,15 +332,15 @@ $.widget("ui.selectmenu", {
                //original selectmenu width
                var selectWidth = this.element.width();
                
-               //set menu button width
-               this.newelement.width( (o.width) ? o.width : selectWidth);
-               
                //set menu width to either menuWidth option value, width option value, or select width 
-               if(o.style == 'dropdown'){ this.list.width( (o.menuWidth) ? o.menuWidth : ((o.width) ? o.width : selectWidth)); }
-               else { this.list.width( (o.menuWidth) ? o.menuWidth : ((o.width) ? o.width - o.handleWidth : selectWidth - o.handleWidth)); }   
+               if (o.style == 'dropdown') { 
+                       this.list.width( (o.menuWidth) ? o.menuWidth : ((o.width) ? o.width : selectWidth)); 
+               } else { 
+                       this.list.width( (o.menuWidth) ? o.menuWidth : ((o.width) ? o.width - o.handleWidth : selectWidth - o.handleWidth)); 
+               }       
                
                // calculate default max height
-               if(o.maxHeight) {
+               if (o.maxHeight) {
                        //set max height from option 
                         if (o.maxHeight < this.list.height()){ this.list.height(o.maxHeight); }
                } else {
@@ -253,91 +351,17 @@ $.widget("ui.selectmenu", {
                }
                //save reference to actionable li's (not group label li's)
                this._optionLis = this.list.find('li:not(.'+ self.widgetBaseClass +'-group)');
-                               
-               //transfer menu click to menu button
-               this.list
-                       .keydown(function(event){
-                               var ret = true;
-                               switch (event.keyCode) {
-                                       case $.ui.keyCode.UP:
-                                       case $.ui.keyCode.LEFT:
-                                               ret = false;
-                                               self._moveFocus(-1);
-                                               break;
-                                       case $.ui.keyCode.DOWN:
-                                       case $.ui.keyCode.RIGHT:
-                                               ret = false;
-                                               self._moveFocus(1);
-                                               break;  
-                                       case $.ui.keyCode.HOME:
-                                               ret = false;
-                                               self._moveFocus(':first');
-                                               break;          
-                                       case $.ui.keyCode.PAGE_UP:
-                                               ret = false;
-                                               self._scrollPage('up');
-                                               break;  
-                                       case $.ui.keyCode.PAGE_DOWN:
-                                               ret = false;
-                                               self._scrollPage('down');
-                                               break;
-                                       case $.ui.keyCode.END:
-                                               ret = false;
-                                               self._moveFocus(':last');
-                                               break;          
-                                       case $.ui.keyCode.ENTER:
-                                       case $.ui.keyCode.SPACE:
-                                               ret = false;
-                                               self.close(event,true);
-                                               $(event.target).parents('li:eq(0)').trigger('mouseup');
-                                               break;          
-                                       case $.ui.keyCode.TAB:
-                                               ret = true;
-                                               self.close(event,true);
-                                               break;  
-                                       case $.ui.keyCode.ESCAPE:
-                                               ret = false;
-                                               self.close(event,true);
-                                               break;
-                               }
-                               return ret;
-                       });
-                       
-               //selectmenu style
-               if(o.style == 'dropdown'){
-                       this.newelement
-                               .addClass(self.widgetBaseClass+"-dropdown");
-                       this.list
-                               .addClass(self.widgetBaseClass+"-menu-dropdown");       
-               }
-               else {
-                       this.newelement
-                               .addClass(self.widgetBaseClass+"-popup");
-                       this.list
-                               .addClass(self.widgetBaseClass+"-menu-popup");  
-               }
-               
-               //append status span to button
-               this.newelement.prepend('<span class="'+self.widgetBaseClass+'-status">'+ selectOptionData[this._selectedIndex()].text +'</span>');
-               
-               //hide original selectmenu element
-               this.element.hide();
-               
+                                               
                //transfer disabled state
-               if(this.element.attr('disabled') == true){ this.disable(); }
+               if (this.element.attr('disabled') == true){ this.disable(); }
                
                //update value
-               this.index(this._selectedIndex());
+               this.index(this._selectedIndex());              
                
                // needed when selectmenu is placed at the very bottom / top of the page
         window.setTimeout(function() {
             self._refreshPosition();
         }, 200);
-               
-               // needed when window is resized
-               $(window).resize(function(){
-                       self._refreshPosition();
-               });             
        },
        destroy: function() {
                this.element.removeData(this.widgetName)
@@ -350,6 +374,7 @@ $.widget("ui.selectmenu", {
                        .attr('for',this.element.attr('id'))
                        .unbind('click');
                this.newelement.remove();
+               // FIXME option.wrapper needs
                this.list.remove();
                this.element.show();    
                
@@ -381,6 +406,7 @@ $.widget("ui.selectmenu", {
                });
                this._prevChar[0] = C;
        },
+       // returns some usefull information, called by callbacks only
        _uiHash: function(){
                var index = this.index();
                return {
@@ -397,10 +423,12 @@ $.widget("ui.selectmenu", {
                        this._closeOthers(event);
                        this.newelement
                                .addClass('ui-state-active');
-                       
-                       this.list
-                               .appendTo('body')
-                               .addClass(self.widgetBaseClass + '-open')
+                       if (self.options.wrapperElement) {
+                               this.list.parent().appendTo('body');
+                       } else {
+                               this.list.appendTo('body');
+                       }
+                       this.list.addClass(self.widgetBaseClass + '-open')
                                .attr('aria-hidden', false)
                                .find('li:not(.'+ self.widgetBaseClass +'-group):eq('+ this._selectedIndex() +') a')[0].focus();        
                        if(this.options.style == "dropdown"){ this.newelement.removeClass('ui-corner-all').addClass('ui-corner-top'); } 
@@ -500,6 +528,7 @@ $.widget("ui.selectmenu", {
        value: function(newValue) {
                if (arguments.length) {
                        // FIXME test for number is a kind of legacy support, could be removed at any time (Dez. 2010)
+                       // see this post for more info: https://github.com/fnagel/jquery-ui/issues#issue/33
                        if (typeof newValue == "number") {
                                        this.index(newValue);
                        } else if (typeof newValue == "string") {
@@ -522,7 +551,7 @@ $.widget("ui.selectmenu", {
                        .attr('id', '');
                //select new
                this._selectedOptionLi()
-                       .addClass(this.widgetBaseClass + "-item-selected"+activeClass)
+                       .addClass(this.widgetBaseClass + "-item-selected" + activeClass)
                        .find('a')
                        .attr('aria-selected', 'true')
                        .attr('id', activeID);
@@ -547,8 +576,7 @@ $.widget("ui.selectmenu", {
                var o = this.options;                           
                // if its a native pop-up we need to calculate the position of the selected li
                if (o.style == "popup" && !o.positionOptions.offset) {
-                       var selected = this.list.find('li:not(.ui-selectmenu-group):eq('+this._selectedIndex()+')');
-                       // var _offset = "0 -" + (selected.outerHeight() + selected.offset().top - this.list.offset().top);
+                       var selected = this._selectedOptionLi();
                        var _offset = "0 -" + (selected.outerHeight() + selected.offset().top - this.list.offset().top);
                }
                this.list