PageSourceSearch

https://flowpaper.com/assets/js/jquery.dropdown.js

js flowpaper.com collected 2026-09-24 08:25:46 UTC 12,374 bytes, 378 lines download raw bytes

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            $this.each(function() {
251              initElement($(this));
252            });
253          }
254        });
255      }
256
257      // Loop trough elements
258      $(this).each(function() {
259        initElement($(this));
260      });
261    },
262    select: function(target) {
263      var $target = $(this).find("[value=\"" + target + "\"]");
264      methods._select($(this), $target);
265    },
266    _select: function($dropdown, $target) {
267      if ($target.is(".dropdownjs-add")) return;
268
269      // Get dropdown's elements
270      var $select = $dropdown.data("select"),
271          $input  = $dropdown.find("input.fakeinput");
272      // Is it a multi select?
273      var multi = $select.attr("multiple");
274
275      // Cache the dropdown options
276      var selectOptions = $dropdown.find("li");
277
278      // Behavior for multiple select
279      if (multi) {
280        // Toggle option state
281        $target.toggleClass("selected");
282        // Toggle selection of the clicked option in native select
283        $target.each(function(){
284          var $selected = $select.find("[value=\"" + $(this).attr("value") + "\"]");
285          $selected.prop("selected", $(this).hasClass("selected"));
286        })
287        // Add or remove the value from the input
288        var text = [];
289        selectOptions.each(function() {
290          if ($(this).hasClass("selected")) {
291            text.push($(this).text());
292          }
293        });
294        $input.val(text.join(", "));
295      }
296
297      // Behavior for single select
298      if (!multi) {
299        // Unselect options except the one that will be selected
300        if ($target.is("li")) {
301            selectOptions.not($target).removeClass("selected");
302        }
303        // Select the selected option
304        $target.addClass("selected");
305        // Set the value to the native select
306        $select.val($target.attr("value"));
307        // Set the value to the input
308        $input.val($target.text().trim());
309      }
310
311      // This is used only if Material Design for Bootstrap is selected
312      if ($.material) {
313        if ($input.val().trim()) {
314          $select.removeClass("empty");
315        } else {
316          $select.addClass("empty");
317        }
318      }
319      
320       // Call the callback
321        if (this.options.onSelected) {
322            this.options.onSelected($target.attr("value"));
323        }
324
325    },
326    _addOption: function($ul, $this) {
327      // Create the option
328      var $option = $("<li></li>");
329
330      // Style the option
331      $option.addClass(this.options.optionStyle);
332
333      // If the option has some text then transfer it
334      if ($this.text()) {
335        $option.text($this.text());
336      }
337      // Otherwise set the empty label and set it as an empty option
338      else {
339        $option.html("&nbsp;");
340      }
341      // Set the value of the option
342      $option.attr("value", $this.val());
343
344      // Will user be able to remove this option?
345      if ($ul.data("select").attr("data-dynamic-opts")) {
346        $option.append("<span class=close></span>");
347        $option.find(".close").on("click", function() {
348          $option.remove();
349          $this.remove();
350        });
351      }
352
353      // Ss it selected?
354      if ($this.prop("selected")) {
355        $option.attr("selected", true);
356        $option.addClass("selected");
357      }
358
359      // Append option to our dropdown
360      if ($ul.find(".dropdownjs-add").length) {
361        $ul.find(".dropdownjs-add").before($option);
362      } else {
363        $ul.append($option);
364      }
365    }
366  };
367
368  $.fn.dropdown = function(params) {
369    if (methods[params]) {
370      return methods[params].apply(this, Array.prototype.slice.call(arguments,1));
371    } else if (typeof params === "object" | !params) {
372      return methods.init.apply(this, arguments);
373    } else {
374      $.error("Method " + params + " does not exists on jQuery.dropdown");
375    }
376  };
377
378}));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.