gluon-web-remote

Web remote Administration for big size of gluon routers
git clone git://archive.git.mtrnord.blog/MTRNord/gluon-web-remote.git
Log | Files | Refs | README

jquery.dropdown.js (12234B)


      1 /* globals jQuery, window, document */
      2 
      3 (function (factory) {
      4     if (typeof define === 'function' && define.amd) {
      5         // AMD. Register as an anonymous module.
      6         define(['jquery'], factory);
      7     } else if (typeof exports === 'object') {
      8         // Node/CommonJS
      9         module.exports = factory(require('jquery'));
     10     } else {
     11         // Browser globals
     12         factory(jQuery);
     13     }
     14 }(function($) {
     15 
     16   var methods = {
     17     options : {
     18       "optionClass": "",
     19       "dropdownClass": "",
     20       "autoinit": false,
     21       "callback": false,
     22       "onSelected": false,
     23       "dynamicOptLabel": "Add a new option..."
     24     },
     25     init: function(options) {
     26 
     27       // Apply user options if user has defined some
     28       if (options) {
     29         options = $.extend(methods.options, options);
     30       } else {
     31         options = methods.options;
     32       }
     33 
     34       function initElement($select) {
     35         // Don't do anything if this is not a select or if this select was already initialized
     36         if ($select.data("dropdownjs") || !$select.is("select")) {
     37           return;
     38         }
     39 
     40         // Is it a multi select?
     41         var multi = $select.attr("multiple");
     42 
     43         // Does it allow to create new options dynamically?
     44         var dynamicOptions = $select.attr("data-dynamic-opts"),
     45             $dynamicInput = $();
     46 
     47         // Create the dropdown wrapper
     48         var $dropdown = $("<div></div>");
     49         $dropdown.addClass("dropdownjs").addClass(options.dropdownStyle);
     50         $dropdown.data("select", $select);
     51 
     52         // Create the fake input used as "select" element and cache it as $input
     53         var $input = $("<input type=text readonly class=fakeinput>");
     54         if ($.material) { $input.data("mdproc", true); }
     55         // Append it to the dropdown wrapper
     56         $dropdown.append($input);
     57 
     58         // Create the UL that will be used as dropdown and cache it AS $ul
     59         var $ul = $("<ul></ul>");
     60         $ul.data("select", $select);
     61 
     62         // Append it to the dropdown
     63         $dropdown.append($ul);
     64 
     65         // Transfer the placeholder attribute
     66         $input.attr("placeholder", $select.attr("placeholder"));
     67 
     68         // Loop trough options and transfer them to the dropdown menu
     69         $select.find("option").each(function() {
     70           // Cache $(this)
     71           var $this = $(this);
     72           methods._addOption($ul, $this);
     73 
     74         });
     75 
     76         // If this select allows dynamic options add the widget
     77         if (dynamicOptions) {
     78           $dynamicInput = $("<li class=dropdownjs-add></li>");
     79           $dynamicInput.append("<input>");
     80           $dynamicInput.find("input").attr("placeholder", options.dynamicOptLabel);
     81           $ul.append($dynamicInput);
     82         }
     83 
     84 
     85 
     86         // Cache the dropdown options
     87         var selectOptions = $dropdown.find("li");
     88 
     89         // If is a single select, selected the first one or the last with selected attribute
     90         if (!multi) {
     91             var $selected;
     92             if ($select.find(":selected").length) {
     93                 $selected = $select.find(":selected").last();
     94             }
     95             else {
     96                 $selected = $select.find("option, li").first();
     97                // $selected = $select.find("option").first();
     98             }
     99             methods._select($dropdown, $selected);
    100         } else {
    101             var selectors = [], val = $select.val()
    102             for (var i in val) {
    103               selectors.push('li[value=' + val[i] + ']')
    104             }
    105             if (selectors.length > 0) {
    106               methods._select($dropdown, $dropdown.find(selectors.join(',')));
    107             }
    108         }
    109 
    110         // Transfer the classes of the select to the input dropdown
    111         $input.addClass($select[0].className);
    112 
    113         // Hide the old and ugly select
    114         $select.hide().attr("data-dropdownjs", true);
    115 
    116         // Bring to life our awesome dropdownjs
    117         $select.after($dropdown);
    118 
    119         // Call the callback
    120         if (options.callback) {
    121           options.callback($dropdown);
    122         }
    123 
    124         //---------------------------------------//
    125         // DROPDOWN EVENTS                       //
    126         //---------------------------------------//
    127 
    128         // On click, set the clicked one as selected
    129         $ul.on("click", "li:not(.dropdownjs-add)", function(e) {
    130           methods._select($dropdown, $(this));
    131           // trigger change event, if declared on the original selector
    132           $select.change();
    133         });
    134         $ul.on("keydown", "li:not(.dropdownjs-add)", function(e) {
    135           if (e.which === 27) {
    136             $(".dropdownjs > ul > li").attr("tabindex", -1);
    137             return $input.removeClass("focus").blur();
    138           }
    139           if (e.which === 32 && !$(e.target).is("input")) {
    140             methods._select($dropdown, $(this));
    141             return false;
    142           }
    143         });
    144 
    145         $ul.on("focus", "li:not(.dropdownjs-add)", function() {
    146           if ($select.is(":disabled")) {
    147             return;
    148           }
    149           $input.addClass("focus");
    150         });
    151 
    152         // Add new options when the widget is used
    153         if (dynamicOptions && dynamicOptions.length) {
    154           $dynamicInput.on("keydown", function(e) {
    155             if(e.which !== 13) return;
    156             var $option = $("<option>"),
    157                 val = $dynamicInput.find("input").val();
    158             $dynamicInput.find("input").val("");
    159 
    160             $option.attr("value", val);
    161             $option.text(val);
    162             $select.append($option);
    163 
    164           });
    165         }
    166 
    167         // Listen for new added options and update dropdown if needed
    168         $select.on("DOMNodeInserted", function(e) {
    169           var $this = $(e.target);
    170           if (!$this.val().length) return;
    171 
    172           methods._addOption($ul, $this);
    173           $ul.find("li").not(".dropdownjs-add").attr("tabindex", 0);
    174 
    175         });
    176         
    177         // Update dropdown when using val, need to use .val("value").trigger("change");
    178         $select.on("change", function(e) {
    179           var $this = $(e.target);
    180           if (!$this.val().length) return;
    181 
    182           if (!multi) {
    183             var $selected;
    184             if ($select.find(":selected").length) {
    185               $selected = $select.find(":selected").last();
    186             }
    187             else {
    188               $selected = $select.find("option, li").first();
    189             }
    190             methods._select($dropdown, $selected);
    191           } else {
    192             methods._select($dropdown, $select.find(":selected"));
    193           }
    194         });
    195 
    196         // Used to make the dropdown menu more dropdown-ish
    197         $input.on("click focus", function(e) {
    198           e.stopPropagation();
    199           if ($select.is(":disabled")) {
    200             return;
    201           }
    202           $(".dropdownjs > ul > li").attr("tabindex", -1);
    203           $(".dropdownjs > input").not($(this)).removeClass("focus").blur();
    204 
    205           $(".dropdownjs > ul > li").not(".dropdownjs-add").attr("tabindex", 0);
    206 
    207           // Set height of the dropdown
    208           var coords = {
    209             top: $(this).offset().top - $(document).scrollTop(),
    210             left: $(this).offset().left - $(document).scrollLeft(),
    211             bottom: $(window).height() - ($(this).offset().top - $(document).scrollTop()),
    212             right: $(window).width() - ($(this).offset().left - $(document).scrollLeft())
    213           };
    214 
    215           var height = coords.bottom;
    216 
    217           // Decide if place the dropdown below or above the input
    218           if (height < 200 && coords.top > coords.bottom) {
    219             height = coords.top;
    220             $ul.attr("placement", "top-left");
    221           } else {
    222             $ul.attr("placement", "bottom-left");
    223           }
    224 
    225           $(this).next("ul").css("max-height", height - 20);
    226           $(this).addClass("focus");
    227         });
    228         // Close every dropdown on click outside
    229         $(document).on("click", function(e) {
    230 
    231           // Don't close the multi dropdown if user is clicking inside it
    232           if (multi && $(e.target).parents(".dropdownjs").length) return;
    233 
    234           // Don't close the dropdown if user is clicking inside the dynamic-opts widget
    235           if ($(e.target).parents(".dropdownjs-add").length || $(e.target).is(".dropdownjs-add")) return;
    236 
    237           // Close opened dropdowns
    238           $(".dropdownjs > ul > li").attr("tabindex", -1);
    239           $input.removeClass("focus");
    240         });
    241       }
    242 
    243       if (options.autoinit) {
    244         $(document).on("DOMNodeInserted", function(e) {
    245           var $this = $(e.target);
    246           if (!$this.is("select")) {
    247             $this = $this.find('select');
    248           }
    249           if ($this.is(options.autoinit)) {
    250             initElement($this);
    251           }
    252         });
    253       }
    254 
    255       // Loop trough elements
    256       $(this).each(function() {
    257         initElement($(this));
    258       });
    259     },
    260     select: function(target) {
    261       var $target = $(this).find("[value=\"" + target + "\"]");
    262       methods._select($(this), $target);
    263     },
    264     _select: function($dropdown, $target) {
    265       if ($target.is(".dropdownjs-add")) return;
    266 
    267       // Get dropdown's elements
    268       var $select = $dropdown.data("select"),
    269           $input  = $dropdown.find("input.fakeinput");
    270       // Is it a multi select?
    271       var multi = $select.attr("multiple");
    272 
    273       // Cache the dropdown options
    274       var selectOptions = $dropdown.find("li");
    275 
    276       // Behavior for multiple select
    277       if (multi) {
    278         // Toggle option state
    279         $target.toggleClass("selected");
    280         // Toggle selection of the clicked option in native select
    281         $target.each(function(){
    282           var $selected = $select.find("[value=\"" + $(this).attr("value") + "\"]");
    283           $selected.prop("selected", $(this).hasClass("selected"));
    284         })
    285         // Add or remove the value from the input
    286         var text = [];
    287         selectOptions.each(function() {
    288           if ($(this).hasClass("selected")) {
    289             text.push($(this).text());
    290           }
    291         });
    292         $input.val(text.join(", "));
    293       }
    294 
    295       // Behavior for single select
    296       if (!multi) {
    297         // Unselect options except the one that will be selected
    298         selectOptions.not($target).removeClass("selected");
    299         // Select the selected option
    300         $target.addClass("selected");
    301         // Set the value to the native select
    302         $select.val($target.attr("value"));
    303         // Set the value to the input
    304         $input.val($target.text().trim());
    305       }
    306 
    307       // This is used only if Material Design for Bootstrap is selected
    308       if ($.material) {
    309         if ($input.val().trim()) {
    310           $select.removeClass("empty");
    311         } else {
    312           $select.addClass("empty");
    313         }
    314       }
    315       
    316        // Call the callback
    317         if (this.options.onSelected) {
    318             this.options.onSelected($target.attr("value"));
    319         }
    320 
    321     },
    322     _addOption: function($ul, $this) {
    323       // Create the option
    324       var $option = $("<li></li>");
    325 
    326       // Style the option
    327       $option.addClass(this.options.optionStyle);
    328 
    329       // If the option has some text then transfer it
    330       if ($this.text()) {
    331         $option.text($this.text());
    332       }
    333       // Otherwise set the empty label and set it as an empty option
    334       else {
    335         $option.html("&nbsp;");
    336       }
    337       // Set the value of the option
    338       $option.attr("value", $this.val());
    339 
    340       // Will user be able to remove this option?
    341       if ($ul.data("select").attr("data-dynamic-opts")) {
    342         $option.append("<span class=close></span>");
    343         $option.find(".close").on("click", function() {
    344           $option.remove();
    345           $this.remove();
    346         });
    347       }
    348 
    349       // Ss it selected?
    350       if ($this.prop("selected")) {
    351         $option.attr("selected", true);
    352       }
    353 
    354       // Append option to our dropdown
    355       if ($ul.find(".dropdownjs-add").length) {
    356         $ul.find(".dropdownjs-add").before($option);
    357       } else {
    358         $ul.append($option);
    359       }
    360     }
    361   };
    362 
    363   $.fn.dropdown = function(params) {
    364     if (methods[params]) {
    365       return methods[params].apply(this, Array.prototype.slice.call(arguments,1));
    366     } else if (typeof params === "object" | !params) {
    367       return methods.init.apply(this, arguments);
    368     } else {
    369       $.error("Method " + params + " does not exists on jQuery.dropdown");
    370     }
    371   };
    372 
    373 }));