PluginProbe ʕ •ᴥ•ʔ
YITH WooCommerce Wishlist / 3.0.17
YITH WooCommerce Wishlist v3.0.17
4.16.0 trunk 2.1.0 2.1.1 2.1.2 2.2.0 2.2.1 2.2.10 2.2.11 2.2.12 2.2.13 2.2.14 2.2.15 2.2.16 2.2.17 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 3.0.0 3.0.1 3.0.10 3.0.11 3.0.12 3.0.13 3.0.14 3.0.15 3.0.16 3.0.17 3.0.18 3.0.19 3.0.2 3.0.20 3.0.21 3.0.22 3.0.23 3.0.25 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.10.0 3.11.0 3.12.0 3.13.0 3.14.0 3.15.0 3.16.0 3.17.0 3.18.0 3.19.0 3.2.0 3.20.0 3.21.0 3.22.0 3.23.0 3.24.0 3.25.0 3.26.0 3.27.0 3.28.0 3.29.0 3.3.0 3.30.0 3.31.0 3.32.0 3.33.0 3.34.0 3.35.0 3.36.0 3.37.0 3.38.0 3.4.0 3.5.0 3.6.0 3.7.0 3.8.0 3.9.0 4.0.0 4.0.1 4.1.0 4.10.0 4.10.1 4.10.2 4.11.0 4.12.0 4.13.0 4.14.0 4.15.0 4.2.0 4.3.0 4.4.0 4.5.0 4.6.0 4.7.0 4.8.0 4.9.0
yith-woocommerce-wishlist / assets / js / unminified / jquery.selectBox.js
yith-woocommerce-wishlist / assets / js / unminified Last commit date
admin 5 years ago jquery.selectBox.js 9 years ago jquery.yith-wcwl.js 5 years ago
jquery.selectBox.js
1092 lines
1 /*
2 * jQuery selectBox - A cosmetic, styleable replacement for SELECT elements
3 *
4 * Licensed under the MIT license: http://opensource.org/licenses/MIT
5 *
6 * v1.2.0
7 *
8 * https://github.com/marcj/jquery-selectBox
9 */
10 ;(function ($) {
11
12 /**
13 * SelectBox class.
14 *
15 * @param {HTMLElement|jQuery} select If it's a jQuery object, we use the first element.
16 * @param {Object} options
17 * @constructor
18 */
19 var SelectBox = this.SelectBox = function (select, options) {
20 if (select instanceof jQuery) {
21 if (select.length > 0) {
22 select = select[0];
23 } else {
24 return;
25 }
26 }
27
28 this.typeTimer = null;
29 this.typeSearch = '';
30 this.isMac = navigator.platform.match(/mac/i);
31 options = 'object' === typeof options ? options : {};
32 this.selectElement = select;
33
34 // Disable for iOS devices (their native controls are more suitable for a touch device)
35 if (!options.mobile && navigator.userAgent.match(/iPad|iPhone|Android|IEMobile|BlackBerry/i)) {
36 return false;
37 }
38
39 // Element must be a select control
40 if ('select' !== select.tagName.toLowerCase()) {
41 return false;
42 }
43
44 this.init(options);
45 }
46
47 /**
48 * @type {String}
49 */
50 SelectBox.prototype.version = '1.2.0';
51
52 /**
53 * @param {Object} options
54 *
55 * @returns {Boolean}
56 */
57 SelectBox.prototype.init = function (options) {
58 var select = $(this.selectElement);
59 if (select.data('selectBox-control')) {
60 return false;
61 }
62
63 var control = $('<a class="selectBox" />')
64 , inline = select.attr('multiple') || parseInt(select.attr('size')) > 1
65 , settings = options || {}
66 , tabIndex = parseInt(select.prop('tabindex')) || 0
67 , self = this;
68
69 control
70 .width(select.outerWidth())
71 .addClass(select.attr('class'))
72 .attr('title', select.attr('title') || '')
73 .attr('tabindex', tabIndex)
74 .css('display', 'inline-block')
75 .bind('focus.selectBox', function () {
76 if (this !== document.activeElement && document.body !== document.activeElement) {
77 $(document.activeElement).blur();
78 }
79 if (control.hasClass('selectBox-active')) {
80 return;
81 }
82 control.addClass('selectBox-active');
83 select.trigger('focus');
84 })
85 .bind('blur.selectBox', function () {
86 if (!control.hasClass('selectBox-active')) {
87 return;
88 }
89 control.removeClass('selectBox-active');
90 select.trigger('blur');
91 });
92
93 if (!$(window).data('selectBox-bindings')) {
94 $(window)
95 .data('selectBox-bindings', true)
96 .bind('scroll.selectBox', this.hideMenus)
97 .bind('resize.selectBox', this.hideMenus);
98 }
99
100 if (select.attr('disabled')) {
101 control.addClass('selectBox-disabled');
102 }
103
104 // Focus on control when label is clicked
105 select.bind('click.selectBox', function (event) {
106 control.focus();
107 event.preventDefault();
108 });
109
110 // Generate control
111 if (inline) {
112 // Inline controls
113 options = this.getOptions('inline');
114
115 control
116 .append(options)
117 .data('selectBox-options', options).addClass('selectBox-inline selectBox-menuShowing')
118 .bind('keydown.selectBox', function (event) {
119 self.handleKeyDown(event);
120 })
121 .bind('keypress.selectBox',function (event) {
122 self.handleKeyPress(event);
123 })
124 .bind('mousedown.selectBox',function (event) {
125 if (1 !== event.which) {
126 return;
127 }
128 if ($(event.target).is('A.selectBox-inline')) {
129 event.preventDefault();
130 }
131 if (!control.hasClass('selectBox-focus')) {
132 control.focus();
133 }
134 })
135 .insertAfter(select);
136
137 // Auto-height based on size attribute
138 if (!select[0].style.height) {
139 var size = select.attr('size') ? parseInt(select.attr('size')) : 5;
140 // Draw a dummy control off-screen, measure, and remove it
141 var tmp = control
142 .clone()
143 .removeAttr('id')
144 .css({
145 position: 'absolute',
146 top: '-9999em'
147 })
148 .show()
149 .appendTo('body');
150 tmp.find('.selectBox-options').html('<li><a>\u00A0</a></li>');
151 var optionHeight = parseInt(tmp.find('.selectBox-options A:first').html('&nbsp;').outerHeight());
152 tmp.remove();
153 control.height(optionHeight * size);
154 }
155 this.disableSelection(control);
156 } else {
157 // Dropdown controls
158 var label = $('<span class="selectBox-label" />'),
159 arrow = $('<span class="selectBox-arrow" />');
160
161 // Update label
162 label.attr('class', this.getLabelClass()).text(this.getLabelText());
163 options = this.getOptions('dropdown');
164 options.appendTo('BODY');
165
166 control
167 .data('selectBox-options', options)
168 .addClass('selectBox-dropdown')
169 .append(label)
170 .append(arrow)
171 .bind('mousedown.selectBox', function (event) {
172 if (1 === event.which) {
173 if (control.hasClass('selectBox-menuShowing')) {
174 self.hideMenus();
175 } else {
176 event.stopPropagation();
177 // Webkit fix to prevent premature selection of options
178 options
179 .data('selectBox-down-at-x', event.screenX)
180 .data('selectBox-down-at-y', event.screenY);
181 self.showMenu();
182 }
183 }
184 })
185 .bind('keydown.selectBox', function (event) {
186 self.handleKeyDown(event);
187 })
188 .bind('keypress.selectBox', function (event) {
189 self.handleKeyPress(event);
190 })
191 .bind('open.selectBox',function (event, triggerData) {
192 if (triggerData && triggerData._selectBox === true) {
193 return;
194 }
195 self.showMenu();
196 })
197 .bind('close.selectBox', function (event, triggerData) {
198 if (triggerData && triggerData._selectBox === true) {
199 return;
200 }
201 self.hideMenus();
202 })
203 .insertAfter(select);
204
205 // Set label width
206 var labelWidth =
207 control.width()
208 - arrow.outerWidth()
209 - parseInt(label.css('paddingLeft')) || 0
210 - parseInt(label.css('paddingRight')) || 0;
211
212 label.width(labelWidth);
213 this.disableSelection(control);
214 }
215 // Store data for later use and show the control
216 select
217 .addClass('selectBox')
218 .data('selectBox-control', control)
219 .data('selectBox-settings', settings)
220 .hide();
221 };
222
223 /**
224 * @param {String} type 'inline'|'dropdown'
225 * @returns {jQuery}
226 */
227 SelectBox.prototype.getOptions = function (type) {
228 var options;
229 var select = $(this.selectElement);
230 var self = this;
231 // Private function to handle recursion in the getOptions function.
232 var _getOptions = function (select, options) {
233 // Loop through the set in order of element children.
234 select.children('OPTION, OPTGROUP').each(function () {
235 // If the element is an option, add it to the list.
236 if ($(this).is('OPTION')) {
237 // Check for a value in the option found.
238 if ($(this).length > 0) {
239 // Create an option form the found element.
240 self.generateOptions($(this), options);
241 } else {
242 // No option information found, so add an empty.
243 options.append('<li>\u00A0</li>');
244 }
245 } else {
246 // If the element is an option group, add the group and call this function on it.
247 var optgroup = $('<li class="selectBox-optgroup" />');
248 optgroup.text($(this).attr('label'));
249 options.append(optgroup);
250 options = _getOptions($(this), options);
251 }
252 });
253 // Return the built strin
254 return options;
255 };
256
257 switch (type) {
258 case 'inline':
259 options = $('<ul class="selectBox-options" />');
260 options = _getOptions(select, options);
261 options
262 .find('A')
263 .bind('mouseover.selectBox', function (event) {
264 self.addHover($(this).parent());
265 })
266 .bind('mouseout.selectBox',function (event) {
267 self.removeHover($(this).parent());
268 })
269 .bind('mousedown.selectBox',function (event) {
270 if (1 !== event.which) {
271 return
272 }
273 event.preventDefault(); // Prevent options from being "dragged"
274 if (!select.selectBox('control').hasClass('selectBox-active')) {
275 select.selectBox('control').focus();
276 }
277 })
278 .bind('mouseup.selectBox', function (event) {
279 if (1 !== event.which) {
280 return;
281 }
282 self.hideMenus();
283 self.selectOption($(this).parent(), event);
284 });
285
286 this.disableSelection(options);
287 return options;
288 case 'dropdown':
289 options = $('<ul class="selectBox-dropdown-menu selectBox-options" />');
290 options = _getOptions(select, options);
291
292 options
293 .data('selectBox-select', select)
294 .css('display', 'none')
295 .appendTo('BODY')
296 .find('A')
297 .bind('mousedown.selectBox', function (event) {
298 if (event.which === 1) {
299 event.preventDefault(); // Prevent options from being "dragged"
300 if (event.screenX === options.data('selectBox-down-at-x') &&
301 event.screenY === options.data('selectBox-down-at-y')) {
302 options.removeData('selectBox-down-at-x').removeData('selectBox-down-at-y');
303 self.hideMenus();
304 }
305 }
306 })
307 .bind('mouseup.selectBox', function (event) {
308 if (1 !== event.which) {
309 return;
310 }
311 if (event.screenX === options.data('selectBox-down-at-x') &&
312 event.screenY === options.data('selectBox-down-at-y')) {
313 return;
314 } else {
315 options.removeData('selectBox-down-at-x').removeData('selectBox-down-at-y');
316 }
317 self.selectOption($(this).parent());
318 self.hideMenus();
319 })
320 .bind('mouseover.selectBox', function (event) {
321 self.addHover($(this).parent());
322 })
323 .bind('mouseout.selectBox', function (event) {
324 self.removeHover($(this).parent());
325 });
326
327 // Inherit classes for dropdown menu
328 var classes = select.attr('class') || '';
329 if ('' !== classes) {
330 classes = classes.split(' ');
331 for (var i in classes) {
332 options.addClass(classes[i] + '-selectBox-dropdown-menu');
333 }
334 }
335 this.disableSelection(options);
336 return options;
337 }
338 };
339
340 /**
341 * Returns the current class of the selected option.
342 *
343 * @returns {String}
344 */
345 SelectBox.prototype.getLabelClass = function () {
346 var selected = $(this.selectElement).find('OPTION:selected');
347 return ('selectBox-label ' + (selected.attr('class') || '')).replace(/\s+$/, '');
348 };
349
350 /**
351 * Returns the current label of the selected option.
352 *
353 * @returns {String}
354 */
355 SelectBox.prototype.getLabelText = function () {
356 var selected = $(this.selectElement).find('OPTION:selected');
357 return selected.text() || '\u00A0';
358 };
359
360 /**
361 * Sets the label.
362 * This method uses the getLabelClass() and getLabelText() methods.
363 */
364 SelectBox.prototype.setLabel = function () {
365 var select = $(this.selectElement);
366 var control = select.data('selectBox-control');
367 if (!control) {
368 return;
369 }
370
371 control
372 .find('.selectBox-label')
373 .attr('class', this.getLabelClass())
374 .text(this.getLabelText());
375 };
376
377 /**
378 * Destroys the SelectBox instance and shows the origin select element.
379 *
380 */
381 SelectBox.prototype.destroy = function () {
382 var select = $(this.selectElement);
383 var control = select.data('selectBox-control');
384 if (!control) {
385 return;
386 }
387
388 var options = control.data('selectBox-options');
389 options.remove();
390 control.remove();
391 select
392 .removeClass('selectBox')
393 .removeData('selectBox-control')
394 .data('selectBox-control', null)
395 .removeData('selectBox-settings')
396 .data('selectBox-settings', null)
397 .show();
398 };
399
400 /**
401 * Refreshes the option elements.
402 */
403 SelectBox.prototype.refresh = function () {
404 var select = $(this.selectElement),
405 control = select.data('selectBox-control'),
406 dropdown = control.hasClass('selectBox-dropdown'),
407 menuOpened = control.hasClass('selectBox-menuShowing');
408 select.selectBox('options', select.html());
409 // Restore opened dropdown state (original menu was trashed)
410 if (dropdown && menuOpened) {
411 this.showMenu();
412 }
413 };
414
415 /**
416 * Shows the dropdown menu.
417 */
418 SelectBox.prototype.showMenu = function () {
419 var self = this
420 , select = $(this.selectElement)
421 , control = select.data('selectBox-control')
422 , settings = select.data('selectBox-settings')
423 , options = control.data('selectBox-options');
424
425 if (control.hasClass('selectBox-disabled')) {
426 return false;
427 }
428
429 this.hideMenus();
430 var borderBottomWidth = parseInt(control.css('borderBottomWidth')) || 0;
431
432 // Menu position
433 options
434 .width(control.innerWidth())
435 .css({
436 top: control.offset().top + control.outerHeight() - borderBottomWidth,
437 left: control.offset().left
438 });
439
440
441 if (select.triggerHandler('beforeopen')) {
442 return false;
443 }
444
445 var dispatchOpenEvent = function () {
446 select.triggerHandler('open', {
447 _selectBox: true
448 });
449 };
450
451 // Show menu
452 switch (settings.menuTransition) {
453 case 'fade':
454 options.fadeIn(settings.menuSpeed, dispatchOpenEvent);
455 break;
456 case 'slide':
457 options.slideDown(settings.menuSpeed, dispatchOpenEvent);
458 break;
459 default:
460 options.show(settings.menuSpeed, dispatchOpenEvent);
461 break;
462 }
463
464 if (!settings.menuSpeed) {
465 dispatchOpenEvent();
466 }
467
468 // Center on selected option
469 var li = options.find('.selectBox-selected:first');
470 this.keepOptionInView(li, true);
471 this.addHover(li);
472 control.addClass('selectBox-menuShowing');
473
474 $(document).bind('mousedown.selectBox', function (event) {
475 if (1 === event.which) {
476 if ($(event.target).parents().andSelf().hasClass('selectBox-options')) {
477 return;
478 }
479 self.hideMenus();
480 }
481 });
482 };
483
484 /**
485 * Hides the menu of all instances.
486 */
487 SelectBox.prototype.hideMenus = function () {
488 if ($(".selectBox-dropdown-menu:visible").length === 0) {
489 return;
490 }
491
492 $(document).unbind('mousedown.selectBox');
493 $(".selectBox-dropdown-menu").each(function () {
494 var options = $(this)
495 , select = options.data('selectBox-select')
496 , control = select.data('selectBox-control')
497 , settings = select.data('selectBox-settings');
498
499 if (select.triggerHandler('beforeclose')) {
500 return false;
501 }
502
503 var dispatchCloseEvent = function () {
504 select.triggerHandler('close', {
505 _selectBox: true
506 });
507 };
508
509 if (settings) {
510 switch (settings.menuTransition) {
511 case 'fade':
512 options.fadeOut(settings.menuSpeed, dispatchCloseEvent);
513 break;
514 case 'slide':
515 options.slideUp(settings.menuSpeed, dispatchCloseEvent);
516 break;
517 default:
518 options.hide(settings.menuSpeed, dispatchCloseEvent);
519 break;
520 }
521 if (!settings.menuSpeed) {
522 dispatchCloseEvent();
523 }
524 control.removeClass('selectBox-menuShowing');
525 } else {
526 $(this).hide();
527 $(this).triggerHandler('close', {
528 _selectBox: true
529 });
530 $(this).removeClass('selectBox-menuShowing');
531 }
532 });
533 };
534
535 /**
536 * Selects an option.
537 *
538 * @param {HTMLElement} li
539 * @param {DOMEvent} event
540 * @returns {Boolean}
541 */
542 SelectBox.prototype.selectOption = function (li, event) {
543 var select = $(this.selectElement);
544 li = $(li);
545
546 var control = select.data('selectBox-control')
547 , settings = select.data('selectBox-settings');
548
549 if (control.hasClass('selectBox-disabled')) {
550 return false;
551 }
552
553 if (0 === li.length || li.hasClass('selectBox-disabled')) {
554 return false;
555 }
556
557 if (select.attr('multiple')) {
558 // If event.shiftKey is true, this will select all options between li and the last li selected
559 if (event.shiftKey && control.data('selectBox-last-selected')) {
560 li.toggleClass('selectBox-selected');
561 var affectedOptions;
562 if (li.index() > control.data('selectBox-last-selected').index()) {
563 affectedOptions = li
564 .siblings()
565 .slice(control.data('selectBox-last-selected').index(), li.index());
566 } else {
567 affectedOptions = li
568 .siblings()
569 .slice(li.index(), control.data('selectBox-last-selected').index());
570 }
571 affectedOptions = affectedOptions.not('.selectBox-optgroup, .selectBox-disabled');
572 if (li.hasClass('selectBox-selected')) {
573 affectedOptions.addClass('selectBox-selected');
574 } else {
575 affectedOptions.removeClass('selectBox-selected');
576 }
577 } else if ((this.isMac && event.metaKey) || (!this.isMac && event.ctrlKey)) {
578 li.toggleClass('selectBox-selected');
579 } else {
580 li.siblings().removeClass('selectBox-selected');
581 li.addClass('selectBox-selected');
582 }
583 } else {
584 li.siblings().removeClass('selectBox-selected');
585 li.addClass('selectBox-selected');
586 }
587
588 if (control.hasClass('selectBox-dropdown')) {
589 control.find('.selectBox-label').text(li.text());
590 }
591
592 // Update original control's value
593 var i = 0, selection = [];
594 if (select.attr('multiple')) {
595 control.find('.selectBox-selected A').each(function () {
596 selection[i++] = $(this).attr('rel');
597 });
598 } else {
599 selection = li.find('A').attr('rel');
600 }
601
602 // Remember most recently selected item
603 control.data('selectBox-last-selected', li);
604
605 // Change callback
606 if (select.val() !== selection) {
607 select.val(selection);
608 this.setLabel();
609 select.trigger('change');
610 }
611
612 return true;
613 };
614
615 /**
616 * Adds the hover class.
617 *
618 * @param {HTMLElement} li
619 */
620 SelectBox.prototype.addHover = function (li) {
621 li = $(li);
622 var select = $(this.selectElement)
623 , control = select.data('selectBox-control')
624 , options = control.data('selectBox-options');
625
626 options.find('.selectBox-hover').removeClass('selectBox-hover');
627 li.addClass('selectBox-hover');
628 };
629
630 /**
631 * Returns the original HTML select element.
632 *
633 * @returns {HTMLElement}
634 */
635 SelectBox.prototype.getSelectElement = function () {
636 return this.selectElement;
637 };
638
639 /**
640 * Remove the hover class.
641 *
642 * @param {HTMLElement} li
643 */
644 SelectBox.prototype.removeHover = function (li) {
645 li = $(li);
646 var select = $(this.selectElement)
647 , control = select.data('selectBox-control')
648 , options = control.data('selectBox-options');
649
650 options.find('.selectBox-hover').removeClass('selectBox-hover');
651 };
652
653 /**
654 * Checks if the widget is in the view.
655 *
656 * @param {jQuery} li
657 * @param {Boolean} center
658 */
659 SelectBox.prototype.keepOptionInView = function (li, center) {
660 if (!li || li.length === 0) {
661 return;
662 }
663
664 var select = $(this.selectElement)
665 , control = select.data('selectBox-control')
666 , options = control.data('selectBox-options')
667 , scrollBox = control.hasClass('selectBox-dropdown') ? options : options.parent()
668 , top = parseInt(li.offset().top -scrollBox.position().top)
669 , bottom = parseInt(top + li.outerHeight());
670
671 if (center) {
672 scrollBox.scrollTop(li.offset().top - scrollBox.offset().top + scrollBox.scrollTop() -
673 (scrollBox.height() / 2));
674 } else {
675 if (top < 0) {
676 scrollBox.scrollTop(li.offset().top - scrollBox.offset().top + scrollBox.scrollTop());
677 }
678 if (bottom > scrollBox.height()) {
679 scrollBox.scrollTop((li.offset().top + li.outerHeight()) - scrollBox.offset().top +
680 scrollBox.scrollTop() - scrollBox.height());
681 }
682 }
683 };
684
685 /**
686 * Handles the keyDown event.
687 * Handles open/close and arrow key functionality
688 *
689 * @param {DOMEvent} event
690 */
691 SelectBox.prototype.handleKeyDown = function (event) {
692 var select = $(this.selectElement)
693 , control = select.data('selectBox-control')
694 , options = control.data('selectBox-options')
695 , settings = select.data('selectBox-settings')
696 , totalOptions = 0, i = 0;
697
698 if (control.hasClass('selectBox-disabled')) {
699 return;
700 }
701
702 switch (event.keyCode) {
703 case 8:
704 // backspace
705 event.preventDefault();
706 this.typeSearch = '';
707 break;
708 case 9:
709 // tab
710 case 27:
711 // esc
712 this.hideMenus();
713 this.removeHover();
714 break;
715 case 13:
716 // enter
717 if (control.hasClass('selectBox-menuShowing')) {
718 this.selectOption(options.find('LI.selectBox-hover:first'), event);
719 if (control.hasClass('selectBox-dropdown')) {
720 this.hideMenus();
721 }
722 } else {
723 this.showMenu();
724 }
725 break;
726 case 38:
727 // up
728 case 37:
729 // left
730 event.preventDefault();
731 if (control.hasClass('selectBox-menuShowing')) {
732 var prev = options.find('.selectBox-hover').prev('LI');
733 totalOptions = options.find('LI:not(.selectBox-optgroup)').length;
734 i = 0;
735 while (prev.length === 0 || prev.hasClass('selectBox-disabled') ||
736 prev.hasClass('selectBox-optgroup')) {
737 prev = prev.prev('LI');
738 if (prev.length === 0) {
739 if (settings.loopOptions) {
740 prev = options.find('LI:last');
741 } else {
742 prev = options.find('LI:first');
743 }
744 }
745 if (++i >= totalOptions) {
746 break;
747 }
748 }
749 this.addHover(prev);
750 this.selectOption(prev, event);
751 this.keepOptionInView(prev);
752 } else {
753 this.showMenu();
754 }
755 break;
756 case 40:
757 // down
758 case 39:
759 // right
760 event.preventDefault();
761 if (control.hasClass('selectBox-menuShowing')) {
762 var next = options.find('.selectBox-hover').next('LI');
763 totalOptions = options.find('LI:not(.selectBox-optgroup)').length;
764 i = 0;
765 while (0 === next.length || next.hasClass('selectBox-disabled') ||
766 next.hasClass('selectBox-optgroup')) {
767 next = next.next('LI');
768 if (next.length === 0) {
769 if (settings.loopOptions) {
770 next = options.find('LI:first');
771 } else {
772 next = options.find('LI:last');
773 }
774 }
775 if (++i >= totalOptions) {
776 break;
777 }
778 }
779 this.addHover(next);
780 this.selectOption(next, event);
781 this.keepOptionInView(next);
782 } else {
783 this.showMenu();
784 }
785 break;
786 }
787 };
788
789 /**
790 * Handles the keyPress event.
791 * Handles type-to-find functionality
792 *
793 * @param {DOMEvent} event
794 */
795 SelectBox.prototype.handleKeyPress = function (event) {
796 var select = $(this.selectElement)
797 , control = select.data('selectBox-control')
798 , options = control.data('selectBox-options');
799
800 if (control.hasClass('selectBox-disabled')) {
801 return;
802 }
803
804 switch (event.keyCode) {
805 case 9:
806 // tab
807 case 27:
808 // esc
809 case 13:
810 // enter
811 case 38:
812 // up
813 case 37:
814 // left
815 case 40:
816 // down
817 case 39:
818 // right
819 // Don't interfere with the keydown event!
820 break;
821 default:
822 // Type to find
823 if (!control.hasClass('selectBox-menuShowing')) {
824 this.showMenu();
825 }
826 event.preventDefault();
827 clearTimeout(this.typeTimer);
828 this.typeSearch += String.fromCharCode(event.charCode || event.keyCode);
829 options.find('A').each(function () {
830 if ($(this).text().substr(0, this.typeSearch.length).toLowerCase() === this.typeSearch.toLowerCase()) {
831 this.addHover($(this).parent());
832 this.selectOption($(this).parent(), event);
833 this.keepOptionInView($(this).parent());
834 return false;
835 }
836 });
837 // Clear after a brief pause
838 this.typeTimer = setTimeout(function () {
839 this.typeSearch = '';
840 }, 1000);
841 break;
842 }
843 };
844
845 /**
846 * Enables the selectBox.
847 */
848 SelectBox.prototype.enable = function () {
849 var select = $(this.selectElement);
850 select.prop('disabled', false);
851 var control = select.data('selectBox-control');
852 if (!control) {
853 return;
854 }
855 control.removeClass('selectBox-disabled');
856 };
857
858 /**
859 * Disables the selectBox.
860 */
861 SelectBox.prototype.disable = function () {
862 var select = $(this.selectElement);
863 select.prop('disabled', true);
864 var control = select.data('selectBox-control');
865 if (!control) {
866 return;
867 }
868 control.addClass('selectBox-disabled');
869 };
870
871 /**
872 * Sets the current value.
873 *
874 * @param {String} value
875 */
876 SelectBox.prototype.setValue = function (value) {
877 var select = $(this.selectElement);
878 select.val(value);
879 value = select.val(); // IE9's select would be null if it was set with a non-exist options value
880
881 if (null === value) { // So check it here and set it with the first option's value if possible
882 value = select.children().first().val();
883 select.val(value);
884 }
885
886 var control = select.data('selectBox-control');
887 if (!control) {
888 return;
889 }
890
891 var settings = select.data('selectBox-settings')
892 , options = control.data('selectBox-options');
893
894 // Update label
895 this.setLabel();
896
897 // Update control values
898 options.find('.selectBox-selected').removeClass('selectBox-selected');
899 options.find('A').each(function () {
900 if (typeof(value) === 'object') {
901 for (var i = 0; i < value.length; i++) {
902 if ($(this).attr('rel') == value[i]) {
903 $(this).parent().addClass('selectBox-selected');
904 }
905 }
906 } else {
907 if ($(this).attr('rel') == value) {
908 $(this).parent().addClass('selectBox-selected');
909 }
910 }
911 });
912
913 if (settings.change) {
914 settings.change.call(select);
915 }
916 };
917
918 /**
919 * Sets the option elements.
920 *
921 * @param {String|Object} options
922 */
923 SelectBox.prototype.setOptions = function (options) {
924 var select = $(this.selectElement)
925 , control = select.data('selectBox-control')
926 , settings = select.data('selectBox-settings')
927 , type;
928
929 switch (typeof(options)) {
930 case 'string':
931 select.html(options);
932 break;
933 case 'object':
934 select.html('');
935 for (var i in options) {
936 if (options[i] === null) {
937 continue;
938 }
939 if (typeof(options[i]) === 'object') {
940 var optgroup = $('<optgroup label="' + i + '" />');
941 for (var j in options[i]) {
942 optgroup.append('<option value="' + j + '">' + options[i][j] + '</option>');
943 }
944 select.append(optgroup);
945 } else {
946 var option = $('<option value="' + i + '">' + options[i] + '</option>');
947 select.append(option);
948 }
949 }
950 break;
951 }
952
953 if (!control) {
954 return;
955 }
956
957 // Remove old options
958 control.data('selectBox-options').remove();
959
960 // Generate new options
961 type = control.hasClass('selectBox-dropdown') ? 'dropdown' : 'inline';
962 options = this.getOptions(type);
963 control.data('selectBox-options', options);
964
965 switch (type) {
966 case 'inline':
967 control.append(options);
968 break;
969 case 'dropdown':
970 // Update label
971 this.setLabel();
972 $("BODY").append(options);
973 break;
974 }
975 };
976
977 /**
978 * Disables the selection.
979 *
980 * @param {*} selector
981 */
982 SelectBox.prototype.disableSelection = function (selector) {
983 $(selector).css('MozUserSelect', 'none').bind('selectstart', function (event) {
984 event.preventDefault();
985 });
986 };
987
988 /**
989 * Generates the options.
990 *
991 * @param {jQuery} self
992 * @param {jQuery} options
993 */
994 SelectBox.prototype.generateOptions = function (self, options) {
995 var li = $('<li />'), a = $('<a />');
996 li.addClass(self.attr('class'));
997 li.data(self.data());
998 a.attr('rel', self.val()).text(self.text());
999 li.append(a);
1000 if (self.attr('disabled')) {
1001 li.addClass('selectBox-disabled');
1002 }
1003 if (self.attr('selected')) {
1004 li.addClass('selectBox-selected');
1005 }
1006 options.append(li);
1007 };
1008
1009 /**
1010 * Extends the jQuery.fn object.
1011 */
1012 $.extend($.fn, {
1013 selectBox: function (method, options) {
1014 var selectBox;
1015
1016 switch (method) {
1017 case 'control':
1018 return $(this).data('selectBox-control');
1019 case 'settings':
1020 if (!options) {
1021 return $(this).data('selectBox-settings');
1022 }
1023 $(this).each(function () {
1024 $(this).data('selectBox-settings', $.extend(true, $(this).data('selectBox-settings'), options));
1025 });
1026 break;
1027 case 'options':
1028 // Getter
1029 if (undefined === options) {
1030 return $(this).data('selectBox-control').data('selectBox-options');
1031 }
1032 // Setter
1033 $(this).each(function () {
1034 if (selectBox = $(this).data('selectBox')) {
1035 selectBox.setOptions(options);
1036 }
1037 });
1038 break;
1039 case 'value':
1040 // Empty string is a valid value
1041 if (undefined === options) {
1042 return $(this).val();
1043 }
1044 $(this).each(function () {
1045 if (selectBox = $(this).data('selectBox')) {
1046 selectBox.setValue(options);
1047 }
1048 });
1049 break;
1050 case 'refresh':
1051 $(this).each(function () {
1052 if (selectBox = $(this).data('selectBox')) {
1053 selectBox.refresh();
1054 }
1055 });
1056 break;
1057 case 'enable':
1058 $(this).each(function () {
1059 if (selectBox = $(this).data('selectBox')) {
1060 selectBox.enable(this);
1061 }
1062 });
1063 break;
1064 case 'disable':
1065 $(this).each(function () {
1066 if (selectBox = $(this).data('selectBox')) {
1067 selectBox.disable();
1068 }
1069 });
1070 break;
1071 case 'destroy':
1072 $(this).each(function () {
1073 if (selectBox = $(this).data('selectBox')) {
1074 selectBox.destroy();
1075 $(this).data('selectBox', null);
1076 }
1077 });
1078 break;
1079 case 'instance':
1080 return $(this).data('selectBox');
1081 default:
1082 $(this).each(function (idx, select) {
1083 if (!$(select).data('selectBox')) {
1084 $(select).data('selectBox', new SelectBox(select, method));
1085 }
1086 });
1087 break;
1088 }
1089 return $(this);
1090 }
1091 });
1092 })(jQuery);