PageSourceSearch

https://lakonikos.gr/templates/default/js/select.js

js lakonikos.gr collected 2026-10-02 07:28:24 UTC 32,282 bytes, 650 lines download raw bytes

1/* ===========================================================
2 *
3 *  Name:          selectordie.js
4 *  Updated:       2014-10-11
5 *  Version:       0.1.8
6 *  Created by:    Per V @ Vst.mn
7 *  What?:         The Select or Die JS
8 *
9 *  Copyright (c) 2014 Per Vestman
10 *  Dual licensed under the MIT and GPL licenses.
11 *
12 *  To much comments in the code. Please, I know.
13 *
14 *  Oddny | Cogs 'n Kegs
15 *
16 * =========================================================== */
17
18; (function ($) {
19    "use strict";
20
21    $.fn.selectOrDie = function (method) {
22
23        var $defaults = {
24                customID:          null,      // String  - "" by default - Adds an ID to the SoD
25                customClass:       "",        // String  - "" by default - Adds a class to the SoD
26                placeholder:       null,      // String  - "" by default - Adds a placeholder that will be shown before a selection has been made
27                placeholderOption: false,     // Boolean - false by default - Same as above, but it uses the first option in the <select> as a placeholder (and hides it from the list)
28                prefix:            null,      // String  - "" by default - Adds a prefix that always will be shown before the selected value
29                cycle:             false,     // Boolean  - false by default - Should keyboard cycle through options or not?
30                stripEmpty:        false,     // Boolean  - false by default - Should empty <option>'s be stripped from the <select>
31                links:             false,     // Boolean  - false by default - Should the options be treated as links?
32                linksExternal:     false,     // Boolean  - false by default - Should the options be treated as links and open in a new window/tab?
33                size:              0,         // Integer  - 0 by default - The value set equals the amount of items before scroll is needed
34                tabIndex:          0,         // integer  - 0 by default
35                onChange:          $.noop     // Adds a callback function for when the SoD gets changed
36            },
37            $_settings = {},
38            $_sodKeysWhenClosed = false,
39            $_sodFilterTimeout, $_sodViewportTimeout;
40
41        var _private = {
42
43            initSoD: function (options) {
44                $_settings = $.extend({}, $defaults, options);
45
46                return this.each(function () {
47
48                    if ( !$(this).parent().hasClass("sod_select") ) {
49                        var $select                    = $(this),
50                            $settingsId                = $select.data("custom-id") ? $select.data("custom-id") : $_settings.customID,
51                            $settingsClass             = $select.data("custom-class") ? $select.data("custom-class") : $_settings.customClass,
52                            $settingsPrefix            = $select.data("prefix") ? $select.data("prefix") : $_settings.prefix,
53                            $settingsPlaceholder       = $select.data("placeholder") ? $select.data("placeholder") : $_settings.placeholder,
54                            $settingsPlaceholderOption = $select.data("placeholder-option") ? $select.data("placeholder-option") : $_settings.placeholderOption,
55                            $settingsCycle             = $select.data("cycle") ? $select.data("cycle") : $_settings.cycle,
56                            $settingsLinks             = $select.data("links") ? $select.data("links") : $_settings.links,
57                            $settingsLinksExternal     = $select.data("links-external") ? $select.data("links-external") : $_settings.linksExternal,
58                            $settingsSize              = parseInt($select.data("size")) ? $select.data("size") : $_settings.size,
59                            $settingsTabIndex          = parseInt($select.data("tabindex")) ? $select.data("tabindex") : ( $_settings.tabIndex ? $_settings.tabIndex : ( $select.attr("tabindex") ? $select.attr("tabindex") : $_settings.tabIndex ) ),
60                            $settingsStripEmpty        = $select.data("strip-empty") ? $select.data("strip-empty") : $_settings.stripEmpty,
61                            $selectTitle               = $select.prop("title") ? $select.prop("title") : null,
62                            $selectDisabled            = $select.is(":disabled") ? " disabled" : "",
63                            $sodPrefix                 = "",
64                            $sodHtml                   = "",
65                            $sodHeight                 = 0,
66                            $sod, $sodListWrapper, $sodList;
67
68                        // If there's a prefix defined
69                        if ( $settingsPrefix ) {
70                            $sodPrefix = "<span class=\"sod_prefix\">" + $settingsPrefix + "</span> ";
71                        }
72
73                        // If there's a placeholder defined
74                        if ( $settingsPlaceholder && !$settingsPrefix ) {
75                            $sodHtml += "<span class=\"sod_label sod_placeholder\">" + $settingsPlaceholder + "</span>";
76                        }
77                        else {
78                            $sodHtml += "<span class=\"sod_label\">
78" + $sodPrefix + "</span>";
79                        }
80
81                        // Inserts a new element that will act like our new <select>
82                        $sod = $("<span/>", {
83                            id:                        $settingsId,
84                            "class":                   "sod_select " + $settingsClass + $selectDisabled,
85                            title:                     $selectTitle,
86                            tabindex:                  $settingsTabIndex,
87                            html:                      $sodHtml,
88                            "data-cycle":              $settingsCycle,
89                            "data-links":              $settingsLinks,
90                            "data-links-external":     $settingsLinksExternal,
91                            "data-placeholder":        $settingsPlaceholder,
92                            "data-placeholder-option": $settingsPlaceholderOption,
93                            "data-prefix":             $settingsPrefix,
94                            "data-filter":             ""
95                        }).insertAfter( this );
96
97                        // If it's a touch device
98                        if ( _private.isTouch() ) {
99                            $sod.addClass("touch");
100                        }
101
102                        // Add a wrapper for the option list
103                        $sodListWrapper = $("<span/>", {
104                            "class": "sod_list_wrapper"
105                        }).appendTo($sod);
106
107                        // Inserts a <span> into our wrapper created above. It will host our <option>:s
108                        $sodList = $("<span/>", {
109                            "class": "sod_list"
110                        }).appendTo($sodListWrapper);
111
112                        // Inserts an option <span> for each <option>
113                        $("option, optgroup", $select).each(function (i) {
114                            var $this = $(this);
115
116                            if ( $settingsStripEmpty && !$.trim($this.text()) ) { // Strip empty <option>'s from the <select>
117                                $this.remove();
118                            } else if ( i === 0 && $settingsPlaceholderOption && !$sodPrefix )
119                                _private.populateSoD($this, $sodList, $sod, true);
120                            else {
121                                _private.populateSoD($this, $sodList, $sod, false);
122                            }
123                        });
124
125                        // If the setting size is set, then add a max-height to the SoD
126                        if ( $settingsSize ) {
127                            // Show the SoD options
128                            $sodListWrapper.show();
129
130                            // Calculate a max-height
131                            $(".sod_option:lt(" + $settingsSize + ")", $sodList).each(function () {
132                                $sodHeight += $(this).outerHeight();
133                            });
134
135                            // Hide the SoD list wrapper and set a "max-height" to the list itself
136                            $sodListWrapper.removeAttr("style");
137                            $sodList.css({"max-height": $sodHeight });
138                        }
139
140                        // Move the <select> into the SoD element
141                        $select.appendTo( $sod );
142
143                        // Bind events to the SoD
144                        $sod.on("focusin", _private.focusSod)
145                            .on("click", _private.triggerSod)
146                            .on("click", ".sod_option", _private.optionClick)
147                            .on("mousemove", ".sod_option", _private.optionHover)
148                            .on("keydown", _private.keyboardUse);
149
150                        // Bind change event to the <select>
151                        $select.on("change", _private.selectChange);
152
153                        // When a label for the native select is clicked we want to focus the SoD
154                        $(document).on("click", "label[for='" + $select.attr("id") + "']", function(e) {
155                            e.preventDefault();
156                            $sod.focus();
157                        });
158                    }
159                    else {
160                        console.log("Select or Die: It looks like the SoD already exists");
161                    }
162
163                });
164            }, // initSoD
165
166
167            populateSoD: function ($option, $sodList, $sod, $isPlaceholder) {
168                var $sodPlaceholder       = $sod.data("placeholder"),
169                    $sodPlaceholderOption = $sod.data("placeholder-option"),
170                    $sodPrefix            = $sod.data("prefix"),
171                    $sodLabel             = $sod.find(".sod_label"),
172                    $optionParent         = $option.parent(),
173                    $optionText           = $option.text(),
174                    $optionValue          = $option.val(),
175                    $optionCustomId       = $option.data("custom-id") ? $option.data("custom-id") : null,
176                    $optionCustomClass    = $option.data("custom-class") ? $option.data("custom-class") : "",
177                    $optionIsDisabled     = $option.is(":disabled") ? " disabled " : "",
178                    $optionIsSelected     = $option.is(":selected") ? " selected active " : "",
179                    $optionLink           = $option.data("link") ? " link " : "",
180                    $optionLinkExternal   = $option.data("link-external") ? " linkexternal" : "",
181                    $optgroupLabel        = $option.prop("label");
182
183                // Create <li> for each <option>
184                if ( $option.is("option") ) { // If <option>
185                    $("<span/>", {
186                        "class":      "sod_option " + $optionCustomClass + $optionIsDisabled + $optionIsSelected + $optionLink + $optionLinkExternal,
187                        id:           $optionCustomId,
188                        title:        $optionText,
189                        html:         $optionText,
190                        "data-value": $optionValue
191                    }).appendTo( $sodList );
192
193                    // Set the SoD data-label (used in the blur event)
194                    if ( $isPlaceholder && !$sodPrefix ) { // Various things if the first option should be used as a placeholder
195                        $sod.data("label", $optionText);
196                        $sod.data("placeholder", $optionText);
197                        $option.prop("disabled", true);
198                        $sodList.find(".sod_option:last").addClass("is-placeholder disabled");
199
200                        if ( $optionIsSelected ) {
201                            $sodLabel.addClass("sod_placeholder");
202                        }
203                    }
204                    else if ( $optionIsSelected && $sodPlaceholder && !$sodPlaceholderOption && !$sodPrefix ) { // If the option is selected and the placeholder option is used
205                        $sod.data("label", $sodPlaceholder);
206                    }
207                    else if ( $optionIsSelected ) { // If the option is selected
208                        $sod.data("label", $optionText);
209                    }
210
211                    // If selected and no placeholder is set, update label,
212                    // added in v.0.1.8: if the placeholder-option is set we'll update the label
213                    if ( $optionIsSelected && !$sodPlaceholder || $optionIsSelected && $sodPlaceholderOption || $optionIsSelected && $sodPrefix ) {
214                        $sodLabel.append($optionText);
215                    }
216
217                    // If child of an <optgroup>
218                    if ( $optionParent.is("optgroup") ) {
219                        $sodList.find(".sod_option:last").addClass("groupchild");
220
221                        // If <optgroup> disabled
222                        if ( $optionParent.is(":disabled") ) {
223                            $sodList.find(".sod_option:last").addClass("disabled");
224                        }
225                    }
226                }
227                else { // If <<optgroup>
228                    $("<span/>", {
229                        "class":      "sod_option optgroup " + $optionIsDisabled,
230                        title:        $optgroupLabel,
231                        html:         $optgroupLabel,
232                        "data-label": $optgroupLabel
233                    }).appendTo( $sodList );
234                }
235            }, // populateSoD
236
237
238            focusSod: function () {
239                var $sod = $(this);
240
241                // If not disabled we'll add focus (and blur other active SoD's)
242                if ( !$sod.hasClass("disabled") ) {
243                    _private.blurSod($(".sod_select.focus").not($sod));
244                    $sod.addClass("focus");
245
246                    // Blur the SoD when clicking outside it
247                    $("html").on("click.sodBlur", function() {
248                        _private.blurSod($sod);
249                    });
250                }
251                else {
252                    _private.blurSod($sod);
253                }
254            }, // focusSod
255
256
257            triggerSod: function (e) {
258                e.stopPropagation();
259
260                var $sod            = $(this),
261                    $sodList        = $sod.find(".sod_list"),
262                    $sodPlaceholder = $sod.data("placeholder"),
263                    $optionActive   = $sod.find(".active"),
264                    $optionSelected = $sod.find(".selected");
265
266                // Trigger the SoD if it's not disabled, already open or a touch device
267                if ( !$sod.hasClass("disabled") && !$sod.hasClass("open") && !$sod.hasClass("touch") ) {
268                    // Add the .open class to display list
269                    $sod.addClass("open");
270
271                    // If a placeholder is set, then show it
272                    if ( $sodPlaceholder && !$sod.data("prefix") ) {
273                        $sod.find(".sod_label").addClass("sod_placeholder").html($sodPlaceholder);
274                    }
275
276                    // Scroll list to selected item
277                    _private.listScroll($sodList, $optionSelected);
278
279                    // Check if the option list fits in the viewport
280                    _private.checkViewport($sod, $sodList);
281                }
282                else {
283                    // Clears viewport check timeout
284                    clearTimeout($_sodViewportTimeout);
285                    $sod.removeClass("open");
286
287                    // If a placeholder is set, make sure the placeholder text is removed if
288                    // the user toggles the select using his mouse
289                    if ( $sodPlaceholder ) {
290                        $sod.find(".sod_label").get(0).lastChild.nodeValue = $optionActive.text();
291                    }
292                }
293            }, // triggerSod
294
295
296            keyboardUse: function (e) {
297                var $sod            = $(this),
298                    $sodList        = $sod.find(".sod_list"),
299                    $sodOptions     = $sod.find(".sod_option"),
300                    $sodLabel       = $sod.find(".sod_label"),
301                    $sodCycle       = $sod.data("cycle"),
302                    $optionActive   = $sodOptions.filter(".active"),
303                    $sodFilterHit, $optionNext, $optionCycle;
304
305                // Highlight prev/next element if up/down key pressed
306                if ( e.which > 36 && e.which < 41 ) {
307
308                    // Set $optionNext and $optionCycle
309                    if ( e.which === 37 || e.which === 38 ) { // Left/Up key
310                        $optionNext  = $optionActive.prevAll(":not('.disabled, .optgroup')").first();
311                        $optionCycle = $sodOptions.not(".disabled, .optgroup").last();
312                    }
313                    else if ( e.which === 39 || e.which === 40 ) { // Right/Down key
314                        $optionNext  = $optionActive.nextAll(":not('.disabled, .optgroup')").first();
315                        $optionCycle = $sodOptions.not(".disabled, .optgroup").first();
316                    }
317
318                    // If there's no option before/after and cycle is enabled
319                    if ( !$optionNext.hasClass("sod_option") && $sodCycle ) {
320                        $optionNext = $optionCycle;
321                    }
322
323                    // Add .active to the next option, update the label and scroll the list
324                    if ( $optionNext.hasClass("sod_option") || $sodCycle ) {
325                        $optionActive.removeClass("active");
326                        $optionNext.addClass("active");
327                        $sodLabel.get(0).lastChild.nodeValue = $optionNext.text();
328                        _private.listScroll($sodList, $optionNext);
329
330                        // If the user used his keys when the SoD was closed we'll
331                        // update the $_sodKeysWhenClosed flag that we use in blurSod()
332                        if ( !$sod.hasClass("open") ) {
333                            $_sodKeysWhenClosed = true;
334                            // $sod.data("closed-keys", true);
335                        }
336
337                    }
338
339                    // Disables the up/down keys from scrolling the page
340                    return false;
341                }
342                else if ( e.which === 13 || (e.which === 32 && $sod.hasClass("open") && ($sod.data("filter")[0] === ' ' || $sod.data("filter") === "") ) ) { // Enter key or space, simulate click() function
343                    e.preventDefault();
344                    $optionActive.click();
345                }
346                else if ( e.which === 32 && !$sod.hasClass("open") && ($sod.data("filter")[0] === ' ' || $sod.data("filter") === "") ) { // Space bar, Opens the SoD if already closed
347                    e.preventDefault();
348                    $_sodKeysWhenClosed = false;
349                    $sod.click();
350                }
351                else if ( e.which === 27 ) { // Esc key, blur the SoD
352                    _private.blurSod($sod);
353                }
354
355                // "Filter" options list using keybaord based input
356                if ( e.which !== 0) {
357                    // Clears data-filter timeout
358                    clearTimeout($_sodFilterTimeout);
359
360                    // Append the data-filter with typed character
361                    $sod.data("filter", $sod.data("filter") + String.fromCharCode(e.which));
362
363                    // Check for matches of the typed string
364                    $sodFilterHit = $sodOptions.filter(function() {
365                        return $(this).text().toLowerCase().indexOf($sod.data("filter").toLowerCase()) === 0;
366                    }).not(".disabled, .optgroup").first();
367
368                    // If the typed value is a hit, then set it to active
369                    if ( $sodFilterHit.length ) {
370                        $optionActive.removeClass("active");
371                        $sodFilterHit.addClass("active");
372                        _private.listScroll($sodList, $sodFilterHit);
373                        $sodLabel.get(0).lastChild.nodeValue = $sodFilterHit.text();
374
375                        if ( !$sod.hasClass("open") ) {
376                            $_sodKeysWhenClosed = true;
377                        }
378                    }
379
380                    // Set a timeout to empty the data-filter
381                    $_sodFilterTimeout = setTimeout( function() {
382                        $sod.data("filter", "");
383                    }, 500);
384                }
385            }, // keyboardUse
386
387
388            optionHover: function () {
389                var $option = $(this);
390
391                // Mousemove event on option to make the SoD behave just like a native select
392                if ( !$option.hasClass("disabled") && !$option.hasClass("optgroup") ) {
393                    $option.siblings().removeClass("active").end().addClass("active");
394                }
395            }, // optionHover
396
397
398            optionClick: function (e) {
399                e.stopPropagation();
400
401                var $clicked        = $(this),
402                    $sod            = $clicked.closest(".sod_select"),
403                    $optionDisabled = $clicked.hasClass("disabled"),
404                    $optionOptgroup = $clicked.hasClass("optgroup"),
405                    $optionIndex    = $sod.find(".sod_option:not('.optgroup')").index(this);
406
407                // Fixes https://github.com/vestman/Select-or-Die/issues/8, thanks builtbylane
408                if ( $sod.hasClass("touch") ) {
409                    return;
410                }
411
412                // If not disabled or optgroup
413                if ( !$optionDisabled && !$optionOptgroup ) {
414                    $sod.find(".selected, .sod_placeholder").removeClass("selected sod_placeholder");
415                    $clicked.addClass("selected");
416                    $sod.find("select option")[$optionIndex].selected = true;
417                    $sod.find("select").change();
418                }
419
420                // Clear viewport check timeout
421                clearTimeout($_sodViewportTimeout);
422
423                // Hide the list
424                $sod.removeClass("open");
425            }, // optionClick
426
427
428            selectChange: function () {
429                var $select         = $(this),
430                    $optionSelected = $select.find(":selected"),
431                    $optionText     = $optionSelected.text(),
432                    $sod            = $select.closest(".sod_select");
433
434                $sod.find(".sod_label").get(0).lastChild.nodeValue = $optionText;
435                $sod.data("label", $optionText);
436
437                // Triggers the onChange callback
438                $_settings.onChange.call(this);
439
440                // If $_settings.links, send the user to the URL
441                if ( ($sod.data("links") || $optionSelected.data("link")) && !$optionSelected.data("link-external") ) {
442                    window.location.href = $optionSelected.val();
443                }
444                else if ( $sod.data("links-external") || $optionSelected.data("link-external") ) {
445                    window.open($optionSelected.val(),"_blank");
446                }
447            }, // selectChange
448
449
450            blurSod: function ($sod) {
451                if ( $("body").find($sod).length ) {
452                    var $sodLabel         = $sod.data("label"),
453                        $sodPlaceholder   = $sod.data("placeholder"),
454                        $optionActive     = $sod.find(".active"),
455                        $optionSelected   = $sod.find(".selected"),
456                        $optionHasChanged = false;
457
458                    // Clear viewport check timeout
459                    clearTimeout($_sodViewportTimeout);
460
461                    // Check the $sod for changes. If the user has used his keys when the SoD was closed
462                    // we'll set the currently active option to selected. If the user used his keys when
463                    // the SoD was open but did NOT make a selection, then we'll restore the SoD
464                    if ( $_sodKeysWhenClosed && !$optionActive.hasClass("selected") ) {
465                        $optionActive.click();
466                        $optionHasChanged = true;
467                    }
468                    else if ( !$optionActive.hasClass("selected") ) {
469                        $optionActive.removeClass("active");
470                        $optionSelected.addClass("active");
471                    }
472
473                    if ( !$optionHasChanged && $sodPlaceholder ) {
474                        $sod.find(".sod_label").get(0).lastChild.nodeValue = $optionSelected.text();
475                    } else if ( !$optionHasChanged ) {
476                        $sod.find(".sod_label").get(0).lastChild.nodeValue = $sodLabel;
477                    }
478
479                    // Reset the flag indicating whether the user has used his arrow keys when the SoD
480                    // was closed or not
481                    $_sodKeysWhenClosed = false;
482
483                    // Remove open/focus class
484                    $sod.removeClass("open focus");
485
486                    // Blur the SOD
487                    $sod.blur();
488
489                    // Unbind the
490                    $("html").off(".sodBlur");
491                }
492            }, // blurSod
493
494
495            checkViewport: function ($sod, $sodList) {
496                var $sodPosition   = $sod[0].getBoundingClientRect(),
497                    $sodListHeight = $sodList.outerHeight();
498
499                // If the list is below the viewport AND fits above, then show it above
500                if ( ($sodPosition.bottom + $sodListHeight + 10) > $(window).height() && ($sodPosition.top - $sodListHeight) > 10 ) {
501                    $sod.addClass("above");
502                }
503                else {
504                    $sod.removeClass("above");
505                }
506
507                // This was fun, lets do it again and again.
508                $_sodViewportTimeout = setTimeout( function() {
509                    _private.checkViewport($sod, $sodList);
510                }, 200);
511            }, // checkViewport
512
513
514            listScroll: function ($sodList, $option) {
515                var $scrollList   = $sodList[0].getBoundingClientRect(), // getBoundingClientRect FTW!
516                    $scrollOption = $option[0].getBoundingClientRect();
517
518                // Scroll list up and down
519                if ( $scrollList.top > $scrollOption.top ) {
520                    $sodList.scrollTop($sodList.scrollTop() - $scrollList.top + $scrollOption.top);
521                } else if ( $scrollList.bottom < $scrollOption.bottom ) {
522                    $sodList.scrollTop($sodList.scrollTop() - $scrollList.bottom + $scrollOption.bottom);
523                }
524            }, // listScroll
525
526
527            isTouch: function () {
528                return (("ontouchstart" in window) || (navigator.MaxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0));
529            } // isTouch
530
531        };
532
533        var methods = {
534
535            destroy: function () {
536                return this.each(function () {
537                    var $select = $(this),
538                        $sod    = $select.parent();
539
540                    // Destroy the SoD
541                    if ( $sod.hasClass("sod_select") ) {
542                        // Unbind the change event on the real <select>
543                        $select.off("change");
544
545                        // Restore DOM
546                        $sod.find("span").remove();
547                        $select.unwrap();
548                    } else {
549                        console.log("Select or Die: There's no SoD to destroy");
550                    }
551                });
552            }, // destroy
553
554
555            update: function () {
556                return this.each(function () {
557                    var $select  = $(this),
558                        $sod     = $select.parent(),
559                        $sodList = $sod.find(".sod_list:first");
560
561                    // Check for the SoD
562                    if ( $sod.hasClass("sod_select") ) {
563                        // Empty current list of options in faux <select>
564                        $sodList.empty();
565
566                        // Clear the label (but keep prefix)
567                        $sod.find(".sod_label").get(0).lastChild.nodeValue = "";
568
569                        // Disable the SoD if the select is disabled
570                        if ( $select.is(":disabled") ) {
571                            $sod.addClass("disabled");
572                        }
573
574                        // Inserts a <span class="sod_option"> for each <option>
575                        $("option, optgroup", $select).each(function () {
576                            _private.populateSoD($(this), $sodList, $sod);
577                        });
578                    } else {
579                        console.log("Select or Die: There's no SoD to update");
580                    }
581                });
582
583            }, // update
584
585
586            disable: function ($value) {
587                return this.each(function () {
588                    var $select = $(this),
589                        $sod    = $select.parent();
590
591                    // Check for the SoD
592                    if ( $sod.hasClass("sod_select") ) {
593                        if ( typeof $value !== "undefined" ) { // Disable option/optgroup
594
595                            // Disables the option (and possible children if optgroup) in the SoD
596                            $sod.find(".sod_list:first .sod_option[data-value='" + $value + "']").addClass("disabled");
597                            $sod.find(".sod_list:first .sod_option[data-label='" + $value + "']").nextUntil(":not(.groupchild)").addClass("disabled");
598
599                            // Disables the option/optgroup in the real <select>
600                            $("option[value='" + $value + "'], optgroup[label='" + $value + "']", this).prop("disabled", true);
601
602                        } else if ( $sod.hasClass("sod_select") ) { // Disable select/SoD
603                            $sod.addClass("disabled");
604                            $select.prop("disabled", true);
605                        }
606                    } else {
607                        console.log("Select or Die: There's no SoD to disable");
608                    }
609                });
610            }, // disable
611
612
613            enable: function ($value) {
614                return this.each(function () {
615                    var $select = $(this),
616                        $sod    = $select.parent();
617
618                    // Check for the SoD
619                    if ( $sod.hasClass("sod_select") ) {
620                        if ( typeof $value !== "undefined" ) { // Enable option/optgroup
621
622                            // Enables the option (and possible children if optgroup) in the SoD
623                            $sod.find(".sod_list:first .sod_option[data-value='" + $value + "']").removeClass("disabled");
624                            $sod.find(".sod_list:first .sod_option[data-label='" + $value + "']").nextUntil(":not(.groupchild)").removeClass("disabled");
625
626                            // Enables the option in the real <select>
627                            $("option[value='" + $value + "'], optgroup[label='" + $value + "']", this).prop("disabled", false);
628
629                        } else if ( $sod.hasClass("sod_select") ) { // Enable select/SoD
630                            $sod.removeClass("disabled");
631                            $select.prop("disabled", false);
632                        }
633                    } else {
634                        console.log("Select or Die: There's no SoD to enable");
635                    }
636                });
637            } // enable
638
639        };
640
641        if ( methods[method] ) {
642            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
643        } else if ( typeof method === "object" || !method ) {
644            return _private.initSoD.apply(this, arguments);
645        } else {
646            $.error("Select or Die: Oh no! No such method \"" + method + "\" for the SoD instance");
647        }
648    };
649
650})(jQuery);

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.