forked from patrickkunka/easydropdown
-
Notifications
You must be signed in to change notification settings - Fork 0
/
jquery.easydropdown.min.js
241 lines (240 loc) · 12 KB
/
jquery.easydropdown.min.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
/*
* Custom code! See https://github.com/computerminds/easydropdown/
*
* EASYDROPDOWN - A Drop-down Builder for Styleable Inputs and Menus
* Version: 2.1.4
* License: Creative Commons Attribution 3.0 Unported - CC BY 3.0
* http://creativecommons.org/licenses/by/3.0/
* This software may be used freely on commercial and non-commercial projects with attribution to the author/copyright holder.
* Author: Patrick Kunka
* Copyright 2013 Patrick Kunka, All Rights Reserved
*/
!function (e) {
function t() {
this.isField = !0, this.down = !1, this.inFocus = !1, this.disabled = !1, this.multiple = !1, this.cutOff = !1, this.hasLabel = !1, this.keyboardMode = !1, this.nativeTouch = !0, this.wrapperClass = "dropdown", this.onChange = null
}
t.prototype = {
constructor: t, instances: {}, init: function (t, n) {
var o = this;
e.extend(o, n), o.$select = e(t), o.id = t.id, o.options = [], o.$options = o.$select.find("option"), o.isTouch = "ontouchend" in document, o.$select.removeClass(o.wrapperClass + " dropdown"), o.$select.is(":disabled") && (o.disabled = !0), o.$select.attr("multiple") && (o.multiple = !0), o.$options.length && (o.selected = [], o.$options.each(function (t) {
var n = e(this);
n.is(":selected") && (o.selected.push({
index: t,
title: n.html()
}), void 0 === o.focusIndex && (o.focusIndex = t)), n.hasClass("label") && 0 == t ? (o.hasLabel = !0, o.label = n.html(), n.attr("value", "")) : o.options.push({
domNode: n[0],
title: n.html(),
value: n.val(),
selected: n.is(":selected")
})
}), o.selected.length || (o.selected = [
{
index: 0,
title: o.$options.eq(0).html()
}
], o.focusIndex = 0), o.multiple || (o.selected = o.selected[0]), o.render())
}, render: function () {
var t = this, n = t.isTouch && t.nativeTouch ? " touch" : "",
o = t.disabled ? " disabled" : "", s = t.multiple ? " multiple" : "";
t.$container = t.$select.wrap('<div class="' + t.wrapperClass + n + o + s + '"><span class="old"/></div>').parent().parent(), t.$active = e('<span class="selected"></span>').appendTo(t.$container), t.$carat = e('<span class="carat"/>').appendTo(t.$container), t.$scrollWrapper = e("<div><ul/></div>").appendTo(t.$container), t.$dropDown = t.$scrollWrapper.find("ul"), t.$form = t.$container.closest("form"), e.each(t.options, function () {
var e = this, n = e.selected ? ' class="active"' : "";
t.$dropDown.append("<li" + n + ">" + e.title + "</li>")
}), t.$items = t.$dropDown.find("li"), t.$active.html(t.getSelectionText()), t.cutOff && t.$items.length > t.cutOff && t.$container.addClass("scrollable"), t.getMaxHeight(), t.isTouch && t.nativeTouch ? t.bindTouchHandlers() : t.bindHandlers()
}, getSelectionText: function () {
var e, t = this, n = 0;
if (t.multiple && !t.selected.length || !t.multiple && "undefined" == typeof t.selected.title)return t.$options.eq(0).html();
if (t.multiple) {
for (t.selected.sort(function (e, t) {
return e.index == t.index ? 0 : e.index > t.index ? 1 : -1
}), e = []; n < t.selected.length; ++n)t.hasLabel && 0 == t.selected[n].index ? 1 == t.selected.length && (e = [t.label]) : e.push(t.selected[n].title);
e = e.join(", ")
}
else e = t.selected.title;
return e
}, getMaxHeight: function () {
var e = this;
for (e.maxHeight = 0, i = 0; i < e.$items.length; i++) {
var t = e.$items.eq(i);
if (e.maxHeight += t.outerHeight(), e.cutOff == i + 1)break
}
}, bindTouchHandlers: function () {
var t = this;
t.$container.on("click.easyDropDown", function () {
t.$select.focus()
}), t.$select.on({
change: function () {
var n = e(this).find("option:selected"), o = (n.html(), n.val(), []);
n.each(function (t, n) {
o.push({title: e(n).html(), index: e(n).index()})
}), t.selected = t.multiple ? o : o[0], t.$active.html(t.getSelectionText()), t.fireChangeCallback()
}, focus: function () {
t.$container.addClass("focus")
}, blur: function () {
t.$container.removeClass("focus")
}
})
}, fireChangeCallback: function () {
var t = this, n = t.$select.find("option:selected");
"function" == typeof t.onChange && (t.multiple ? t.onChange.call(t.$select[0], n.map(function (t, n) {
return {title: e(n).html(), value: e(n).val()}
})) : t.onChange.call(t.$select[0], {title: title, value: value}))
}, bindHandlers: function () {
var t = this;
t.query = "", t.$container.on({
"click.easyDropDown": function (n) {
return t.multiple && t.down && !t.disabled ? void(0 == e(n.target).closest(t.$dropDown).length && t.close()) : void(t.down || t.disabled ? t.close() : t.open())
}, "mousemove.easyDropDown": function () {
t.keyboardMode && (t.keyboardMode = !1)
}
}), e("body").on("click.easyDropDown." + t.id, function (n) {
var o = e(n.target), s = t.wrapperClass.split(" ").join(".");
!o.closest("." + s).length && t.down && t.close()
}), t.$items.on({
"click.easyDropDown": function () {
var n = e(this).index();
t.select(n), t.$select.focus()
}, "mouseover.easyDropDown": function () {
if (!t.keyboardMode) {
var n = e(this);
n.addClass("focus").siblings().removeClass("focus"), t.focusIndex = n.index()
}
}, "mouseout.easyDropDown": function () {
t.keyboardMode || e(this).removeClass("focus")
}
}), t.$select.on({
"focus.easyDropDown": function () {
t.$container.addClass("focus"), t.inFocus = !0
}, "blur.easyDropDown": function () {
t.$container.removeClass("focus"), t.inFocus = !1
}, "keydown.easyDropDown": function (e) {
if (t.inFocus) {
t.keyboardMode = !0;
var n = e.keyCode;
if ((38 == n || 40 == n || 32 == n) && (e.preventDefault(), 38 == n ? (t.focusIndex--, t.focusIndex = t.focusIndex < 0 ? t.$items.length - 1 : t.focusIndex) : 40 == n && (t.focusIndex++, t.focusIndex = t.focusIndex > t.$items.length - 1 ? 0 : t.focusIndex), t.down || t.open(), t.$items.removeClass("focus").eq(t.focusIndex).addClass("focus"), t.cutOff && t.scrollToView(), t.query = ""), t.down)if (9 == n || 27 == n) t.close();
else {
if (13 == n)return e.preventDefault(), t.select(t.focusIndex), t.close(), !1;
if (8 == n)return e.preventDefault(), t.query = t.query.slice(0, -1), t.search(), clearTimeout(t.resetQuery), !1;
if (38 != n && 40 != n) {
var o = String.fromCharCode(n);
t.query += o, t.search(), clearTimeout(t.resetQuery)
}
}
}
}, "keyup.easyDropDown": function () {
t.resetQuery = setTimeout(function () {
t.query = ""
}, 1200)
}
}), t.$dropDown.on("scroll.easyDropDown", function (e) {
t.$dropDown[0].scrollTop >= t.$dropDown[0].scrollHeight - t.maxHeight ? t.$container.addClass("bottom") : t.$container.removeClass("bottom")
}), t.$form.length && t.$form.on("reset.easyDropDown", function () {
var e = t.hasLabel ? t.label : t.options[0].title;
t.$active.html(e)
})
}, unbindHandlers: function () {
var t = this;
t.$container.add(t.$select).add(t.$items).add(t.$form).add(t.$dropDown).off(".easyDropDown"), e("body").off("." + t.id)
}, open: function () {
var e = this, t = window.scrollY || document.documentElement.scrollTop,
n = window.scrollX || document.documentElement.scrollLeft,
o = e.notInViewport(t);
e.closeAll(), e.getMaxHeight(), e.$select.focus(), window.scrollTo(n, t + o), e.$container.addClass("open"), e.$scrollWrapper.css("height", e.maxHeight + "px"), e.down = !0
}, close: function () {
var e = this;
e.$container.removeClass("open"), e.$scrollWrapper.css("height", "0px"), e.focusIndex = e.multiple ? e.selected.length ? e.selected[0].index : 0 : e.selected.index, e.query = "", e.down = !1
}, closeAll: function () {
var e = this, t = Object.getPrototypeOf(e).instances;
for (var n in t) {
var o = t[n];
o.close()
}
}, select: function (e, t) {
var n = this;
"string" == typeof e && (e = n.$select.find("option[value=" + e + "]").index() - 1), "undefined" == typeof t && (t = n.multiple ? !n.$items.eq(e).hasClass("active") : !0);
var o, s, i = n.options[e], l = n.hasLabel ? e + 1 : e,
c = n.$select.find("option"), a = {index: l, title: i.title};
if (this.multiple || (n.$items.removeClass("active"), c.removeAttr("selected")), t ? n.$items.eq(e).addClass("active") : n.$items.eq(e).removeClass("active"), c.eq(l).prop("selected", t).parent().trigger("change"), this.multiple) {
if (t) {
for (s = !1, o = 0; o < n.selected.length; ++o)n.selected[o].index == l && (s = !0);
s || n.selected.push(a)
}
else for (o = 0; o < n.selected.length; ++o)if (n.selected[o].index == l) {
n.selected.splice(o, 1);
break
}
}
else t ? n.selected = a : n.selected = {
index: 0,
title: n.$options.eq(0).html()
};
n.focusIndex = o, n.$active.html(n.getSelectionText()), n.fireChangeCallback()
}, deselect: function (e) {
this.select(e, !1)
}, search: function () {
var e = this, t = function (t) {
e.focusIndex = t, e.$items.removeClass("focus").eq(e.focusIndex).addClass("focus"), e.scrollToView()
}, n = function (t) {
return e.options[t].title.toUpperCase()
};
for (i = 0; i < e.options.length; i++) {
var o = n(i);
if (0 == o.indexOf(e.query))return void t(i)
}
for (i = 0; i < e.options.length; i++) {
var o = n(i);
if (o.indexOf(e.query) > -1) {
t(i);
break
}
}
}, scrollToView: function () {
var e = this;
if (e.focusIndex >= e.cutOff) {
var t = e.$items.eq(e.focusIndex),
n = t.outerHeight() * (e.focusIndex + 1) - e.maxHeight;
e.$dropDown.scrollTop(n)
}
}, notInViewport: function (e) {
var t = this, n = {
min: e,
max: e + (window.innerHeight || document.documentElement.clientHeight)
}, o = t.$dropDown.offset().top + t.maxHeight;
return o >= n.min && o <= n.max ? 0 : o - n.max + 5
}, destroy: function () {
var e = this;
e.unbindHandlers(), e.$select.unwrap().siblings().remove(), e.$select.unwrap(), delete Object.getPrototypeOf(e).instances[e.$select[0].id]
}, disable: function () {
var e = this;
e.disabled = !0, e.$container.addClass("disabled"), e.$select.attr("disabled", !0), e.down || e.close()
}, enable: function () {
var e = this;
e.disabled = !1, e.$container.removeClass("disabled"), e.$select.attr("disabled", !1)
}
};
var n = function (e, n) {
e.id = e.id ? e.id : "EasyDropDown" + o();
var s = new t;
s.instances[e.id] || (s.instances[e.id] = s, s.init(e, n))
}, o = function () {
return ("00000" + (16777216 * Math.random() << 0).toString(16)).substr(-6).toUpperCase()
};
e.fn.easyDropDown = function () {
var e, o = arguments, s = [];
return e = this.each(function () {
if (o && "string" == typeof o[0]) {
var e = t.prototype.instances[this.id][o[0]](o[1], o[2]);
e && s.push(e)
}
else n(this, o[0])
}), s.length ? s.length > 1 ? s : s[0] : e
}, e(function () {
"function" != typeof Object.getPrototypeOf && ("object" == typeof"test".__proto__ ? Object.getPrototypeOf = function (e) {
return e.__proto__
} : Object.getPrototypeOf = function (e) {
return e.constructor.prototype
}), e("select.dropdown").each(function () {
var t = e(this).attr("data-settings");
settings = t ? e.parseJSON(t) : {}, n(this, settings)
})
})
}(jQuery);