forked from gfranko/jquery.selectBoxIt.js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjquery.selectBoxIt.js
executable file
·2869 lines (1770 loc) · 95.5 KB
/
jquery.selectBoxIt.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* jquery SelectBoxIt - v3.3.0 - 2013-3-19
* http://www.gregfranko.com/jQuery.selectBoxIt.js/
* Copyright (c) 2012 Greg Franko; Licensed MIT */
// Immediately-Invoked Function Expression (IIFE) [Ben Alman Blog Post](http://benalman.com/news/2010/11/immediately-invoked-function-expression/) that calls another IIFE that contains all of the plugin logic. I used this pattern so that anyone viewing this code would not have to scroll to the bottom of the page to view the local parameters that were passed to the main IIFE.
;(function (selectBoxIt) {
//ECMAScript 5 Strict Mode: [John Resig Blog Post](http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/)
"use strict";
// Calls the second IIFE and locally passes in the global jQuery, window, and document objects
selectBoxIt(window.jQuery, window, document);
}
// Locally passes in `jQuery`, the `window` object, the `document` object, and an `undefined` variable. The `jQuery`, `window` and `document` objects are passed in locally, to improve performance, since javascript first searches for a variable match within the local variables set before searching the global variables set. All of the global variables are also passed in locally to be minifier friendly. `undefined` can be passed in locally, because it is not a reserved word in JavaScript.
(function ($, window, document, undefined) {
// ECMAScript 5 Strict Mode: [John Resig Blog Post](http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/)
"use strict";
// Calling the jQueryUI Widget Factory Method
$.widget("selectBox.selectBoxIt", {
// Plugin version
VERSION: "3.3.0",
// These options will be used as defaults
options: {
// **showEffect**: Accepts String: "none", "fadeIn", "show", "slideDown", or any of the jQueryUI show effects (i.e. "bounce")
"showEffect": "none",
// **showEffectOptions**: Accepts an object literal. All of the available properties are based on the jqueryUI effect options
"showEffectOptions": {},
// **showEffectSpeed**: Accepts Number (milliseconds) or String: "slow", "medium", or "fast"
"showEffectSpeed": "medium",
// **hideEffect**: Accepts String: "none", "fadeOut", "hide", "slideUp", or any of the jQueryUI hide effects (i.e. "explode")
"hideEffect": "none",
// **hideEffectOptions**: Accepts an object literal. All of the available properties are based on the jqueryUI effect options
"hideEffectOptions": {},
// **hideEffectSpeed**: Accepts Number (milliseconds) or String: "slow", "medium", or "fast"
"hideEffectSpeed": "medium",
// **showFirstOption**: Shows the first dropdown list option within the dropdown list options list
"showFirstOption": true,
// **defaultText**: Overrides the text used by the dropdown list selected option to allow a user to specify custom text. Accepts a String.
"defaultText": "",
// **defaultIcon**: Overrides the icon used by the dropdown list selected option to allow a user to specify a custom icon. Accepts a String (CSS class name(s)).
"defaultIcon": "",
// **downArrowIcon**: Overrides the default down arrow used by the dropdown list to allow a user to specify a custom image. Accepts a String (CSS class name(s)).
"downArrowIcon": "",
// **theme**: Provides theming support for Twitter Bootstrap and jQueryUI
"theme": "default",
// **keydownOpen**: Opens the dropdown if the up or down key is pressed when the dropdown is focused
"keydownOpen": true,
// **isMobile**: Function to determine if a user's browser is a mobile browser
"isMobile": function() {
// Adapted from http://www.detectmobilebrowsers.com
var ua = navigator.userAgent || navigator.vendor || window.opera;
// Checks for iOs, Android, Blackberry, Opera Mini, and Windows mobile devices
return (/iPhone|iPod|iPad|Android|BlackBerry|Opera Mini|IEMobile/).test(ua);
},
// **native**: Triggers the native select box when a user interacts with the drop down
"native": false,
// **aggressiveChange**: Will select a drop down item (and trigger a change event) when a user navigates to the item via the keyboard (up and down arrow or search), before a user selects an option with a click or the enter key
"aggressiveChange": false,
// **selectWhenHidden: Will allow a user to select an option using the keyboard when the drop down list is hidden and focused
"selectWhenHidden": true,
// **viewport**: Allows for a custom domnode used for the viewport. Accepts a selector. Default is $(window).
"viewport": $(window),
// **similarSearch**: Optimizes the search for lists with many similar values (i.e. State lists) by making it easier to navigate through
"similarSearch": false,
// **copyAttributes**: HTML attributes that will be copied over to the new drop down
"copyAttributes": [
"title",
"rel"
],
// **copyClasses**: HTML classes that will be copied over to the new drop down. The value indicates where the classes should be copied. The default value is 'button', but you can also use 'container' (recommended) or 'none'.
"copyClasses": "button",
// **nativeMousedown**: Mimics native firefox drop down behavior by opening the drop down on mousedown and selecting the currently hovered drop down option on mouseup
"nativeMousedown": false,
// **customShowHideEvent**: Prevents the drop down from opening on click or mousedown, which allows a user to open/close the drop down with a custom event handler.
"customShowHideEvent": false,
// **autoWidth**: Makes sure the width of the drop down is wide enough to fit all of the drop down options
"autoWidth": true,
// **html**: Determines whether or not option text is rendered as html or as text
"html": true
},
// Get Themes
// ----------
// Retrieves the active drop down theme and returns the theme object
"getThemes": function() {
var self = this,
theme = $(self.element).attr("data-theme") || "c";
return {
// Twitter Bootstrap Theme
"bootstrap": {
"focus": "active",
"hover": "",
"disabled": "disabled",
"arrow": "caret",
"button": "btn",
"list": "dropdown-menu",
"container": "bootstrap",
"open": "open"
},
// jQueryUI Theme
"jqueryui": {
"focus": "ui-state-focus",
"hover": "ui-state-hover",
"disabled": "ui-state-disabled",
"arrow": "ui-icon ui-icon-triangle-1-s",
"button": "ui-widget ui-state-default",
"list": "ui-widget ui-widget-content",
"container": "jqueryui",
"open": "selectboxit-open"
},
// jQuery Mobile Theme
"jquerymobile": {
"focus": "ui-btn-down-" + theme,
"hover": "ui-btn-hover-" + theme,
"disabled": "ui-disabled",
"arrow": "ui-icon ui-icon-arrow-d ui-icon-shadow",
"button": "ui-btn ui-btn-icon-right ui-btn-corner-all ui-shadow ui-btn-up-" + theme,
"list": "ui-btn ui-btn-icon-right ui-btn-corner-all ui-shadow ui-btn-up-" + theme,
"container": "jquerymobile",
"open": "selectboxit-open"
},
"default": {
"focus": "selectboxit-focus",
"hover": "selectboxit-hover",
"disabled": "selectboxit-disabled",
"arrow": "selectboxit-default-arrow",
"button": "selectboxit-btn",
"list": "selectboxit-list",
"container": "selectboxit-container",
"open": "selectboxit-open"
}
};
},
// _Create
// -------
// Sets the Plugin Instance variables and
// constructs the plugin. Only called once.
_create: function() {
var self = this;
// If the element calling SelectBoxIt is not a select box or is not visible
if(!self.element.is("select")) {
// Exits the plugin
return;
}
// Hides the original select box
self.element.hide();
// The original select box DOM element
self.originalElem = self.element[0];
// The original select box DOM element wrapped in a jQuery object
self.selectBox = self.element;
// All of the original select box options
self.selectItems = self.element.find("option");
// The first option in the original select box
self.firstSelectItem = self.selectItems.slice(0, 1);
// The html document height
self.documentHeight = $(document).height();
self.theme = self.getThemes()[self.options["theme"]] || self.getThemes()["default"];
// The index of the currently selected dropdown list option
self.currentFocus = 0;
// Keeps track of which blur events will hide the dropdown list options
self.blur = true;
// Array holding all of the original select box options text
self.textArray = [];
// Maintains search order in the `search` method
self.currentIndex = 0;
// Maintains the current search text in the `search` method
self.currentText = "";
// Whether or not the dropdown list opens up or down (depending on how much room is on the page)
self.flipped = false;
// Creates the dropdown elements that will become the dropdown
// Creates the ul element that will become the dropdown options list
// Add's all attributes (excluding id, class names, and unselectable properties) to the drop down and drop down items list
// Hides the original select box and adds the new plugin DOM elements to the page
// Adds event handlers to the new dropdown list
self._createDropdownButton()._createUnorderedList()._copyAttributes()._replaceSelectBox()._addClasses(self.theme)._eventHandlers();
if(self.originalElem.disabled && self.disable) {
// Disables the dropdown list if the original dropdown list had the `disabled` attribute
self.disable();
}
// If the Aria Accessibility Module has been included
if(self._ariaAccessibility) {
// Adds ARIA accessibillity tags to the dropdown list
self._ariaAccessibility();
}
if(self._mobile) {
// Adds mobile support
self._mobile();
}
// If the native option is set to true
if(self.options["native"]) {
// Triggers the native select box when a user is interacting with the drop down
this._applyNativeSelect();
}
// Triggers a custom `create` event on the original dropdown list
self.triggerEvent("create");
// Maintains chainability
return self;
},
// _Create dropdown button
// -----------------------
// Creates new dropdown and dropdown elements to replace
// the original select box with a dropdown list
_createDropdownButton: function() {
var self = this,
originalElemId = self.originalElem.id || "",
copyClasses = self.options["copyClasses"],
selectboxClasses = self.selectBox.attr("class") || "";
// Creates a dropdown element that contains the dropdown list text value
self.dropdownText = $("<span/>", {
// Dynamically sets the dropdown `id` attribute
"id": originalElemId && originalElemId + "SelectBoxItText",
"class": "selectboxit-text",
// IE specific attribute to not allow the element to be selected
"unselectable": "on",
// Sets the dropdown `text` to equal the original select box default value
"text": self.firstSelectItem.text()
}).
// Sets the HTML5 data attribute on the dropdownText `dropdown` element
attr("data-val", self.originalElem.value);
self.dropdownImageContainer = $("<span/>", {
"class": "selectboxit-option-icon-container"
});
// Creates a dropdown element that contains the dropdown list text value
self.dropdownImage = $("<i/>", {
// Dynamically sets the dropdown `id` attribute
"id": originalElemId && originalElemId + "SelectBoxItDefaultIcon",
"class": "selectboxit-default-icon",
// IE specific attribute to not allow the element to be selected
"unselectable": "on"
});
// Creates a dropdown to act as the new dropdown list
self.dropdown = $("<span/>", {
// Dynamically sets the dropdown `id` attribute
"id": originalElemId && originalElemId + "SelectBoxIt",
"class": "selectboxit " + (copyClasses === "button" ? selectboxClasses: ""),
// Sets the dropdown `name` attribute to be the same name as the original select box
"name": self.originalElem.name,
// Sets the dropdown `tabindex` attribute to 0 to allow the dropdown to be focusable
"tabindex": self.selectBox.attr("tabindex") || "0",
// IE specific attribute to not allow the element to be selected
"unselectable": "on"
}).
// Appends the default text to the inner dropdown list dropdown element
append(self.dropdownImageContainer.append(self.dropdownImage)).append(self.dropdownText);
// Create the dropdown container that will hold all of the dropdown list dom elements
self.dropdownContainer = $("<span/>", {
"id": originalElemId && originalElemId + "SelectBoxItContainer",
"class": "selectboxit-container " + (copyClasses === "container" ? selectboxClasses: "")
}).
// Appends the inner dropdown list dropdown element to the dropdown list container dropdown element
append(self.dropdown);
// Maintains chainability
return self;
},
// _Create Unordered List
// ----------------------
// Creates an unordered list element to hold the
// new dropdown list options that directly match
// the values of the original select box options
_createUnorderedList: function() {
// Storing the context of the widget
var self = this,
dataDisabled,
optgroupClass,
optgroupElement,
iconClass,
iconUrl,
iconUrlClass,
iconUrlStyle,
// Declaring the variable that will hold all of the dropdown list option elements
currentItem = "",
originalElemId = self.originalElem.id || "",
// Creates an unordered list element
createdList = $("<ul/>", {
// Sets the unordered list `id` attribute
"id": originalElemId && originalElemId + "SelectBoxItOptions",
"class": "selectboxit-options",
//Sets the unordered list `tabindex` attribute to -1 to prevent the unordered list from being focusable
"tabindex": -1
}),
currentDataSelectedText,
currentDataText,
currentText;
// Checks the `showFirstOption` plugin option to determine if the first dropdown list option should be shown in the options list.
if (!self.options["showFirstOption"]) {
// Excludes the first dropdown list option from the options list
self.selectItems = self.selectBox.find("option").slice(1);
}
// Loops through the original select box options list and copies the text of each
// into new list item elements of the new dropdown list
self.selectItems.each(function(index) {
optgroupClass = "";
optgroupElement = "";
dataDisabled = $(this).prop("disabled");
iconClass = $(this).data("icon") || "";
iconUrl = $(this).data("iconurl") || "";
iconUrlClass = iconUrl ? "selectboxit-option-icon-url": "";
iconUrlStyle = iconUrl ? 'style="background-image:url(\'' + iconUrl + '\');"': "",
currentDataSelectedText = $(this).attr("data-selectedtext"),
currentDataText = $(this).attr("data-text"),
currentText = currentDataText ? currentDataText: $(this).text();
// If the current option being traversed is within an optgroup
if($(this).parent().is("optgroup")) {
optgroupClass = "selectboxit-optgroup-option";
if($(this).index() === 0) {
optgroupElement = '<span class="selectboxit-optgroup-header" data-disabled="true">' + $(this).parent().first().attr("label") + '</span>';
}
}
// Uses string concatenation for speed (applies HTML attribute encoding)
currentItem += optgroupElement + '<li id="' + index + '" data-val="' + this.value + '" data-disabled="' + dataDisabled + '" class="' + optgroupClass + " selectboxit-option " + ($(this).attr("class") || "") + '"><a class="selectboxit-option-anchor"><span class="selectboxit-option-icon-container"><i class="selectboxit-option-icon ' + iconClass + ' ' + (iconUrlClass || self.theme["container"]) + '"' + iconUrlStyle + '></i></span>' + (self.options["html"] ? currentText: self.htmlEscape(currentText)) + '</a></li>';
// Stores all of the original select box options text inside of an array
// (Used later in the `searchAlgorithm` method)
self.textArray[index] = dataDisabled ? "": currentText;
// Checks the original select box option for the `selected` attribute
if (this.selected) {
// Replaces the default text with the selected option text
self._setText(self.dropdownText, currentDataSelectedText || currentText);
//Set the currently selected option
self.currentFocus = index;
}
});
// If the `defaultText` option is being used
if ((self.options["defaultText"] || self.selectBox.data("text")) && !self.selectBox.find("option[selected]").length) {
var defaultedText = self.options["defaultText"] || self.selectBox.data("text");
//Overrides the current dropdown default text with the value the user specifies in the `defaultText` option
self._setText(self.dropdownText, defaultedText);
self.options["defaultText"] = defaultedText;
}
// Append the list item to the unordered list
createdList.append(currentItem);
// Stores the dropdown list options list inside of the `list` instance variable
self.list = createdList;
// Append the dropdown list options list to the dropdown container element
self.dropdownContainer.append(self.list);
// Stores the indropdownidual dropdown list options inside of the `listItems` instance variable
self.listItems = self.list.find("li");
// Sets the 'selectboxit-option-first' class name on the first drop down option
self.listItems.first().addClass("selectboxit-option-first");
// Sets the 'selectboxit-option-last' class name on the last drop down option
self.listItems.last().addClass("selectboxit-option-last");
// Set the disabled CSS class for select box options
self.list.find("li[data-disabled='true']").not(".optgroupHeader").addClass(self.theme["disabled"]);
self.dropdownImage.addClass(self.selectBox.data("icon") || self.options["defaultIcon"] || self.listItems.eq(self.currentFocus).find("i").attr("class"));
self.dropdownImage.attr("style", self.listItems.eq(self.currentFocus).find("i").attr("style"));
//Maintains chainability
return self;
},
// _Replace Select Box
// -------------------
// Hides the original dropdown list and inserts
// the new DOM elements
_replaceSelectBox: function() {
var self = this,
height,
originalElemId = self.originalElem.id || "";
// Hides the original select box
self.selectBox.css("display", "none").
// Adds the new dropdown list to the page directly after the hidden original select box element
after(self.dropdownContainer);
// The height of the dropdown list
height = self.dropdown.height();
// The down arrow element of the dropdown list
self.downArrow = $("<i/>", {
// Dynamically sets the dropdown `id` attribute of the dropdown list down arrow
"id": originalElemId && originalElemId + "SelectBoxItArrow",
"class": "selectboxit-arrow",
// IE specific attribute to not allow the dropdown list text to be selected
"unselectable": "on"
});
// The down arrow container element of the dropdown list
self.downArrowContainer = $("<span/>", {
// Dynamically sets the dropdown `id` attribute for the down arrow container element
"id": originalElemId && originalElemId + "SelectBoxItArrowContainer",
"class": "selectboxit-arrow-container",
// IE specific attribute to not allow the dropdown list text to be selected
"unselectable": "on"
}).
// Inserts the down arrow element inside of the down arrow container element
append(self.downArrow);
// Appends the down arrow element to the dropdown list
self.dropdown.append(self.downArrowContainer);
// Adds the `selectboxit-selected` class name to the currently selected drop down option
self.listItems.removeClass("selectboxit-selected").eq(self.currentFocus).addClass("selectboxit-selected");
// If an image is not being used
if(!self.dropdownImageContainer.width()) {
// Removes the image and image container
self.dropdownImageContainer.remove();
}
if(self.options["autoWidth"]) {
self.dropdown.css({ "width": "auto" }).css({
"width": self.list.outerWidth(true) + self.downArrowContainer.outerWidth(true) + self.dropdownImage.outerWidth(true)
});
}
// Dynamically adds the `max-width` and `line-height` CSS styles of the dropdown list text element
self.dropdownText.css({
"max-width": self.dropdownContainer.width() - (self.downArrowContainer.outerWidth(true) + self.dropdownImage.outerWidth(true))
});
// Maintains chainability
return self;
},
// _Scroll-To-View
// ---------------
// Updates the dropdown list scrollTop value
_scrollToView: function(type) {
var self = this,
currentOption = self.listItems.eq(self.currentFocus),
// The current scroll positioning of the dropdown list options list
listScrollTop = self.list.scrollTop(),
// The height of the currently selected dropdown list option
currentItemHeight = currentOption.height(),
// The relative distance from the currently selected dropdown list option to the the top of the dropdown list options list
currentTopPosition = currentOption.position().top,
absCurrentTopPosition = Math.abs(currentTopPosition),
// The height of the dropdown list option list
listHeight = self.list.height(),
currentText;
// Scrolling logic for a text search
if (type === "search") {
// Increases the dropdown list options `scrollTop` if a user is searching for an option
// below the currently selected option that is not visible
if (listHeight - currentTopPosition < currentItemHeight) {
// The selected option will be shown at the very bottom of the visible options list
self.list.scrollTop(listScrollTop + (currentTopPosition - (listHeight - currentItemHeight)));
}
// Decreases the dropdown list options `scrollTop` if a user is searching for an option above the currently selected option that is not visible
else if (currentTopPosition < -1) {
self.list.scrollTop(currentTopPosition - currentItemHeight);
}
}
// Scrolling logic for the `up` keyboard navigation
else if (type === "up") {
// Decreases the dropdown list option list `scrollTop` if a user is navigating to an element that is not visible
if (currentTopPosition < -1) {
self.list.scrollTop(listScrollTop - absCurrentTopPosition);
}
}
// Scrolling logic for the `down` keyboard navigation
else if (type === "down") {
// Increases the dropdown list options `scrollTop` if a user is navigating to an element that is not fully visible
if (listHeight - currentTopPosition < currentItemHeight) {
// Increases the dropdown list options `scrollTop` by the height of the current option item.
self.list.scrollTop((listScrollTop + (absCurrentTopPosition - listHeight + currentItemHeight)));
}
}
// Maintains chainability
return self;
},
// _Callback
// ---------
// Call the function passed into the method
_callbackSupport: function(callback) {
var self = this;
// Checks to make sure the parameter passed in is a function
if ($.isFunction(callback)) {
// Calls the method passed in as a parameter and sets the current `SelectBoxIt` object that is stored in the jQuery data method as the context(allows for `this` to reference the SelectBoxIt API Methods in the callback function. The `dropdown` DOM element that acts as the new dropdown list is also passed as the only parameter to the callback
callback.call(self, self.dropdown);
}
// Maintains chainability
return self;
},
// _setText
// --------
// Set's the text or html for the drop down
_setText: function(elem, currentText) {
var self = this;
if(self.options["html"]) {
elem.html(currentText);
}
else {
elem.text(currentText);
}
return self;
},
// Open
// ----
// Opens the dropdown list options list
open: function(callback) {
var self = this,
showEffect = self.options["showEffect"],
showEffectSpeed = self.options["showEffectSpeed"],
showEffectOptions = self.options["showEffectOptions"],
isNative = self.options["native"],
isMobile = self.options["isMobile"]();
// If there are no select box options, do not try to open the select box
if(!self.listItems.length) {
return self;
}
// If the new drop down is being used and is not visible
if((!isNative && !isMobile) && !this.list.is(":visible")) {
// Triggers a custom "open" event on the original select box
self.triggerEvent("open");
if (self._dynamicPositioning) {
// Dynamically positions the dropdown list options list
self._dynamicPositioning();
}
// Uses `no effect`
if(showEffect === "none") {
// Does not require a callback function because this animation will complete before the call to `scrollToView`
self.list.show();
}
// Uses the jQuery `show` special effect
else if(showEffect === "show") {
// Requires a callback function to determine when the `show` animation is complete
self.list.show(showEffectSpeed);
}
// Uses the jQuery `slideDown` special effect
else if(showEffect === "slideDown") {
// Requires a callback function to determine when the `slideDown` animation is complete
self.list.slideDown(showEffectSpeed);
}
// Uses the jQuery `fadeIn` special effect
else if(showEffect === "fadeIn") {
// Does not require a callback function because this animation will complete before the call to `scrollToView`
self.list.fadeIn(showEffectSpeed);
}
// If none of the above options were passed, then a `jqueryUI show effect` is expected
else {
// Allows for custom show effects via the [jQueryUI core effects](http://http://jqueryui.com/demos/show/)
self.list.show(showEffect, showEffectOptions, showEffectSpeed);
}
self.list.promise().done(function() {
// Updates the list `scrollTop` attribute
self._scrollToView("search");
});
}
// Provide callback function support
self._callbackSupport(callback);
// Maintains chainability
return self;
},
// Close
// -----
// Closes the dropdown list options list
close: function(callback) {
var self = this,
hideEffect = self.options["hideEffect"],
hideEffectSpeed = self.options["hideEffectSpeed"],
hideEffectOptions = self.options["hideEffectOptions"],
isNative = self.options["native"],
isMobile = self.options["isMobile"]();
// If the drop down is being used and is visible
if((!isNative && !isMobile) && this.list.is(":visible")) {
// Triggers a custom "close" event on the original select box
self.triggerEvent("close");
// Uses `no effect`
if(hideEffect === "none") {
// Does not require a callback function because this animation will complete before the call to `scrollToView`
self.list.hide();
}
// Uses the jQuery `hide` special effect
else if(hideEffect === "hide") {
self.list.hide(hideEffectSpeed);
}
// Uses the jQuery `slideUp` special effect
else if(hideEffect === "slideUp") {
self.list.slideUp(hideEffectSpeed);
}
// Uses the jQuery `fadeOut` special effect
else if(hideEffect === "fadeOut") {
self.list.fadeOut(hideEffectSpeed);
}
// If none of the above options were passed, then a `jqueryUI hide effect` is expected
else {
// Allows for custom hide effects via the [jQueryUI core effects](http://http://jqueryui.com/demos/hide/)
self.list.hide(hideEffect, hideEffectOptions, hideEffectSpeed);
}
}
// Provide callback function support
self._callbackSupport(callback);
// Maintains chainability
return self;
},
toggle: function() {
var self = this,
listIsVisible = self.list.is(":visible");
if(listIsVisible) {
self.close();
}
else if(!listIsVisible) {
self.open();
}
},
// _Key Mappings
// -------------
// Object literal holding the string representation of each key code
_keyMappings: {
"38": "up",
"40": "down",
"13": "enter",
"8": "backspace",
"9": "tab",
"32": "space",
"27": "esc"
},
// _Key Down Methods
// -----------------
// Methods to use when the keydown event is triggered
_keydownMethods: function() {
var self = this,
moveToOption = self.list.is(":visible") || !self.options["keydownOpen"];
return {
"down": function() {
// If the plugin options allow keyboard navigation
if (self.moveDown && moveToOption) {
self.moveDown();
}
},
"up": function() {
// If the plugin options allow keyboard navigation
if (self.moveUp && moveToOption) {
self.moveUp();
}
},
"enter": function() {
var activeElem = self.list.find("li." + self.focusClass);
// If there is no active Elem yet
if(!activeElem.length) {
activeElem = self.listItems.first();
}
// Updates the dropdown list value
self._update(activeElem);