PageSourceSearch

https://booksrus.pl/local/templates/aspro_max/js/jquery.ikSelect.js?161435193832030

js booksrus.pl collected 2026-09-30 02:35:55 UTC 32,030 bytes, 1,067 lines download raw bytes

1/*! ikSelect 1.0.3
2	Copyright (c) 2013 Igor Kozlov
3	http://igorkozlov.me */
4
5;(function ($, window, document, undefined) {
6	var $window = $(window);
7	var defaults = {
8		syntax: '<div class="ik_select_link"><div class="ik_select_link_text"></div></div><div class="ik_select_dropdown"><div class="ik_select_list"></div></div>',
9		autoWidth: true, // set select width according to the longest option
10		ddFullWidth: true, // set dropdown width according to the longest option
11		equalWidths: true, // include scrollbar width in fake select calculations
12		dynamicWidth: false, // change fake select's width according to it's contents
13		extractLink: false,
14		customClass: '',
15		linkCustomClass: '',
16		ddCustomClass: '',
17		ddMaxHeight: 200,
18		filter: false,
19		nothingFoundText: 'Nothing found',
20		isDisabled: false,
21		onInit: function() {},
22		onShow: function () {},
23		onHide: function () {},
24		onKeyUp: function () {},
25		onKeyDown: function () {},
26		onHoverMove: function () {}
27	};
28
29	var instOpened; // instance of the currently opened select
30
31	// browser detection part was taken from jQuery migrate
32	// https://github.com/jquery/jquery-migrate/blob/e6bda6a84c294eb1319fceb48c09f51042c80892/src/core.js
33	var uaMatch = function (ua) {
34		ua = ua.toLowerCase();
35
36		var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
37			/(webkit)[ \/]([\w.]+)/.exec(ua) ||
38			/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
39			/(msie) ([\w.]+)/.exec(ua) ||
40			ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
41			[];
42
43		return {
44			browser: match[1] || '',
45			version: match[2] || '0'
46		};
47	};
48
49	if (! $.browser) {
50		var matched = uaMatch(navigator.userAgent);
51		var browser = {};
52
53		if (matched.browser) {
54			browser[matched.browser] = true;
55			browser.version = matched.version;
56		}
57
58		if (browser.chrome) {
59			browser.webkit = true;
60		} else if (browser.webkit) {
61			browser.safari = true;
62		}
63
64		$.browser = browser;
65	}
66
67	$.browser.mobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile/i.test(navigator.userAgent);
68	$.browser.operamini = Object.prototype.toString.call(window.operamini) === "[object OperaMini]";
69
70	function IkSelect(element, options) {
71		var dataOptions = {}; // parsed data- attributes
72
73		this.el = element;
74		this.$el = $(element); // original select
75
76		for (var key in defaults) {
77			dataOptions[key] = this.$el.data(key.toLowerCase());
78		}
79
80		this.options = $.extend({}, defaults, options, dataOptions);
81
82		if ($.browser.mobile) {
83			this.options.filter = false;
84		}
85
86		this.init();
87	}
88
89	$.extend(IkSelect.prototype, {
90		init: function () {
91			this.$wrapper = $('<div class="ik_select">' + this.options.syntax + '</div>'); // wrapper for the fake select and the fake dropdown
92			this.$link = $('.ik_select_link', this.$wrapper); // fake select
93			this.$linkText = $('.ik_select_link_text', this.$wrapper); // fake select's text
94			this.$dropdown = $('.ik_select_dropdown', this.$wrapper); // fake dropdown
95			this.$list = $('.ik_select_list', this.$wrapper); // options list inside the fake dropdown
96			this.$listInner = $('<div class="ik_select_list_inner"/>'); // support dropdown for scrolling
97			this.$active = $([]); // active fake option
98			this.$hover = $([]); // hovered fake option
99			this.hoverIndex = 0; // hovered fake option's index
100
101			this.$optionSet = $([]);
102			this.$optgroupSet = $([]);
103
104			this.$list.append(this.$listInner);
105
106			if (this.options.filter) {
107				this.$filter = $([]); // filter text input
108				this.$optionSetOriginal = $([]); // contains original list items when filtering
109				this.$nothingFoundText = $('<div class="ik_select_nothing_found"/>').html(this.options.nothingFoundText);
110				this.$filterWrap = $('.ik_select_filter_wrap', this.$wrapper);
111
112				if (! this.$filterWrap.length) {
113					this.$filterWrap = $('<div class="ik_select_filter_wrap"/>');
114				}
115
116				this.$filter = $('<input type="text" class="ik_select_filter">');
117
118				this.$filterWrap.append(this.$filter);
119				this.$list.prepend(this.$filterWrap);
120
121				this.$filter.on({
122					// keyboard controls should work even if the filter is in focus
123					'keydown.ikSelect keyup.ikSelect': $.proxy(this, '_elKeyUpDown'),
124					// actual filtering happens on keyup
125					'keyup.ikSelect': $.proxy(this, '_filterKeyup')
126				});
127			}
128
129			this.$wrapper.addClass(this.options.customClass);
130			this.$link.addClass(this.options.linkCustomClass || (this.options.customClass && this.options.customClass + '-link'));
131			this.$dropdown.addClass(this.options.ddCustomClass || (this.options.customClass && this.options.customClass + '-dd'));
132
133			// creating fake option list
134			this.reset();
135
136			// disable select if an option or attribute are truthy
137			this.toggle(!(this.options.isDisabled || this.$el.prop('disabled') || this.$el.hasClass('hidden')));
138
139			// click event for fake select
140			this.$link.on('click.ikSelect', $.proxy(this, '_linkClick'));
141
142			this.$el.on({
143				// when focus is on the original select add a focus class to the fake one
144				'focus.ikSelect': $.proxy(this, '_elFocus'),
145				// when focus lost remove the focus class from the fake one
146				'blur.ikSelect': $.proxy(this, '_elBlur'),
147				// make sure that the fake select shows correct data
148				'change.ikSelect': $.proxy(this, '_syncOriginalOption'),
149				// keyboard controls for the fake select
150				'keydown.ikSelect keyup.ikSelect': $.proxy(this, '_elKeyUpDown')
151			});
152
153			this.$list.on({
154				'click.ikSelect': $.proxy(this, '_optionClick'),
155				'mouseover.ikSelect': $.proxy(this, '_optionMouseover')
156			}, '.ik_select_option');
157
158			// stop propagation of click events on the wrapper
159			this.$wrapper.on('click', function () {
160				return false;
161			});
162
163			// appending the fake select right after the original one
164			this.$el.after(this.$wrapper);
165
166			// set correct dimensions
167			this.redraw();
168
169			// move original select inside the wrapper
170			this.$el.appendTo(this.$wrapper);
171
172			this.options.onInit(this);
173			this.$el.trigger('ikinit', this);
174		},
175
176		// click listener for fake select
177		_linkClick: function () {
178			if (this.isDisabled) {
179				return;
180			}
181			if (this === instOpened) {
182				this.hideDropdown();
183			} else {
184				this.showDropdown();
185			}
186
187		},
188
189		// click listener for the fake options
190		_optionClick: function () {
191			this._makeOptionActive(this.searchIndexes ? this.$optionSetOriginal.index(this.$hover) : this.hoverIndex, true);
192			this.hideDropdown();
193			this.$el.change().focus();
194		},
195
196		// hover listener for the fake options
197		_optionMouseover: function (event) {
198			var $option = $(event.currentTarget);
199			if ($option.hasClass('ik_select_option_disabled')) {
200				return;
201			}
202			this.$hover.removeClass('ik_select_hover');
203			this.$hover = $option.addClass('ik_select_hover');
204			this.hoverIndex = this.$optionSet.index(this.$hover);
205		},
206
207		// makes fake option active without syncing the original select
208		_makeOptionActive: function (index, shouldSync) {
209			var $option = $(this.el.options[index]),
210				text='';
211			if($option.data('img_src')){
212				text+='<span class="icon_color" style="background: url('+$option.data('img_src')+')"></span>';
213				this.$link.addClass('img');
214			}
215			if($option.attr('title')){
216				this.$link.attr('title', $option.attr('title'));
217			}
218			text+=$option.text();
219			this.$linkText.html(text);
220
221			this.$link.toggleClass('ik_select_link_novalue', !$option.attr('value'));
222
223			this.$hover.removeClass('ik_select_hover');
224			this.$active.removeClass('ik_select_active');
225			this.$hover = this.$active = this.$optionSet.eq(index).addClass('ik_select_hover ik_select_active');
226			this.hoverIndex = index;
227
228			if (shouldSync) {
229				this._syncFakeOption();
230			}
231		},
232
233		// keyboard controls for the fake select
234		_elKeyUpDown: function (event) {
235			var $handle = $(event.currentTarget);
236			var type = event.type;
237			var keycode = event.which;
238			var newTop;
239
240			switch (keycode) {
241			case 38: // up
242				if (type === 'keydown') {
243					event.preventDefault();
244					this._moveToPrevActive();
245				}
246				break;
247			case 40: // down
248				if (type === 'keydown') {
249					event.preventDefault();
250					this._moveToNextActive();
251				}
252				break;
253			case 33: // page up
254				if (type === 'keydown') {
255					event.preventDefault();
256					newTop = this.$hover.position().top - this.$listInner.height();
257					this._moveToPrevActive(function (optionTop) {
258						return optionTop <= newTop;
259					});
260				}
261				break;
262			case 34: // page down
263				if (type === 'keydown') {
264					event.preventDefault();
265					newTop = this.$hover.position().top + this.$listInner.height();
266					this._moveToNextActive(function (optionTop) {
267						return optionTop >= newTop;
268					});
269				}
270				break;
271			case 36: // home
272				if (type === 'keydown' && $handle.is(this.$el)) {
273					event.preventDefault();
274					this._moveToFirstActive();
275				}
276				break;
277			case 35: // end
278				if (type === 'keydown' && $handle.is(this.$el)) {
279					event.preventDefault();
280					this._moveToLastActive();
281				}
282				break;
283			case 32: // space
284				if (type === 'keydown' && $handle.is(this.$el)) {
285					event.preventDefault();
286					if (! this.$dropdown.is(':visible')) {
287						this._linkClick();
288					} else {
289						this.$hover.click();
290					}
291				}
292				break;
293			case 13: // enter
294				if (type === 'keydown' && this.$dropdown.is(':visible')) {
295					event.preventDefault();
296					this.$hover.click();
297				}
298				break;
299			case 27: // esc
300				if (type === 'keydown' && this.$dropdown.is(':visible')) {
301					event.preventDefault();
302					this.hideDropdown();
303				}
304				break;
305			case 9: // tab
306				if (type === 'keydown') {
307					if ($.browser.webkit && this.$dropdown.is(':visible')) {
308						event.preventDefault();
309					} else {
310						this.hideDropdown();
311					}
312				}
313				break;
314			default:
315				if (type === 'keyup' && $handle.is(this.$el)) {
316					this._syncOriginalOption();
317				}
318				break;
319			}
320
321			// mozilla ignores preventDefault for select navigation
322			// this ensures that original select is in sync
323			if (type === 'keyup' && $.browser.mozilla) {
324				this._syncFakeOption();
325			}
326
327			if (type === 'keydown') {
328				this.options.onKeyDown(this, keycode);
329				this.$el.trigger('ikkeydown', [this, keycode]);
330			}
331			if (type === 'keyup') {
332				this.options.onKeyUp(this, keycode);
333				this.$el.trigger('ikkeyup', [this, keycode]);
334			}
335		},
336
337		// controls hover/active states for options and makes selected with keyboard options fully visible
338		_moveTo: function (index) {
339			var optionTopLine, optionBottomLine;
340			var $optgroup;
341
342			if (!this.$dropdown.is(':visible') && $.browser.webkit) {
343				this.showDropdown();
344				return this;
345			}
346
347			if (!this.$dropdown.is(':visible') || $.browser.mozilla) {
348				this._makeOptionActive(index, true);
349			} else {
350				this.$hover.removeClass('ik_select_hover');
351				this.$hover = this.$optionSet.eq(index).addClass('ik_select_hover');
352				this.hoverIndex = index;
353			}
354
355			// make option fully visible
356			optionTopLine = this.$hover.position().top;
357			optionBottomLine = optionTopLine + this.$active.outerHeight();
358			// make optgroup label visible if first option witin this optgroup is hovered
359			if (!this.$hover.index()) {
360				$optgroup = this.$hover.closest('.ik_select_optgroup');
361				if ($optgroup.length) {
362					optionTopLine = $optgroup.position().top;
363				}
364			}
365			if (optionBottomLine > this.$listInner.height()) {
366				this.$listInner.scrollTop(this.$listInner.scrollTop() + optionBottomLine - this.$listInner.height());
367			} else if (optionTopLine < 0) {
368				this.$listInner.scrollTop(this.$listInner.scrollTop() + optionTopLine);
369			}
370
371			this.options.onHoverMove(this);
372			this.$el.trigger('ikhovermove', this);
373		},
374
375		_moveToFirstActive: function () {
376			for (var i = 0; i < this.$optionSet.length; i++) {
377				if (!this.$optionSet.eq(i).hasClass('ik_select_option_disabled')) {
378					this._moveTo(i);
379					break;
380				}
381			}
382		},
383
384		_moveToLastActive: function () {
385			for (var i = this.$optionSet.length - 1; i >= 0; i++) {
386				if (!this.$optionSet.eq(i).hasClass('ik_select_option_disabled')) {
387					this._moveTo(i);
388					break;
389				}
390			}
391		},
392
393		_moveToPrevActive: function (condition) {
394			var $option;
395			for (var i = this.hoverIndex - 1; i >= 0; i--) {
396				$option = this.$optionSet.eq(i);
397				if (!$option.hasClass('ik_select_option_disabled') && (typeof condition === 'undefined' || condition($option.position().top))) {
398					this._moveTo(i);
399					break;
400				}
401			}
402		},
403
404		_moveToNextActive: function (condition) {
405			var $option;
406			for (var i = this.hoverIndex + 1; i < this.$optionSet.length; i++) {
407				$option = this.$optionSet.eq(i);
408				if (!$option.hasClass('ik_select_option_disabled') && (typeof condition === 'undefined' || condition($option.position().top))) {
409					this._moveTo(i);
410					break;
411				}
412			}
413		},
414
415		// when focus is on the original select add a focus class to the fake one
416		_elFocus:  function () {
417			var wrapperOffsetTop, wrapperHeight, windowScrollTop, windowHeight;
418			if (this.isDisabled) {
419				return this;
420			}
421			this.$link.addClass('ik_select_link_focus');
422
423			// scroll the window so that focused select is visible
424			wrapperOffsetTop = this.$wrapper.offset().top;
425			wrapperHeight = this.$wrapper.height();
426			windowScrollTop = $window.scrollTop();
427			windowHeight = $window.height();
428			if ((wrapperOffsetTop + wrapperHeight > windowScrollTop + windowHeight) ||
429				(wrapperOffsetTop < windowScrollTop)) {
430				$window.scrollTop(wrapperOffsetTop - windowHeight / 2);
431			}
432		},
433
434		// when focus lost remove the focus class from the fake one
435		_elBlur: function () {
436			this.$link.removeClass('ik_select_link_focus');
437		},
438
439		// filtering on key up
440		_filterKeyup: function () {
441			var filterVal = $.trim(this.$filter.val());
442			var filterValOld;
443			this.$listInner.show();
444
445			if (typeof this.searchIndexes === 'undefined') {
446				this.$optionSetOriginal = this.$optionSet;
447				this.searchIndexes = $.makeArray(this.$optionSet.map(function (optionIndex, option) {
448					return $(option).text().toLowerCase();
449				}));
450			}
451
452			if (filterVal !== filterValOld) {
453				if (filterVal === '') {
454					this.$optionSet = this.$optionSetOriginal.show();
455					this.$optgroupSet.show();
456					this.$nothingFoundText.remove();
457				} else {
458					this.$optionSet = $([]);
459					this.$optgroupSet.show();
460					this.$optionSetOriginal.each($.proxy(function (optionIndex, option) {
461						var $option = $(option);
462						if (this.searchIndexes[optionIndex].indexOf(filterVal.toLowerCase()) >= 0) {
463							this.$optionSet = this.$optionSet.add($option);
464							$option.show();
465						} else {
466							$option.hide();
467						}
468					}, this));
469
470					if (this.$optionSet.length) {
471						this.$nothingFoundText.remove();
472						this.$optgroupSet.each(function (optgroupIndex, optgroup) {
473							var $optgroup = $(optgroup);
474							if (!$('.ik_select_option:visible', $optgroup).length) {
475								$optgroup.hide();
476							}
477						});
478
479						if (!this.$hover.is(':visible')) {
480							this._moveToFirstActive();
481						}
482					} else {
483						this.$listInner.hide();
484						this.$list.append(this.$nothingFoundText);
485					}
486				}
487
488				filterValOld = filterVal;
489			}
490		},
491
492		// sync selected option in the fake select with the original one
493		_syncFakeOption: function () {
494			this.el.selectedIndex = this.hoverIndex;
495		},
496
497		// sync selected option in the original select with the fake one
498		_syncOriginalOption: function () {
499			this._makeOptionActive(this.el.selectedIndex);
500		},
501
502		// sets fixed height to dropdown if it's bigger than ddMaxHeight
503		_fixHeight: function () {
504			this.$dropdown.show();
505			this.$listInner.css('height', 'auto');
506			if (this.$listInner.height() > this.options.ddMaxHeight) {
507				this.$listInner.css({
508					overflow: 'auto',
509					height: this.options.ddMaxHeight,
510					position: 'relative'
511				});
512			}
513			this.$dropdown.hide();
514		},
515
516		// calculates the needed data for showing the dropdown
517		redraw: function () {
518			var maxWidthOuter, scrollbarWidth, wrapperParentWidth;
519
520			if (this.options.filter) {
521				this.$filter.hide();
522			}
523
524			this.$wrapper.css({
525				position: 'relative'
526			});
527			this.$dropdown.css({
528				position: 'absolute',
529				zIndex: 9998,
530				width: '100%'
531			});
532			this.$list.css({
533				position: 'relative'
534			});
535
536			this._fixHeight();
537
538			// width calculations for the fake select when "autoWidth" is "true"
539			if (this.options.dynamicWidth || this.options.autoWidth || this.options.ddFullWidth) {
540				this.$wrapper.width('');
541
542				this.$dropdown.show().width(9999);
543				this.$listInner.css('float', 'left');
544				this.$list.css('float', 'left');
545				maxWidthOuter = this.$list.outerWidth(true);
546				scrollbarWidth = this.$listInner.width() - this.$listInnerUl.width();
547				this.$list.css('float', '');
548				this.$listInner.css('float', '');
549				this.$dropdown.css('width', '100%');
550
551				if (this.options.ddFullWidth) {
552					this.$dropdown.width(maxWidthOuter + scrollbarWidth);
553				}
554
555				if (this.options.dynamicWidth) {
556					this.$wrapper.css({
557						display: 'inline-block',
558						width: 'auto',
559						verticalAlign: 'top'
560					});
561				} else if (this.options.autoWidth) {
562					this.$wrapper.width(maxWidthOuter + (this.options.equalWidths ? scrollbarWidth : 0)).addClass('ik_select_autowidth');
563				}
564
565				wrapperParentWidth = this.$wrapper.parent().width();
566				if (this.$wrapper.width() > wrapperParentWidth) {
567					this.$wrapper.width(wrapperParentWidth);
568				}
569			}
570
571			if (this.options.filter) {
572				this.$filter.show().outerWidth(this.$filterWrap.width());
573			}
574
575			this.$dropdown.hide();
576
577			// hide the original select
578			this.$el.css({
579				position: 'absolute',
580				margin: 0,
581				padding: 0,
582				top: 0,
583				left: -9999
584			});
585
586			// show the original select in mobile browsers
587			if ($.browser.mobile) {
588				this.$el.css({
589					opacity: 0,
590					left: 0,
591					height: this.$wrapper.height(),
592					width: this.$wrapper.width()
593				});
594			}
595		},
596
597		// creates or recreates dropdown and sets selected options's text into fake select
598		reset: function () {
599			var html = '';
600
601			// init fake select's text
602			this.$linkText.html(this.$el.val());
603
604			this.$listInner.empty();
605
606			// creating an ul>li list identical to the original dropdown
607			html = '<ul>';
608			this.$el.children().each($.proxy(function (childIndex, child) {
609				var $child = $(child);
610				var tagName = child.tagName.toLowerCase();
611				var options;
612				if (tagName === 'optgroup') {
613					options = $child.children().map($.proxy(function (optionIndex, option) {
614						return this._generateOptionObject($(option));
615					}, this));
616					options = $.makeArray(options);
617					html += this._renderListOptgroup({
618						label: $child.attr('label') || '&nbsp;',
619						isDisabled: $child.is(':disabled'),
620						options: options
621					});
622				} else if (tagName === 'option') {
623					html += this._renderListOption(this._generateOptionObject($child));
624				}
625			}, this));
626			html += '</ul>';
627			this.$listInner.append(html);
628			this._syncOriginalOption();
629
630			this.$listInnerUl = $('> ul', this.$listInner);
631			this.$optgroupSet = $('.ik_select_optgroup', this.$listInner);
632			this.$optionSet = $('.ik_select_option', this.$listInner);
633		},
634
635		// hides dropdown
636		hideDropdown: function () {
637			if (this.options.filter) {
638				this.$filter.val('');
639				this._filterKeyup();
640			}
641
642			this.$dropdown.hide().appendTo(this.$wrapper).css({
643				'left': '',
644				'top': ''
645			});
646			if (this.options.extractLink) {
647				this.$wrapper.outerWidth(this.$wrapper.data('outerWidth'));
648				this.$wrapper.height('');
649				this.$link.removeClass('ik_select_link_extracted').css({
650					position: '',
651					top: '',
652					left: '',
653					zIndex: ''
654				}).prependTo(this.$wrapper);
655			}
656			instOpened = null;
657			this.$el.focus();
658
659			this.options.onHide(this);
660			this.$el.trigger('ikhide', this);
661		},
662
663		// shows dropdown
664		showDropdown: function () {
665			var dropdownOffset, dropdownOuterWidth, dropdownOuterHeight;
666			var wrapperOffset, wrapperOuterWidth;
667			var windowWidth, windowHeight, windowScroll;
668			var linkOffset;
669
670			if (instOpened === this || !this.$optionSet.length) {
671				return;
672			} else if (instOpened) {
673				instOpened.hideDropdown();
674			}
675
676			this._syncOriginalOption();
677			if($('.show_un_props').length)
678				this.$dropdown.addClass('show_un_props');
679			else if($('.unshow_un_props').length)
680				this.$dropdown.addClass('unshow_un_props');
681			this.$dropdown.show();
682
683			dropdownOffset = this.$dropdown.offset();
684			dropdownOuterWidth = this.$dropdown.outerWidth(true);
685			dropdownOuterHeight = this.$dropdown.outerHeight(true);
686			wrapperOffset = this.$wrapper.offset();
687			windowWidth = $window.width();
688			windowHeight = $window.height();
689			windowScroll = $window.scrollTop();
690
691			// if the dropdown's right border is beyond window's edge then move the dropdown to the left so that it fits
692			if (this.options.ddFullWidth && wrapperOffset.left + dropdownOuterWidth > windowWidth) {
693				dropdownOffset.left = windowWidth - dropdownOuterWidth;
694			}
695
696			// if the dropdown's bottom border is beyond window's edge then move the dropdown to the top so that it fits
697			if (dropdownOffset.top + dropdownOuterHeight > windowScroll + windowHeight) {
698				dropdownOffset.top = windowScroll + windowHeight - dropdownOuterHeight;
699			}
700
701			this.$dropdown.css({
702				left: dropdownOffset.left,
703				top: dropdownOffset.top,
704				width: this.$dropdown.width()
705			}).appendTo('body');
706
707			if (this.options.extractLink) {
708				linkOffset = this.$link.offset();
709				wrapperOuterWidth = this.$wrapper.outerWidth();
710				this.$wrapper.data('outerWidth', wrapperOuterWidth);
711				this.$wrapper.outerWidth(wrapperOuterWidth);
712				this.$wrapper.outerHeight(this.$wrapper.outerHeight());
713				this.$link.outerWidth(this.$link.outerWidth());
714				this.$link.addClass('ik_select_link_extracted').css({
715					position: 'absolute',
716					top: linkOffset.top,
717					left: linkOffset.left,
718					zIndex: 9999
719				}).appendTo('body');
720			}
721
722			this.$listInner.scrollTop(this.$active.position().top - this.$list.height() / 2);
723
724			if (this.options.filter) {
725				this.$filter.focus();
726			} else {
727				this.$el.focus();
728			}
729
730			instOpened = this;
731
732			this.options.onShow(this);
733			this.$el.trigger('ikshow', this);
734		},
735
736		_generateOptionObject: function ($option) {
737			
738			return {
739				value: $option.val(),
740				label: $option.html() || '&nbsp;',
741				isDisabled: $option.is(':disabled'),
742				dataParam: $option.data(),
743				className: $option.attr('class'),
744				title: $option.attr('title')
745			};
746		},
747
748		// generates option code for the fake dropdown
749		_renderListOption: function (option) {
750			var html;
751			var disabledClass = option.isDisabled ? ' ik_select_option_disabled' : '';
752			var imgClass = option.dataParam.img_src ? ' img' : '';
753			var missingClass = option.className=='hidden' ? ' missing' : '';
754			var title = option.title;
755			html = '<li class="ik_select_option' + disabledClass + imgClass + missingClass + '" title="'+title+'" data-value="' + option.value + '">';
756			html += '<span class="ik_select_option_label" title="'+title+'">';
757			if(option.dataParam.img_src){
758				html += '<span class="icon_color" style="background: url('+option.dataParam.img_src+')"></span>';
759			}
760			html += option.label;
761			html += '</span>';
762			html += '</li>';
763			return html;
764		},
765
766		// generates optgroup code for the fake dropdown
767		_renderListOptgroup: function (optgroup) {
768			var html;
769			var disabledClass = optgroup.isDisabled ? ' ik_select_optgroup_disabled' : '';
770			html = '<li class="ik_select_optgroup' + disabledClass + '">';
771			html += '<div class="ik_select_optgroup_label">' + optgroup.label + '</div>';
772			html += '<ul>';
773			if ($.isArray(optgroup.options)) {
774				$.each(optgroup.options, $.proxy(function (optionIndex, option) {
775					html += this._renderListOption({
776						value: option.value,
777						label: option.label || '&nbsp;',
778						isDisabled: option.isDisabled
779					});
780				}, this));
781			}
782			html += '</ul>';
783			html += '</li>';
784			return html;
785		},
786
787		// generates option code for the select
788		_renderOption: function (option) {
789			return '<option value="' + option.value + '">' + option.label + '</option>';
790		},
791
792		// generates optgroup code for the select
793		_renderOptgroup: function (optgroup) {
794			var html;
795			html = '<optgroup label="' + optgroup.label + '">';
796			if ($.isArray(optgroup.options)) {
797				$.each(optgroup.options, $.proxy(function (optionIndex, option) {
798					html += this._renderOption(option);
799				}, this));
800			}
801			html += '</option>';
802			return html;
803		},
804
805		addOptions: function (options, optionIndex, optgroupIndex) {
806			var listHtml = '', selectHtml = '';
807			var $destinationUl = this.$listInnerUl;
808			var $destinationOptgroup = this.$el;
809			var $ulOptions, $optgroupOptions;
810
811			options = $.isArray(options) ? options : [options];
812
813			$.each(options, $.proxy(function (index, option) {
814				listHtml += this._renderListOption(option);
815				selectHtml += this._renderOption(option);
816			}, this));
817
818			if ($.isNumeric(optgroupIndex) && optgroupIndex < this.$optgroupSet.length) {
819				$destinationUl = this.$optgroupSet.eq(optgroupIndex);
820				$destinationOptgroup = $('optgroup', this.$el).eq(optgroupIndex);
821			}
822			if ($.isNumeric(optionIndex)) {
823				$ulOptions = $('.ik_select_option', $destinationUl);
824				if (optionIndex < $ulOptions.length) {
825					$ulOptions.eq(optionIndex).before(listHtml);
826					$optgroupOptions = $('option', $destinationOptgroup);
827					$optgroupOptions.eq(optionIndex).before(selectHtml);
828				}
829			}
830			if (!$optgroupOptions) {
831				$destinationUl.append(listHtml);
832				$destinationOptgroup.append(selectHtml);
833			}
834
835			this.$optionSet = $('.ik_select_option', this.$listInner);
836			this._fixHeight();
837		},
838
839		addOptgroups: function (optgroups, optgroupIndex) {
840			var listHtml = '', selectHtml = '';
841			if (!optgroups) {
842				return;
843			}
844			optgroups = $.isArray(optgroups) ? optgroups : [optgroups];
845
846			$.each(optgroups, $.proxy(function (optgroupIndex, optgroup) {
847				listHtml += this._renderListOptgroup(optgroup);
848				selectHtml += this._renderOptgroup(optgroup);
849			}, this));
850
851			if ($.isNumeric(optgroupIndex) && optgroupIndex < this.$optgroupSet.length) {
852				this.$optgroupSet.eq(optgroupIndex).before(listHtml);
853				$('optgroup', this.$el).eq(optgroupIndex).before(selectHtml);
854			} else {
855				this.$listInnerUl.append(listHtml);
856				this.$el.append(selectHtml);
857			}
858
859			this.$optgroupSet = $('.ik_select_optgroup', this.$listInner);
860			this.$optionSet = $('.ik_select_option', this.$listInner);
861			this._fixHeight();
862		},
863
864		removeOptions: function (optionIndexes, optgroupIndex) {
865			var $removeList = $([]);
866			var $listContext;
867			var $selectContext;
868
869			if ($.isNumeric(optgroupIndex)) {
870				if (optgroupIndex < 0) {
871					$listContext = $('> .ik_select_option', this.$listInnerUl);
872					$selectContext = $('> option', this.$el);
873				} else if (optgroupIndex < this.$optgroupSet.length) {
874					$listContext = $('.ik_select_option', this.$optgroupSet.eq(optgroupIndex));
875					$selectContext = $('optgroup', this.$el).eq(optgroupIndex).find('option');
876				}
877			}
878			if (!$listContext) {
879				$listContext = this.$optionSet;
880				$selectContext = $(this.el.options);
881			}
882
883			if (!$.isArray(optionIndexes)) {
884				optionIndexes = [optionIndexes];
885			}
886
887			$.each(optionIndexes, $.proxy(function (index, optionIndex) {
888				if (optionIndex < $listContext.length) {
889					$removeList = $removeList.add($listContext.eq(optionIndex)).add($selectContext.eq(optionIndex));
890				}
891			}, this));
892
893			$removeList.remove();
894			this.$optionSet = $('.ik_select_option', this.$listInner);
895			this._syncOriginalOption();
896			this._fixHeight();
897		},
898
899		removeOptgroups: function (optgroupIndexes) {
900			var $removeList = $([]);
901			var $selectOptgroupSet = $('optgroup', this.el);
902
903			if (!$.isArray(optgroupIndexes)) {
904				optgroupIndexes = [optgroupIndexes];
905			}
906
907			$.each(optgroupIndexes, $.proxy(function (index, optgroupIndex) {
908				if (optgroupIndex < this.$optgroupSet.length) {
909					$removeList = $removeList.add(this.$optgroupSet.eq(optgroupIndex)).add($selectOptgroupSet.eq(optgroupIndex));
910				}
911			}, this));
912
913			$removeList.remove();
914			this.$optionSet = $('.ik_select_option', this.$listInner);
915			this.$optgroupSet = $('.ik_select_optgroup', this.$listInner);
916			this._syncOriginalOption();
917			this._fixHeight();
918		},
919
920		// disable select
921		disable: function () {
922			this.toggle(false);
923		},
924
925		// enable select
926		enable: function () {
927			this.toggle(true);
928		},
929
930		// toggle select
931		toggle: function (bool) {
932			this.isDisabled = typeof bool !== 'undefined' ? !bool : !this.isDisabled;
933			this.$el.prop('disabled', this.isDisabled);
934			this.$link.toggleClass('ik_select_link_disabled', this.isDisabled);
935		},
936
937		// make option selected by value
938		select: function (value, isIndex) {
939			if (!isIndex) {
940				this.$el.val(value);
941			} else {
942				this.el.selectedIndex = value;
943			}
944			this._syncOriginalOption();
945		},
946
947		disableOptgroups: function (optgroupIndexes) {
948			this.toggleOptgroups(optgroupIndexes, false);
949		},
950
951		enableOptgroups: function (optgroupIndexes) {
952			this.toggleOptgroups(optgroupIndexes, true);
953		},
954
955		toggleOptgroups: function (optgroupIndexes, bool) {
956			if (!$.isArray(optgroupIndexes)) {
957				optgroupIndexes = [optgroupIndexes];
958			}
959
960			$.each(optgroupIndexes, $.proxy(function (index, optgroupIndex) {
961				var isDisabled;
962				var $optionSet, indexes = [], indexFirst;
963				var $optgroup = $('optgroup', this.$el).eq(optgroupIndex);
964				isDisabled = typeof bool !== 'undefined' ? bool : $optgroup.prop('disabled');
965				$optgroup.prop('disabled', !isDisabled);
966				this.$optgroupSet.eq(optgroupIndex).toggleClass('ik_select_optgroup_disabled', !isDisabled);
967
968				$optionSet = $('option', $optgroup);
969				indexFirst = $(this.el.options).index($optionSet.eq(0));
970				for (var i = indexFirst; i < indexFirst + $optionSet.length; i++) {
971					indexes.push(i);
972				}
973				this.toggleOptions(indexes, true, isDisabled);
974			}, this));
975
976			this._syncOriginalOption();
977		},
978
979		disableOptions: function (lookupValues, isIndex) {
980			this.toggleOptions(lookupValues, isIndex, false);
981		},
982
983		enableOptions: function (lookupValues, isIndex) {
984			this.toggleOptions(lookupValues, isIndex, true);
985		},
986
987		toggleOptions: function (lookupValues, isIndex, bool) {
988			var $selectOptionSet = $('option', this.el);
989			if (!$.isArray(lookupValues)) {
990				lookupValues = [lookupValues];
991			}
992
993			var toggleOption = $.proxy(function ($option, optionIndex) {
994				var isDisabled = typeof bool !== 'undefined' ? bool : $option.prop('disabled');
995				$option.prop('disabled', !isDisabled);
996				this.$optionSet.eq(optionIndex).toggleClass('ik_select_option_disabled', !isDisabled);
997			}, this);
998
999			$.each(lookupValues, function (index, lookupValue) {
1000				if (!isIndex) {
1001					$selectOptionSet.each(function (optionIndex, option) {
1002						var $option = $(option);
1003						if ($option.val() === lookupValue) {
1004							toggleOption($option, optionIndex);
1005							return this;
1006						}
1007					});
1008				} else {
1009					toggleOption($selectOptionSet.eq(lookupValue), lookupValue);
1010				}
1011			});
1012
1013			this._syncOriginalOption();
1014		},
1015
1016		// detach plugin from the orignal select
1017		detach: function () {
1018			this.$el.off('.ikSelect').css({
1019				width: '',
1020				height: '',
1021				left: '',
1022				top: '',
1023				position: '',
1024				margin: '',
1025				padding: ''
1026			});
1027
1028			this.$wrapper.before(this.$el);
1029			this.$wrapper.remove();
1030			this.$el.removeData('plugin_ikSelect');
1031		}
1032	});
1033
1034	$.fn.ikSelect = function (options) {
1035		var args;
1036		//do nothing if opera mini
1037		if ($.browser.operamini) {
1038			return this;
1039		}
1040
1041		args = Array.prototype.slice.call(arguments, 1);
1042
1043		return this.each(function () {
1044			var plugin;
1045			if (!$.data(this, 'plugin_ikSelect')) {
1046				$.data(this, 'plugin_ikSelect', new IkSelect(this, options));
1047			} else if (typeof options === 'string') {
1048				plugin = $.data(this, 'plugin_ikSelect');
1049				if (typeof plugin[options] === 'function') {
1050					plugin[options].apply(plugin, args);
1051				}
1052			}
1053		});
1054	};
1055
1056	$.ikSelect = {
1057		extendDefaults: function (options) {
1058			$.extend(defaults, options);
1059		}
1060	};
1061
1062	$(document).bind('click.ikSelect', function () {
1063		if (instOpened) {
1064			instOpened.hideDropdown();
1065		}
1066	});
1067})(jQuery, window, document);

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.