UNPKG

6.33 kBJavaScriptView Raw
1
2
3
4!function(exports, Object) {
5 var undef
6 , P = "prototype"
7 , A = Array[P]
8 , F = Function[P]
9 , S = String[P]
10 , N = Number[P]
11 , slice = F.call.bind(A.slice)
12 , fns = {}
13 , hasOwn = fns.hasOwnProperty
14 , fnRe = /('|")(?:\\?.)*?\1|\/(?:\\?.)+?\/[gim]*|\b(?:false|in|new|null|this|true|typeof|void|function|var|if)\b|\.\w+|\w+:/g
15 , formatRe = /{(?!\\)((?:("|')(?:\\?.)*?\2|\\}|[^}])*)}/g
16 , numbersRe = /-?\d+\.?\d*/g
17 , wordRe = /\b[a-z_$][\w$]*/ig
18 , unescapeRe = /{\\/g
19
20
21 exports.Fn = Fn
22 Fn.hold = hold
23 Fn.wait = wait
24
25
26 // Function extensions
27 // -------------------
28
29 F.extend = function() {
30 var arg
31 , fn = this
32 , i = 0
33
34 function wrapper() {
35 return fn.apply(this, arguments)
36 }
37
38 for (wrapper[P] = Object.create(fn[P]); arg = arguments[i++]; ) {
39 Object.assign(wrapper[P], arg)
40 }
41 wrapper[P].constructor = wrapper
42 return wrapper
43 }
44
45
46 // Non-standard
47 Object.each = function(obj, fn, scope, key) {
48 if (obj) for (key in obj) {
49 hasOwn.call(obj, key) && fn.call(scope, obj[key], key, obj)
50 }
51 }
52
53 // Chrome54, FF47, Edge14, Safari10.1
54 Object.values = function(obj) {
55 return Object.keys(obj || {}).map(function(e) {
56 return obj[e]
57 })
58 }
59
60 // Non-standard
61 // IE<9 bug: [1,2].splice(0).join("") == "" but should be "12"
62 A.remove = arrayRemove
63 function arrayRemove() {
64 var arr = this
65 , len = arr.length
66 , o = slice(arguments)
67 , lastId = -1
68
69 for (; len--; ) if (~o.indexOf(arr[len])) {
70 arr.splice(lastId = len, 1)
71 }
72 return lastId
73 }
74
75 A.each = A.forEach
76 // uniq
77 // first item preserved
78 A.uniq = function() {
79 for (var a = this, i = a.length; i--; ) {
80 if (a.indexOf(a[i]) !== i) a.splice(i, 1)
81 }
82 return a
83 }
84
85 A.pushUniq = function(item) {
86 return this.indexOf(item) < 0 && this.push(item)
87 }
88
89 // THANKS: Oliver Steele - Functional Javascript [http://www.osteele.com/sources/javascript/functional/]
90 function Fn(expr /*, scope, mask1, ..maskN */) {
91 var args = []
92 , arr = expr.match(/[^"']+?->|[\s\S]+$/g)
93 , scope = slice(arguments, 1)
94 , key = scope.length + ":" + expr
95 , fn = fns[key]
96
97 if (!fn) {
98 fn = expr.replace(fnRe, "").match(wordRe) || []
99 for (; arr.length > 1; ) {
100 expr = arr.pop()
101 args = arr.pop().match(/\w+/g) || []
102 arrayRemove.apply(fn, args)
103 if (arr.length) {
104 arr.push("function(" + args + "){return(" + expr + ")}" + (scope[0] ? ".bind(this)" : ""))
105 }
106 }
107 expr = "return(" + expr + ")"
108
109 if (scope[0]) {
110 arr = Object.keys(scope).map(Fn("a->'__'+a"))
111 arr[0] = "this"
112 expr = (
113 fn[0] ?
114 "var " + fn.uniq().join("='',") + "='';" :
115 ""
116 ) + "with(" + arr.join(")with(") + "){" + expr + "}"
117 args = arr.slice(1).concat(args)
118 }
119
120 fn = fns[key] = Function(args, expr)
121 }
122
123 return scope.length ? fn.bind.apply(fn, scope) : fn
124 }
125
126 Fn.keys = function(str) {
127 var i, tmp
128 , arr = []
129 , match = str.match(formatRe)
130 if (match) {
131 for (i = match.length; i--; ) {
132 if (tmp = match[i].replace(fnRe, "").match(wordRe)) {
133 arr.push.apply(arr, tmp)
134 }
135 }
136 }
137 return arr.uniq()
138 }
139
140 S.format = function() {
141 var args = A.slice.call(arguments)
142 args.unshift(0)
143 return this.replace(formatRe, function(_, arg) {
144 args[0] = arg.replace(/\\}/g, "}")
145 return Fn.apply(null, args)()
146 }).replace(unescapeRe, "{")
147 }
148
149 N.format = function(data) {
150 return "" + this
151 }
152
153 S.safe = function() {
154 return this
155 .replace(/&/g, "&amp;")
156 .replace(/</g, "&lt;")
157 .replace(/>/g, "&gt;")
158 .replace(/\"/g, "&quot;")
159 }
160
161 S.capitalize = function() {
162 return this.charAt(0).toUpperCase() + this.slice(1)
163 }
164
165 S.lower = S.toLowerCase
166 S.upper = S.toUpperCase
167
168 N.step = function(a, add) {
169 var x = ("" + a).split(".")
170 , steps = this / a
171 , n = ~~(steps + ((steps < 0 ? -1 : 1) * (add == undef ? .5 : add === 1 && steps == (steps|0) ? 0 : +add))) * a
172 return "" + (1 in x ? n.toFixed(x[1].length) : n)
173 }
174
175 S.step = function(a, add) {
176 return this.replace(numbersRe, function(num) {
177 return (+num).step(a, add)
178 })
179 }
180
181 N.scale = words([1000, 1000, 1000], ["","k","M","G"], {"default": "{n}{u}"})
182
183 S.scale = function() {
184 return this.replace(numbersRe, function(num) {
185 return (+num).scale()
186 })
187 }
188
189 S.pick = N.pick = function() {
190 var val = this + "="
191 for (var s, a = arguments, i = 0, len = a.length; i < len;) {
192 s = a[i++]
193 if (s.indexOf(val) == 0) {
194 s = s.slice(val.length)
195 i = len
196 }
197 }
198 return s.replace("#", this)
199 }
200
201 S.plural = N.plural = function() {
202 // Plural-Forms: nplurals=2; plural=n != 1;
203 // http://www.gnu.org/software/gettext/manual/html_mono/gettext.html#Plural-forms
204 return arguments[ +Fn("n->" + (String.plural || "n!=1"))( parseFloat(this) ) ].replace("#", this)
205 }
206
207 A.pluck = function(name) {
208 for (var arr = this, i = arr.length, out = []; i--; ) {
209 out[i] = arr[i][name]
210 }
211 return out
212 }
213
214 function words(steps, units, strings, overflow) {
215 return function(input) {
216 var n = +(arguments.length ? input : this)
217 , i = 0
218 , s = strings || {"default": "{n} {u}{s}"}
219
220 for (; n>=steps[i]; ) {
221 n /= steps[i++]
222 }
223 if (i == steps.length && overflow) {
224 return overflow(this)
225 }
226 i = units[i]
227 return (s[n < 2 ? i : i + "s"] || s["default"]).format({n: n, u: i, s: n < 2 ? "" : "s"})
228 }
229 }
230 Fn.words = words
231
232 function wait(fn) {
233 var pending = 1
234 function resume() {
235 if (!--pending && fn) fn.call(this)
236 }
237 resume.wait = function() {
238 pending++
239 return resume
240 }
241 return resume
242 }
243
244 function hold(ignore) {
245 var k
246 , obj = this
247 , hooks = []
248 , hooked = []
249 , _resume = wait(resume)
250 ignore = ignore || obj.syncMethods || []
251
252 for (k in obj) if (typeof obj[k] == "function" && ignore.indexOf(k) < 0) !function(k) {
253 hooked.push(k, hasOwn.call(obj, k) && obj[k])
254 obj[k] = function() {
255 hooks.push(k, arguments)
256 return obj
257 }
258 }(k)
259
260 /**
261 * `wait` is already in hooked array,
262 * so override hooked method
263 * that will be cleared on resume.
264 */
265 obj.wait = _resume.wait
266
267 return _resume
268
269 function resume() {
270 for (var v, scope = obj, i = hooked.length; i--; i--) {
271 if (hooked[i]) obj[hooked[i-1]] = hooked[i]
272 else delete obj[hooked[i-1]]
273 }
274 // i == -1 from previous loop
275 for (; v = hooks[++i]; ) {
276 scope = scope[v].apply(scope, hooks[++i]) || scope
277 }
278 hooks = hooked = null
279 }
280 }
281
282}(this, Object)
283
284
285