UNPKG

6.41 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)\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(/[^"']+?->|.+$/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
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.camelCase = function() {
166 return this.replace(/[ _-]+([a-z])/g, function(_, a) {
167 return a.toUpperCase()
168 })
169 }
170
171 S.lower = S.toLowerCase
172 S.upper = S.toUpperCase
173
174 N.step = function(a, add) {
175 var x = ("" + a).split(".")
176 , steps = this / a
177 , n = ~~(steps + ((steps < 0 ? -1 : 1) * (add == undef ? .5 : add === 1 && steps == (steps|0) ? 0 : +add))) * a
178 return "" + (1 in x ? n.toFixed(x[1].length) : n)
179 }
180
181 S.step = function(a, add) {
182 return this.replace(numbersRe, function(num) {
183 return (+num).step(a, add)
184 })
185 }
186
187 N.scale = words([1000, 1000, 1000], ["","k","M","G"], {"default": "{n}{u}"})
188
189 S.scale = function() {
190 return this.replace(numbersRe, function(num) {
191 return (+num).scale()
192 })
193 }
194
195 S.pick = N.pick = function() {
196 var val = this + "="
197 for (var s, a = arguments, i = 0, len = a.length; i < len;) {
198 s = a[i++]
199 if (s.indexOf(val) == 0) {
200 s = s.slice(val.length)
201 i = len
202 }
203 }
204 return s.replace("#", this)
205 }
206
207 S.plural = N.plural = function() {
208 // Plural-Forms: nplurals=2; plural=n != 1;
209 // http://www.gnu.org/software/gettext/manual/html_mono/gettext.html#Plural-forms
210 return arguments[ +Fn("n->" + (String.plural || "n!=1"))( parseFloat(this) ) ].replace("#", this)
211 }
212
213 A.pluck = function(name) {
214 for (var arr = this, i = arr.length, out = []; i--; ) {
215 out[i] = arr[i][name]
216 }
217 return out
218 }
219
220 function words(steps, units, strings, overflow) {
221 return function(input) {
222 var n = +(arguments.length ? input : this)
223 , i = 0
224 , s = strings || {"default": "{n} {u}{s}"}
225
226 for (; n>=steps[i]; ) {
227 n /= steps[i++]
228 }
229 if (i == steps.length && overflow) {
230 return overflow(this)
231 }
232 i = units[i]
233 return (s[n < 2 ? i : i + "s"] || s["default"]).format({n: n, u: i, s: n < 2 ? "" : "s"})
234 }
235 }
236 Fn.words = words
237
238 function wait(fn) {
239 var pending = 1
240 function resume() {
241 if (!--pending && fn) fn.call(this)
242 }
243 resume.wait = function() {
244 pending++
245 return resume
246 }
247 return resume
248 }
249
250 function hold(ignore) {
251 var k
252 , obj = this
253 , hooks = []
254 , hooked = []
255 , _resume = wait(resume)
256 ignore = ignore || obj.syncMethods || []
257
258 for (k in obj) if (typeof obj[k] == "function" && ignore.indexOf(k) == -1) !function(k) {
259 hooked.push(k, hasOwn.call(obj, k) && obj[k])
260 obj[k] = function() {
261 hooks.push(k, arguments)
262 return obj
263 }
264 }(k)
265
266 /**
267 * `wait` is already in hooked array,
268 * so override hooked method
269 * that will be cleared on resume.
270 */
271 obj.wait = _resume.wait
272
273 return _resume
274
275 function resume() {
276 for (var v, scope = obj, i = hooked.length; i--; i--) {
277 if (hooked[i]) obj[hooked[i-1]] = hooked[i]
278 else delete obj[hooked[i-1]]
279 }
280 // i == -1 from previous loop
281 for (; v = hooks[++i]; ) {
282 scope = scope[v].apply(scope, hooks[++i]) || scope
283 }
284 hooks = hooked = null
285 }
286 }
287
288}(this, Object)
289
290
291