File indexing completed on 2024-05-19 06:00:16

0001 !function($) {
0002     var Selectpicker = function(element, options, e) {
0003         if (e ) {
0004             e.stopPropagation();
0005             e.preventDefault();
0006         }
0007         this.$element = $(element);
0008         this.$newElement = null;
0009         this.button = null;
0010 
0011         //Merge defaults, options and data-attributes to make our options
0012         this.options = $.extend({}, $.fn.selectpicker.defaults, this.$element.data(), typeof options == 'object' && options);
0013 
0014         //If we have no title yet, check the attribute 'title' (this is missed by jq as its not a data-attribute
0015         if(this.options.title==null)
0016             this.options.title = this.$element.attr('title');
0017 
0018         //Expose public methods
0019         this.val = Selectpicker.prototype.val;
0020         this.render = Selectpicker.prototype.render;
0021         this.init();
0022     };
0023 
0024     Selectpicker.prototype = {
0025 
0026         constructor: Selectpicker,
0027 
0028         init: function (e) {
0029             var _this = this;
0030             this.$element.hide();
0031             this.multiple = this.$element.prop('multiple');
0032 
0033 
0034             var classList = this.$element.attr('class') !== undefined ? this.$element.attr('class').split(/\s+/) : '';
0035             var id = this.$element.attr('id');
0036             this.$element.after( this.createView() );
0037             this.$newElement = this.$element.next('.select');
0038             var select = this.$newElement;
0039             var menu = this.$newElement.find('.dropdown-menu');
0040             var menuArrow = this.$newElement.find('.dropdown-arrow');
0041             var menuA = menu.find('li > a');
0042             var liHeight = select.addClass('open').find('.dropdown-menu li > a').outerHeight();
0043             select.removeClass('open');
0044             var divHeight = menu.find('li .divider').outerHeight(true);
0045             var selectOffset_top = this.$newElement.offset().top;
0046             var size = 0;
0047             var menuHeight = 0;
0048             var selectHeight = this.$newElement.outerHeight();
0049             this.button = this.$newElement.find('> button');
0050             if (id !== undefined) {
0051                 this.button.attr('id', id);
0052                 $('label[for="' + id + '"]').click(function(){ select.find('button#'+id).focus(); })
0053             }
0054             for (var i = 0; i < classList.length; i++) {
0055                 if(classList[i] != 'selectpicker') {
0056                     this.$newElement.addClass(classList[i]);
0057                 }
0058             }
0059             //If we are multiple, then add the show-tick class by default
0060             if(this.multiple) {
0061                  this.$newElement.addClass('select-multiple');
0062             }
0063             this.button.addClass(this.options.style);
0064             menu.addClass(this.options.menuStyle);
0065             menuArrow.addClass(function() {
0066                 if (_this.options.menuStyle) {
0067                     return _this.options.menuStyle.replace('dropdown-', 'dropdown-arrow-');
0068                 }
0069             });
0070             this.checkDisabled();
0071             this.checkTabIndex();
0072             this.clickListener();
0073             var menuPadding = parseInt(menu.css('padding-top')) + parseInt(menu.css('padding-bottom')) + parseInt(menu.css('border-top-width')) + parseInt(menu.css('border-bottom-width'));
0074             if (this.options.size == 'auto') {
0075                 function getSize() {
0076                     var selectOffset_top_scroll = selectOffset_top - $(window).scrollTop();
0077                     var windowHeight = window.innerHeight;
0078                     var menuExtras = menuPadding + parseInt(menu.css('margin-top')) + parseInt(menu.css('margin-bottom')) + 2;
0079                     var selectOffset_bot = windowHeight - selectOffset_top_scroll - selectHeight - menuExtras;
0080                     menuHeight = selectOffset_bot;
0081                     if (select.hasClass('dropup')) {
0082                         menuHeight = selectOffset_top_scroll - menuExtras;
0083                     }
0084                     menu.css({'max-height' : menuHeight + 'px', 'overflow-y' : 'auto', 'min-height' : liHeight*3 + 'px'});
0085             }
0086                 getSize();
0087                 $(window).resize(getSize);
0088                 $(window).scroll(getSize);
0089                 this.$element.bind('DOMNodeInserted', getSize);
0090             } else if (this.options.size && this.options.size != 'auto' && menu.find('li').length > this.options.size) {
0091                 var optIndex = menu.find("li > *").filter(':not(.divider)').slice(0,this.options.size).last().parent().index();
0092                 var divLength = menu.find("li").slice(0,optIndex + 1).find('.divider').length;
0093                 menuHeight = liHeight*this.options.size + divLength*divHeight + menuPadding;
0094                 menu.css({'max-height' : menuHeight + 'px', 'overflow-y' : 'scroll'});
0095             }
0096 
0097             //Listen for updates to the DOM and re render...
0098             this.$element.bind('DOMNodeInserted', $.proxy(this.reloadLi, this));
0099 
0100             this.render();
0101         },
0102 
0103         createDropdown: function() {
0104             var drop =
0105                 "<div class='btn-group select'>" +
0106                     "<i class='dropdown-arrow'></i>" +
0107                     "<button class='btn dropdown-toggle clearfix' data-toggle='dropdown'>" +
0108                         "<span class='filter-option pull-left'></span>&nbsp;" +
0109                         "<span class='caret'></span>" +
0110                     "</button>" +
0111                     "<ul class='dropdown-menu' role='menu'>" +
0112                     "</ul>" +
0113                 "</div>";
0114 
0115             return $(drop);
0116         },
0117 
0118 
0119         createView: function() {
0120             var $drop = this.createDropdown();
0121             var $li = this.createLi();
0122             $drop.find('ul').append($li);
0123             return $drop;
0124         },
0125 
0126         reloadLi: function() {
0127             //Remove all children.
0128             this.destroyLi();
0129             //Re build
0130             $li = this.createLi();
0131             this.$newElement.find('ul').append( $li );
0132             //render view
0133             this.render();
0134         },
0135 
0136         destroyLi:function() {
0137             this.$newElement.find('li').remove();
0138         },
0139 
0140         createLi: function() {
0141 
0142             var _this = this;
0143             var _li = [];
0144             var _liA = [];
0145             var _liHtml = '';
0146 
0147             this.$element.find('option').each(function(){
0148                 _li.push($(this).text());
0149             });
0150 
0151             this.$element.find('option').each(function(index) {
0152                 //Get the class and text for the option
0153                 var optionClass = $(this).attr("class") !== undefined ? $(this).attr("class") : '';
0154                 var text =  $(this).text();
0155                 var subtext = $(this).data('subtext') !== undefined ? '<small class="muted">'+$(this).data('subtext')+'</small>' : '';
0156 
0157                 //Append any subtext to the main text.
0158                 text+=subtext;
0159 
0160                 if ($(this).parent().is('optgroup') && $(this).data('divider') != true) {
0161                     if ($(this).index() == 0) {
0162                         //Get the opt group label
0163                         var label = $(this).parent().attr('label');
0164                         var labelSubtext = $(this).parent().data('subtext') !== undefined ? '<small class="muted">'+$(this).parent().data('subtext')+'</small>' : '';
0165                         label += labelSubtext;
0166 
0167                         if ($(this)[0].index != 0) {
0168                             _liA.push(
0169                                 '<div class="divider"></div>'+
0170                                 '<dt>'+label+'</dt>'+ 
0171                                 _this.createA(text, "opt " + optionClass )
0172                                 );
0173                         } else {
0174                             _liA.push(
0175                                 '<dt>'+label+'</dt>'+ 
0176                                 _this.createA(text, "opt " + optionClass ));
0177                         }
0178                     } else {
0179                          _liA.push( _this.createA(text, "opt " + optionClass )  );
0180                     }
0181                 } else if ($(this).data('divider') == true) {
0182                     _liA.push('<div class="divider"></div>');
0183                 } else {
0184                     _liA.push( _this.createA(text, optionClass ) );
0185                 }
0186             });
0187 
0188             if (_li.length > 0) {
0189                 for (var i = 0; i < _li.length; i++) {
0190                     var $option = this.$element.find('option').eq(i);
0191                     _liHtml += "<li rel=" + i + ">" + _liA[i] + "</li>";
0192                 }
0193             }
0194 
0195             //If we dont have a selected item, and we dont have a title, select the first element so something is set in the button
0196             if(this.$element.find('option:selected').length==0 && !_this.options.title) {
0197                 this.$element.find('option').eq(0).prop('selected', true).attr('selected', 'selected');
0198             }
0199 
0200             return $(_liHtml);
0201         },
0202 
0203         createA:function(test, classes) {
0204          return '<a tabindex="-1" href="#" class="'+classes+'">' +
0205                  '<span class="pull-left">' + test + '</span>' +
0206                  '</a>';
0207 
0208         },
0209 
0210          render:function() {
0211             var _this = this;
0212 
0213             //Set width of select
0214              if (this.options.width == 'auto') {
0215                  var ulWidth = this.$newElement.find('.dropdown-menu').css('width');
0216                  this.$newElement.css('width',ulWidth);
0217              } else if (this.options.width && this.options.width != 'auto') {
0218                  this.$newElement.css('width',this.options.width);
0219              }
0220 
0221             //Update the LI to match the SELECT
0222             this.$element.find('option').each(function(index) {
0223                _this.setDisabled(index, $(this).is(':disabled') || $(this).parent().is(':disabled') );
0224                _this.setSelected(index, $(this).is(':selected') );
0225             });
0226 
0227 
0228 
0229             var selectedItems = this.$element.find('option:selected').map(function(index,value) {
0230                 if($(this).attr('title')!=undefined) {
0231                     return $(this).attr('title');
0232                 } else {
0233                     return $(this).text();
0234                 }
0235             }).toArray();
0236 
0237             //Convert all the values into a comma delimited string    
0238             var title = selectedItems.join(", ");
0239 
0240             //If this is multi select, and the selectText type is count, the show 1 of 2 selected etc..                    
0241             if(_this.multiple && _this.options.selectedTextFormat.indexOf('count') > -1) {
0242                 var max = _this.options.selectedTextFormat.split(">");
0243                 if( (max.length>1 && selectedItems.length > max[1]) || (max.length==1 && selectedItems.length>=2)) {
0244                     title = selectedItems.length +' of ' + this.$element.find('option').length + ' selected';
0245                 }
0246              }  
0247             
0248             //If we dont have a title, then use the default, or if nothing is set at all, use the not selected text
0249             if(!title) {
0250                 title = _this.options.title != undefined ? _this.options.title : _this.options.noneSelectedText;    
0251             }
0252             
0253             this.$element.next('.select').find('.filter-option').html( title );
0254             },
0255             
0256         
0257         
0258         setSelected:function(index, selected) {
0259             if(selected) {
0260                 this.$newElement.find('li').eq(index).addClass('selected');
0261             } else {
0262                 this.$newElement.find('li').eq(index).removeClass('selected');
0263             }
0264         },
0265         
0266         setDisabled:function(index, disabled) {
0267             if(disabled) {
0268                 this.$newElement.find('li').eq(index).addClass('disabled');
0269             } else {
0270                 this.$newElement.find('li').eq(index).removeClass('disabled');
0271             }
0272         },
0273        
0274         checkDisabled: function() {
0275             if (this.$element.is(':disabled')) {
0276                 this.button.addClass('disabled');
0277                 this.button.click(function(e) {
0278                     e.preventDefault();
0279                 });
0280             }
0281         },
0282                 
0283                 checkTabIndex: function() {
0284                         if (this.$element.is('[tabindex]')) {
0285                                 var tabindex = this.$element.attr("tabindex");
0286                                 this.button.attr('tabindex', tabindex);
0287                         }
0288                 },
0289                 
0290                 clickListener: function() {
0291             var _this = this;
0292             
0293             $('body').on('touchstart.dropdown', '.dropdown-menu', function (e) { e.stopPropagation(); });
0294             
0295            
0296             
0297             this.$newElement.on('click', 'li a', function(e){
0298                 var clickedIndex = $(this).parent().index(),
0299                     $this = $(this).parent(),
0300                     $select = $this.parents('.select');
0301                 
0302                 
0303                 //Dont close on multi choice menu    
0304                 if(_this.multiple) {
0305                     e.stopPropagation();
0306                 }
0307                 
0308                 e.preventDefault();
0309                 
0310                 //Dont run if we have been disabled
0311                 if ($select.prev('select').not(':disabled') && !$(this).parent().hasClass('disabled')){
0312                     //Deselect all others if not multi select box
0313                     if (!_this.multiple) {
0314                         $select.prev('select').find('option').removeAttr('selected');
0315                         $select.prev('select').find('option').eq(clickedIndex).prop('selected', true).attr('selected', 'selected');
0316                     } 
0317                     //Else toggle the one we have chosen if we are multi selet.
0318                     else {
0319                         var selected = $select.prev('select').find('option').eq(clickedIndex).prop('selected');
0320                         
0321                         if(selected) {
0322                             $select.prev('select').find('option').eq(clickedIndex).removeAttr('selected');
0323                         } else {
0324                             $select.prev('select').find('option').eq(clickedIndex).prop('selected', true).attr('selected', 'selected');
0325                         }
0326                     }
0327                     
0328                     
0329                     $select.find('.filter-option').html($this.text());
0330                     $select.find('button').focus();
0331 
0332                     // Trigger select 'change'
0333                     $select.prev('select').trigger('change');
0334                 }
0335 
0336             });
0337             
0338            this.$newElement.on('click', 'li.disabled a, li dt, li .divider', function(e) {
0339                 e.preventDefault();
0340                 e.stopPropagation();
0341                 $select = $(this).parent().parents('.select');
0342                 $select.find('button').focus();
0343             });
0344 
0345             this.$element.on('change', function(e) {
0346                 _this.render();
0347             });
0348         },
0349         
0350         val:function(value) {
0351             
0352             if(value!=undefined) {
0353                 this.$element.val( value );
0354                 
0355                 this.$element.trigger('change');
0356                 return this.$element;
0357             } else {
0358                 return this.$element.val();
0359             }
0360         }
0361 
0362     };
0363 
0364     $.fn.selectpicker = function(option, event) {
0365        //get the args of the outer function..
0366        var args = arguments;
0367        var value;
0368        var chain = this.each(function () {
0369             var $this = $(this),
0370                 data = $this.data('selectpicker'),
0371                 options = typeof option == 'object' && option;
0372             
0373             if (!data) {
0374                 $this.data('selectpicker', (data = new Selectpicker(this, options, event)));
0375             } else {
0376                 for(var i in option) {
0377                         data[i]=option[i];
0378                 }
0379             }
0380             
0381             if (typeof option == 'string') {
0382                 //Copy the value of option, as once we shift the arguments
0383                 //it also shifts the value of option.
0384                 property = option;
0385                 if(data[property] instanceof Function) {
0386                     [].shift.apply(args);
0387                     value = data[property].apply(data, args);
0388                 } else {
0389                     value = data[property];
0390                 }
0391             }
0392         });
0393         
0394         if(value!=undefined) {
0395             return value;
0396         } else {
0397             return chain;
0398         } 
0399     };
0400 
0401     $.fn.selectpicker.defaults = {
0402         style: null,
0403         size: 'auto',
0404         title: null,
0405         selectedTextFormat : 'values',
0406         noneSelectedText : 'Nothing selected',
0407         width: null,
0408         menuStyle: null,
0409         toggleSize: null
0410     }
0411 
0412 }(window.jQuery);