From aa6a5036dd387c1694a37075f0724e67cbf54915 Mon Sep 17 00:00:00 2001
From: FezVrasta <fez@tekhy.net>
Date: Mon, 1 Dec 2014 14:53:15 +0100
Subject: [PATCH 1/3] changed tabbing

---
 jquery.dropdown.js | 486 ++++++++++++++++++++++++++---------------------------
 1 file changed, 243 insertions(+), 243 deletions(-)

diff --git a/jquery.dropdown.js b/jquery.dropdown.js
index 08c5f70..16aff98 100644
--- a/jquery.dropdown.js
+++ b/jquery.dropdown.js
@@ -2,253 +2,253 @@
 
 (function($) {
 
-    var methods = {
-        options : {
-            "optionClass": "",
-            "dropdownClass": "",
-            "autoinit": false,
-            "callback": false
-        },
-        init: function(options) {
-
-            // Apply user options if user has defined some
-            if (options) {
-                options = $.extend(methods.options, options);
-            } else {
-                options = methods.options;
-            }
-
-            function initElement($select) {
-                // Don't do anything if this is not a select or if this select was already initialized
-                if ($select.data("dropdownjs") || !$select.is("select")) {
-                    return;
-                }
-
-                // Is it a multi select?
-                var multi = $select.attr("multiple");
-
-                // Create the dropdown wrapper
-                var $dropdown = $("<div></div>");
-                $dropdown.addClass("dropdownjs").addClass(options.dropdownStyle);
-                $dropdown.data("select", $select);
-
-                // Create the fake input used as "select" element and cache it as $input
-                var $input = $("<input type=text readonly>");
-                if ($.material) { $input.data("mdproc", true); }
-                // Append it to the dropdown wrapper
-                $dropdown.append($input);
-
-                // Create the UL that will be used as dropdown and cache it AS $ul
-                var $ul = $("<ul></ul>");
-
-                // Append it to the dropdown
-                $dropdown.append($ul);
-
-                // Transfer the placeholder attribute
-                $input.attr("placeholder", $select.attr("placeholder"));
-
-                // Loop trough options and transfer them to the dropdown menu
-                $select.find("option").each(function() {
-                    // Cache $(this)
-                    var $this = $(this);
-
-                    // Create the option
-                    var $option = $("<li></li>");
-
-                    // Style the option
-                    $option.addClass(options.optionStyle);
-
-                    // If the option has some text then transfer it
-                    if ($this.text()) {
-                        $option.text($this.text());
-                    }
-                    // Otherwise set the empty label and set it as an empty option
-                    else {
-                        $option.html("&nbsp;");
-                    }
-                    // Set the value of the option
-                    $option.attr("value", $this.val());
-
-                    // Ss it selected?
-                    if ($this.attr("selected")) {
-                        $option.attr("selected", true);
-                    }
-
-                    // Append option to our dropdown
-                    $ul.append($option);
-                });
-
-                // Cache the dropdown options
-                var selectOptions = $dropdown.find("li");
-
-                // If is a single select, selected the first one or the last with selected attribute
-                if (!multi) {
-                    var $selected;
-                    if ($ul.find("[selected]").length) {
-                        $selected = $ul.find("[selected]").last();
-                    }
-                    else {
-                        $selected = $ul.find("li").first();
-                    }
-                    methods._select($dropdown, $selected);
-                } else {
-                    methods._select($dropdown, $ul.find("[selected]"));
-                }
-
-                // Transfer the classes of the select to the input dropdown
-                $input.addClass($select[0].className);
-
-                // Hide the old and ugly select
-                $select.hide().data("dropdownjs", true);
-
-                // Bring to life our awesome dropdownjs
-                $select.after($dropdown);
-
-                // Call the callback
-                if (options.callback) {
-                    options.callback($dropdown);
-                }
-
-                //---------------------------------------//
-                // DROPDOWN EVENTS                       //
-                //---------------------------------------//
-
-                // On click, set the clicked one as selected
-                selectOptions.on("click", function(e) {
-                    methods._select($dropdown, $(this));
-                });
-                selectOptions.on("keydown", function(e) {
-                    if (e.which === 27) {
-                        $(".dropdownjs > ul > li").each(function() { $(this).attr("tabindex", -1); });
-                        return $input.removeClass("focus").blur();
-                    }
-                    if (e.which === 32) {
-                        methods._select($dropdown, $(this));
-                        return false;
-                    }
-                });
-
-                selectOptions.on("focus", function() {
-                    $input.addClass("focus");
-                });
-
-                // Used to make the dropdown menu more dropdown-ish
-                $input.on("click focus", function(e) {
-                    e.stopPropagation();
-                    $(".dropdownjs > ul > li").each(function() { $(this).attr("tabindex", -1); });
-                    $(".dropdownjs > input").not($(this)).removeClass("focus").blur();
-
-                    selectOptions.each(function() { $(this).attr("tabindex", 0); });
-
-                    // Set height of the dropdown
-                    var coords = {
-                        top: $(this).offset().top - $(document).scrollTop(),
-                        left: $(this).offset().left - $(document).scrollLeft(),
-                        bottom: $(window).height() - ($(this).offset().top - $(document).scrollTop()),
-                        right: $(window).width() - ($(this).offset().left - $(document).scrollLeft())
-                    };
-
-                    var height = coords.bottom;
-
-                    // Decide if place the dropdown below or above the input
-                    if (height < 200 && coords.top > coords.bottom) {
-                        height = coords.top;
-                        $ul.attr("placement", "top-left");
-                    } else {
-                        $ul.attr("placement", "bottom-left");
-                    }
-
-                    $(this).next("ul").css("max-height", height - 20);
-                    $(this).addClass("focus");
-                });
-                $(document).on("click", function() {
-                    $(".dropdownjs > ul > li").each(function() { $(this).attr("tabindex", -1); });
-                    $input.removeClass("focus");
-                });
-            }
-
-            if (options.autoinit) {
-                $(document).on("DOMNodeInserted", function(e) {
-                    var $this = $(e.target);
-                    if ($this.is("select") && $this.is(options.autoinit)) {
-                        initElement($this);
-                    }
-                });
-            }
-
-            // Loop trough elements
-            $(this).each(function() {
-                initElement($(this));
-            });
-        },
-        select: function(target) {
-            var $target = $(this).find("[value=\"" + target + "\"]");
-            methods._select($(this), $target);
-        },
-        _select: function($dropdown, $target) {
-            // Get dropdown's elements
-            var $select = $dropdown.data("select"),
-                $input  = $dropdown.find("input");
-
-            // Is it a multi select?
-            var multi = $select.attr("multiple");
-
-            // Cache the dropdown options
-            var selectOptions = $dropdown.find("li");
-
-            // Behavior for multiple select
-            if (multi) {
-                // Toggle option state
-                $target.toggleClass("selected");
-                // Toggle selection of the clicked option in native select
-                var $selected = $select.find("[value=\"" + $target.attr("value") + "\"]");
-                if ($selected.attr("selected")) {
-                    $selected.attr("selected", true);
-                } else {
-                    $selected.attr("selected", false);
-                }
-                // Add or remove the value from the input
-                var text = [];
-                selectOptions.each(function() {
-                    if ($(this).hasClass("selected")) {
-                        text.push($(this).text());
-                    }
-                });
-                $input.val(text.join(", "));
-            }
-
-            // Behavior for single select
-            if (!multi) {
-                // Unselect options except the one that will be selected
-                selectOptions.not($target).removeClass("selected");
-                // Select the selected option
-                $target.addClass("selected");
-                // Set the value to the native select
-                $select.val($target.attr("value"));
-                // Set the value to the input
-                $input.val($target.text());
-            }
-
-            // This is used only if Material Design for Bootstrap is selected
-            if ($.material) {
-                if ($input.val().trim()) {
-                    $select.removeClass("empty");
-                } else {
-                    $select.addClass("empty");
-                }
-            }
+  var methods = {
+    options : {
+      "optionClass": "",
+      "dropdownClass": "",
+      "autoinit": false,
+      "callback": false
+    },
+    init: function(options) {
+
+      // Apply user options if user has defined some
+      if (options) {
+        options = $.extend(methods.options, options);
+      } else {
+        options = methods.options;
+      }
+
+      function initElement($select) {
+        // Don't do anything if this is not a select or if this select was already initialized
+        if ($select.data("dropdownjs") || !$select.is("select")) {
+          return;
+        }
 
+        // Is it a multi select?
+        var multi = $select.attr("multiple");
+
+        // Create the dropdown wrapper
+        var $dropdown = $("<div></div>");
+        $dropdown.addClass("dropdownjs").addClass(options.dropdownStyle);
+        $dropdown.data("select", $select);
+
+        // Create the fake input used as "select" element and cache it as $input
+        var $input = $("<input type=text readonly>");
+        if ($.material) { $input.data("mdproc", true); }
+        // Append it to the dropdown wrapper
+        $dropdown.append($input);
+
+        // Create the UL that will be used as dropdown and cache it AS $ul
+        var $ul = $("<ul></ul>");
+
+        // Append it to the dropdown
+        $dropdown.append($ul);
+
+        // Transfer the placeholder attribute
+        $input.attr("placeholder", $select.attr("placeholder"));
+
+        // Loop trough options and transfer them to the dropdown menu
+        $select.find("option").each(function() {
+          // Cache $(this)
+          var $this = $(this);
+
+          // Create the option
+          var $option = $("<li></li>");
+
+          // Style the option
+          $option.addClass(options.optionStyle);
+
+          // If the option has some text then transfer it
+          if ($this.text()) {
+            $option.text($this.text());
+          }
+          // Otherwise set the empty label and set it as an empty option
+          else {
+            $option.html("&nbsp;");
+          }
+          // Set the value of the option
+          $option.attr("value", $this.val());
+
+          // Ss it selected?
+          if ($this.attr("selected")) {
+            $option.attr("selected", true);
+          }
+
+          // Append option to our dropdown
+          $ul.append($option);
+        });
+
+        // Cache the dropdown options
+        var selectOptions = $dropdown.find("li");
+
+        // If is a single select, selected the first one or the last with selected attribute
+        if (!multi) {
+          var $selected;
+          if ($ul.find("[selected]").length) {
+            $selected = $ul.find("[selected]").last();
+          }
+          else {
+            $selected = $ul.find("li").first();
+          }
+          methods._select($dropdown, $selected);
+        } else {
+          methods._select($dropdown, $ul.find("[selected]"));
         }
-    };
 
-    $.fn.dropdown = function(params) {
-        if (methods[params]) {
-            return methods[params].apply(this, Array.prototype.slice.call(arguments,1));
-        } else if (typeof params === "object" | !params) {
-            return methods.init.apply(this, arguments);
+        // Transfer the classes of the select to the input dropdown
+        $input.addClass($select[0].className);
+
+        // Hide the old and ugly select
+        $select.hide().data("dropdownjs", true);
+
+        // Bring to life our awesome dropdownjs
+        $select.after($dropdown);
+
+        // Call the callback
+        if (options.callback) {
+          options.callback($dropdown);
+        }
+
+        //---------------------------------------//
+        // DROPDOWN EVENTS                       //
+        //---------------------------------------//
+
+        // On click, set the clicked one as selected
+        selectOptions.on("click", function(e) {
+          methods._select($dropdown, $(this));
+        });
+        selectOptions.on("keydown", function(e) {
+          if (e.which === 27) {
+            $(".dropdownjs > ul > li").each(function() { $(this).attr("tabindex", -1); });
+            return $input.removeClass("focus").blur();
+          }
+          if (e.which === 32) {
+            methods._select($dropdown, $(this));
+            return false;
+          }
+        });
+
+        selectOptions.on("focus", function() {
+          $input.addClass("focus");
+        });
+
+        // Used to make the dropdown menu more dropdown-ish
+        $input.on("click focus", function(e) {
+          e.stopPropagation();
+          $(".dropdownjs > ul > li").each(function() { $(this).attr("tabindex", -1); });
+          $(".dropdownjs > input").not($(this)).removeClass("focus").blur();
+
+          selectOptions.each(function() { $(this).attr("tabindex", 0); });
+
+          // Set height of the dropdown
+          var coords = {
+            top: $(this).offset().top - $(document).scrollTop(),
+            left: $(this).offset().left - $(document).scrollLeft(),
+            bottom: $(window).height() - ($(this).offset().top - $(document).scrollTop()),
+            right: $(window).width() - ($(this).offset().left - $(document).scrollLeft())
+          };
+
+          var height = coords.bottom;
+
+          // Decide if place the dropdown below or above the input
+          if (height < 200 && coords.top > coords.bottom) {
+            height = coords.top;
+            $ul.attr("placement", "top-left");
+          } else {
+            $ul.attr("placement", "bottom-left");
+          }
+
+          $(this).next("ul").css("max-height", height - 20);
+          $(this).addClass("focus");
+        });
+        $(document).on("click", function() {
+          $(".dropdownjs > ul > li").each(function() { $(this).attr("tabindex", -1); });
+          $input.removeClass("focus");
+        });
+      }
+
+      if (options.autoinit) {
+        $(document).on("DOMNodeInserted", function(e) {
+          var $this = $(e.target);
+          if ($this.is("select") && $this.is(options.autoinit)) {
+            initElement($this);
+          }
+        });
+      }
+
+      // Loop trough elements
+      $(this).each(function() {
+        initElement($(this));
+      });
+    },
+    select: function(target) {
+      var $target = $(this).find("[value=\"" + target + "\"]");
+      methods._select($(this), $target);
+    },
+    _select: function($dropdown, $target) {
+      // Get dropdown's elements
+      var $select = $dropdown.data("select"),
+          $input  = $dropdown.find("input");
+
+      // Is it a multi select?
+      var multi = $select.attr("multiple");
+
+      // Cache the dropdown options
+      var selectOptions = $dropdown.find("li");
+
+      // Behavior for multiple select
+      if (multi) {
+        // Toggle option state
+        $target.toggleClass("selected");
+        // Toggle selection of the clicked option in native select
+        var $selected = $select.find("[value=\"" + $target.attr("value") + "\"]");
+        if ($selected.attr("selected")) {
+          $selected.attr("selected", true);
+        } else {
+          $selected.attr("selected", false);
+        }
+        // Add or remove the value from the input
+        var text = [];
+        selectOptions.each(function() {
+          if ($(this).hasClass("selected")) {
+            text.push($(this).text());
+          }
+        });
+        $input.val(text.join(", "));
+      }
+
+      // Behavior for single select
+      if (!multi) {
+        // Unselect options except the one that will be selected
+        selectOptions.not($target).removeClass("selected");
+        // Select the selected option
+        $target.addClass("selected");
+        // Set the value to the native select
+        $select.val($target.attr("value"));
+        // Set the value to the input
+        $input.val($target.text());
+      }
+
+      // This is used only if Material Design for Bootstrap is selected
+      if ($.material) {
+        if ($input.val().trim()) {
+          $select.removeClass("empty");
         } else {
-            $.error("Method " + params + " does not exists on jQuery.dropdown");
+          $select.addClass("empty");
         }
-    };
+      }
+
+    }
+  };
+
+  $.fn.dropdown = function(params) {
+    if (methods[params]) {
+      return methods[params].apply(this, Array.prototype.slice.call(arguments,1));
+    } else if (typeof params === "object" | !params) {
+      return methods.init.apply(this, arguments);
+    } else {
+      $.error("Method " + params + " does not exists on jQuery.dropdown");
+    }
+  };
 
 })(jQuery);

From b6519c6bb80aae432cb000e1bb5faf78977eb63d Mon Sep 17 00:00:00 2001
From: FezVrasta <fez@tekhy.net>
Date: Mon, 1 Dec 2014 15:02:54 +0100
Subject: [PATCH 2/3] added support for diabled selects

---
 index.html          | 22 +++++++++++++++++++++-
 jquery.dropdown.css |  6 ++++--
 jquery.dropdown.js  |  8 +++++++-
 3 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/index.html b/index.html
index 044f38d..e0f4e93 100644
--- a/index.html
+++ b/index.html
@@ -6,6 +6,12 @@
         <link href="https://rawgit.com/FezVrasta/bootstrap-material-design/master/dist/css/ripples.min.css" rel="stylesheet">
 
         <link href="jquery.dropdown.css" rel="stylesheet">
+
+      <style>
+      .form-control-wrapper {
+      margin-bottom: 50px;
+      margin-top: 50px;
+      }</style>
     </head>
     <body>
 
@@ -45,6 +51,20 @@
             <option>Is great</option>
         </select>
 
+
+        <select multiple class="select form-control floating-label" placeholder="This is a placeholder" disabled>
+            <option></option>
+            <option selected>Foobar</option>
+            <option selected>Is great</option>
+            <option>Foobar</option>
+            <option>Is great</option>
+            <option>Foobar</option>
+            <option>Is great</option>
+            <option selected>Foobar</option>
+            <option selected>Is great</option>
+            <option>Foobar</option>
+        </select>
+
         <br><br><br>
         <br><br><br>
         <br><br><br>
@@ -58,8 +78,8 @@
 
 
         <script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
-        <script src="https://rawgit.com/FezVrasta/bootstrap-material-design/master/dist/js/material.min.js"></script>
         <script src="https://rawgit.com/FezVrasta/bootstrap-material-design/master/dist/js/ripples.min.js"></script>
+        <script src="https://rawgit.com/FezVrasta/bootstrap-material-design/master/dist/js/material.min.js"></script>
 
         <script src="jquery.dropdown.js"></script>
         <script>
diff --git a/jquery.dropdown.css b/jquery.dropdown.css
index 825f4d9..21f0bd7 100644
--- a/jquery.dropdown.css
+++ b/jquery.dropdown.css
@@ -6,7 +6,6 @@
 }
 .dropdownjs > input {
     width: 100%;
-    cursor: pointer !important;
 }
 .dropdownjs > input.focus ~ ul {
     transform: scale(1);
@@ -36,9 +35,12 @@
 
 
 /* Theme */
-.dropdownjs > input {
+.dropdownjs > input[readonly] {
     cursor: pointer;
 }
+select[data-dropdownjs][disabled] + .dropdownjs > input[readonly] {
+  cursor: default;
+}
 .dropdownjs > ul {
     background: #FFF;
     box-shadow: 0 1px 6px rgba(0, 0, 0, 0.12), 0 1px 6px rgba(0, 0, 0, 0.12);
diff --git a/jquery.dropdown.js b/jquery.dropdown.js
index 16aff98..fa901fb 100644
--- a/jquery.dropdown.js
+++ b/jquery.dropdown.js
@@ -99,7 +99,7 @@
         $input.addClass($select[0].className);
 
         // Hide the old and ugly select
-        $select.hide().data("dropdownjs", true);
+        $select.hide().attr("data-dropdownjs", true);
 
         // Bring to life our awesome dropdownjs
         $select.after($dropdown);
@@ -129,12 +129,18 @@
         });
 
         selectOptions.on("focus", function() {
+          if ($select.is(":disabled")) {
+            return;
+          }
           $input.addClass("focus");
         });
 
         // Used to make the dropdown menu more dropdown-ish
         $input.on("click focus", function(e) {
           e.stopPropagation();
+          if ($select.is(":disabled")) {
+            return;
+          }
           $(".dropdownjs > ul > li").each(function() { $(this).attr("tabindex", -1); });
           $(".dropdownjs > input").not($(this)).removeClass("focus").blur();
 

From 173b88f162b25b32e1e52ce91362ad8b89bf156e Mon Sep 17 00:00:00 2001
From: tasonface <tasonface@users.noreply.github.com>
Date: Thu, 18 Dec 2014 14:05:27 +0100
Subject: [PATCH 3/3] Listen to original "change" event

Trigger change event, if declared on the original selector.

Tested in: Chrome 39.0.2171.71m, Firefox 33.1, IE11
---
 jquery.dropdown.js | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/jquery.dropdown.js b/jquery.dropdown.js
index fa901fb..a06a998 100644
--- a/jquery.dropdown.js
+++ b/jquery.dropdown.js
@@ -116,6 +116,8 @@
         // On click, set the clicked one as selected
         selectOptions.on("click", function(e) {
           methods._select($dropdown, $(this));
+          // trigger change event, if declared on the original selector
+          $select.change();
         });
         selectOptions.on("keydown", function(e) {
           if (e.which === 27) {
