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 |
|
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 |
|
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 |
|
54 | Object.values = function(obj) {
|
55 | return Object.keys(obj || {}).map(function(e) {
|
56 | return obj[e]
|
57 | })
|
58 | }
|
59 |
|
60 |
|
61 |
|
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 |
|
77 |
|
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 |
|
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, "&")
|
156 | .replace(/</g, "<")
|
157 | .replace(/>/g, ">")
|
158 | .replace(/\"/g, """)
|
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 |
|
203 |
|
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 |
|
262 |
|
263 |
|
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 |
|
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 |
|