
lib: add npregress js library
Name : NProgress URL : https://github.com/rstacruz/nprogress License : MIT
@f2d469c94ea9061db402a30e1941564d29ff8aa9
+++ public/javascripts/lib/nprogress/nprogress.css
... | ... | @@ -0,0 +1,70 @@ |
1 | +/* Make clicks pass-through */ | |
2 | +#nprogress { | |
3 | + pointer-events: none; | |
4 | +} | |
5 | + | |
6 | +#nprogress .bar { | |
7 | + background: #27abe1; | |
8 | + | |
9 | + position: fixed; | |
10 | + z-index: 1031; | |
11 | + top: 0px; | |
12 | + left: 0; | |
13 | + | |
14 | + width: 100%; | |
15 | + height: 3px; | |
16 | +} | |
17 | + | |
18 | +/* Fancy blur effect */ | |
19 | +#nprogress .peg { | |
20 | + display: block; | |
21 | + position: absolute; | |
22 | + right: 0px; | |
23 | + width: 3px; | |
24 | + height: 100%; | |
25 | + box-shadow: 0 0 10px #fe6431, 0 0 5px #f3f3f3; | |
26 | + opacity: 1.0; | |
27 | +} | |
28 | + | |
29 | +/* Remove these to get rid of the spinner */ | |
30 | +#nprogress .spinner { | |
31 | + display: block; | |
32 | + position: fixed; | |
33 | + z-index: 1031; | |
34 | + top: 12px; | |
35 | + left: 15px; | |
36 | +} | |
37 | + | |
38 | +#nprogress .spinner-icon { | |
39 | + width: 15px; | |
40 | + height: 15px; | |
41 | + box-sizing: border-box; | |
42 | + | |
43 | + border: solid 3px transparent; | |
44 | + border-top-color: #29d; | |
45 | + border-left-color: #29d; | |
46 | + border-radius: 50%; | |
47 | + | |
48 | + -webkit-animation: nprogress-spinner 400ms linear infinite; | |
49 | + animation: nprogress-spinner 400ms linear infinite; | |
50 | +} | |
51 | + | |
52 | +.nprogress-custom-parent { | |
53 | + overflow: hidden; | |
54 | + position: relative; | |
55 | +} | |
56 | + | |
57 | +.nprogress-custom-parent #nprogress .spinner, | |
58 | +.nprogress-custom-parent #nprogress .bar { | |
59 | + position: absolute; | |
60 | +} | |
61 | + | |
62 | +@-webkit-keyframes nprogress-spinner { | |
63 | + 0% { -webkit-transform: rotate(0deg); } | |
64 | + 100% { -webkit-transform: rotate(360deg); } | |
65 | +} | |
66 | +@keyframes nprogress-spinner { | |
67 | + 0% { transform: rotate(0deg); } | |
68 | + 100% { transform: rotate(360deg); } | |
69 | +} | |
70 | + |
+++ public/javascripts/lib/nprogress/nprogress.js
... | ... | @@ -0,0 +1,476 @@ |
1 | +/* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress | |
2 | + * @license MIT */ | |
3 | + | |
4 | +;(function(root, factory) { | |
5 | + | |
6 | + if (typeof define === 'function' && define.amd) { | |
7 | + define(factory); | |
8 | + } else if (typeof exports === 'object') { | |
9 | + module.exports = factory(); | |
10 | + } else { | |
11 | + root.NProgress = factory(); | |
12 | + } | |
13 | + | |
14 | +})(this, function() { | |
15 | + var NProgress = {}; | |
16 | + | |
17 | + NProgress.version = '0.1.6'; | |
18 | + | |
19 | + var Settings = NProgress.settings = { | |
20 | + minimum: 0.08, | |
21 | + easing: 'ease', | |
22 | + positionUsing: '', | |
23 | + speed: 200, | |
24 | + trickle: true, | |
25 | + trickleRate: 0.02, | |
26 | + trickleSpeed: 800, | |
27 | + showSpinner: true, | |
28 | + barSelector: '[role="bar"]', | |
29 | + spinnerSelector: '[role="spinner"]', | |
30 | + parent: 'body', | |
31 | + template: '<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>' | |
32 | + }; | |
33 | + | |
34 | + /** | |
35 | + * Updates configuration. | |
36 | + * | |
37 | + * NProgress.configure({ | |
38 | + * minimum: 0.1 | |
39 | + * }); | |
40 | + */ | |
41 | + NProgress.configure = function(options) { | |
42 | + var key, value; | |
43 | + for (key in options) { | |
44 | + value = options[key]; | |
45 | + if (value !== undefined && options.hasOwnProperty(key)) Settings[key] = value; | |
46 | + } | |
47 | + | |
48 | + return this; | |
49 | + }; | |
50 | + | |
51 | + /** | |
52 | + * Last number. | |
53 | + */ | |
54 | + | |
55 | + NProgress.status = null; | |
56 | + | |
57 | + /** | |
58 | + * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`. | |
59 | + * | |
60 | + * NProgress.set(0.4); | |
61 | + * NProgress.set(1.0); | |
62 | + */ | |
63 | + | |
64 | + NProgress.set = function(n) { | |
65 | + var started = NProgress.isStarted(); | |
66 | + | |
67 | + n = clamp(n, Settings.minimum, 1); | |
68 | + NProgress.status = (n === 1 ? null : n); | |
69 | + | |
70 | + var progress = NProgress.render(!started), | |
71 | + bar = progress.querySelector(Settings.barSelector), | |
72 | + speed = Settings.speed, | |
73 | + ease = Settings.easing; | |
74 | + | |
75 | + progress.offsetWidth; /* Repaint */ | |
76 | + | |
77 | + queue(function(next) { | |
78 | + // Set positionUsing if it hasn't already been set | |
79 | + if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS(); | |
80 | + | |
81 | + // Add transition | |
82 | + css(bar, barPositionCSS(n, speed, ease)); | |
83 | + | |
84 | + if (n === 1) { | |
85 | + // Fade out | |
86 | + css(progress, { | |
87 | + transition: 'none', | |
88 | + opacity: 1 | |
89 | + }); | |
90 | + progress.offsetWidth; /* Repaint */ | |
91 | + | |
92 | + setTimeout(function() { | |
93 | + css(progress, { | |
94 | + transition: 'all ' + speed + 'ms linear', | |
95 | + opacity: 0 | |
96 | + }); | |
97 | + setTimeout(function() { | |
98 | + NProgress.remove(); | |
99 | + next(); | |
100 | + }, speed); | |
101 | + }, speed); | |
102 | + } else { | |
103 | + setTimeout(next, speed); | |
104 | + } | |
105 | + }); | |
106 | + | |
107 | + return this; | |
108 | + }; | |
109 | + | |
110 | + NProgress.isStarted = function() { | |
111 | + return typeof NProgress.status === 'number'; | |
112 | + }; | |
113 | + | |
114 | + /** | |
115 | + * Shows the progress bar. | |
116 | + * This is the same as setting the status to 0%, except that it doesn't go backwards. | |
117 | + * | |
118 | + * NProgress.start(); | |
119 | + * | |
120 | + */ | |
121 | + NProgress.start = function() { | |
122 | + if (!NProgress.status) NProgress.set(0); | |
123 | + | |
124 | + var work = function() { | |
125 | + setTimeout(function() { | |
126 | + if (!NProgress.status) return; | |
127 | + NProgress.trickle(); | |
128 | + work(); | |
129 | + }, Settings.trickleSpeed); | |
130 | + }; | |
131 | + | |
132 | + if (Settings.trickle) work(); | |
133 | + | |
134 | + return this; | |
135 | + }; | |
136 | + | |
137 | + /** | |
138 | + * Hides the progress bar. | |
139 | + * This is the *sort of* the same as setting the status to 100%, with the | |
140 | + * difference being `done()` makes some placebo effect of some realistic motion. | |
141 | + * | |
142 | + * NProgress.done(); | |
143 | + * | |
144 | + * If `true` is passed, it will show the progress bar even if its hidden. | |
145 | + * | |
146 | + * NProgress.done(true); | |
147 | + */ | |
148 | + | |
149 | + NProgress.done = function(force) { | |
150 | + if (!force && !NProgress.status) return this; | |
151 | + | |
152 | + return NProgress.inc(0.3 + 0.5 * Math.random()).set(1); | |
153 | + }; | |
154 | + | |
155 | + /** | |
156 | + * Increments by a random amount. | |
157 | + */ | |
158 | + | |
159 | + NProgress.inc = function(amount) { | |
160 | + var n = NProgress.status; | |
161 | + | |
162 | + if (!n) { | |
163 | + return NProgress.start(); | |
164 | + } else { | |
165 | + if (typeof amount !== 'number') { | |
166 | + amount = (1 - n) * clamp(Math.random() * n, 0.1, 0.95); | |
167 | + } | |
168 | + | |
169 | + n = clamp(n + amount, 0, 0.994); | |
170 | + return NProgress.set(n); | |
171 | + } | |
172 | + }; | |
173 | + | |
174 | + NProgress.trickle = function() { | |
175 | + return NProgress.inc(Math.random() * Settings.trickleRate); | |
176 | + }; | |
177 | + | |
178 | + /** | |
179 | + * Waits for all supplied jQuery promises and | |
180 | + * increases the progress as the promises resolve. | |
181 | + * | |
182 | + * @param $promise jQUery Promise | |
183 | + */ | |
184 | + (function() { | |
185 | + var initial = 0, current = 0; | |
186 | + | |
187 | + NProgress.promise = function($promise) { | |
188 | + if (!$promise || $promise.state() == "resolved") { | |
189 | + return this; | |
190 | + } | |
191 | + | |
192 | + if (current == 0) { | |
193 | + NProgress.start(); | |
194 | + } | |
195 | + | |
196 | + initial++; | |
197 | + current++; | |
198 | + | |
199 | + $promise.always(function() { | |
200 | + current--; | |
201 | + if (current == 0) { | |
202 | + initial = 0; | |
203 | + NProgress.done(); | |
204 | + } else { | |
205 | + NProgress.set((initial - current) / initial); | |
206 | + } | |
207 | + }); | |
208 | + | |
209 | + return this; | |
210 | + }; | |
211 | + | |
212 | + })(); | |
213 | + | |
214 | + /** | |
215 | + * (Internal) renders the progress bar markup based on the `template` | |
216 | + * setting. | |
217 | + */ | |
218 | + | |
219 | + NProgress.render = function(fromStart) { | |
220 | + if (NProgress.isRendered()) return document.getElementById('nprogress'); | |
221 | + | |
222 | + addClass(document.documentElement, 'nprogress-busy'); | |
223 | + | |
224 | + var progress = document.createElement('div'); | |
225 | + progress.id = 'nprogress'; | |
226 | + progress.innerHTML = Settings.template; | |
227 | + | |
228 | + var bar = progress.querySelector(Settings.barSelector), | |
229 | + perc = fromStart ? '-100' : toBarPerc(NProgress.status || 0), | |
230 | + parent = document.querySelector(Settings.parent), | |
231 | + spinner; | |
232 | + | |
233 | + css(bar, { | |
234 | + transition: 'all 0 linear', | |
235 | + transform: 'translate3d(' + perc + '%,0,0)' | |
236 | + }); | |
237 | + | |
238 | + if (!Settings.showSpinner) { | |
239 | + spinner = progress.querySelector(Settings.spinnerSelector); | |
240 | + spinner && removeElement(spinner); | |
241 | + } | |
242 | + | |
243 | + if (parent != document.body) { | |
244 | + addClass(parent, 'nprogress-custom-parent'); | |
245 | + } | |
246 | + | |
247 | + parent.appendChild(progress); | |
248 | + return progress; | |
249 | + }; | |
250 | + | |
251 | + /** | |
252 | + * Removes the element. Opposite of render(). | |
253 | + */ | |
254 | + | |
255 | + NProgress.remove = function() { | |
256 | + removeClass(document.documentElement, 'nprogress-busy'); | |
257 | + removeClass(document.querySelector(Settings.parent), 'nprogress-custom-parent') | |
258 | + var progress = document.getElementById('nprogress'); | |
259 | + progress && removeElement(progress); | |
260 | + }; | |
261 | + | |
262 | + /** | |
263 | + * Checks if the progress bar is rendered. | |
264 | + */ | |
265 | + | |
266 | + NProgress.isRendered = function() { | |
267 | + return !!document.getElementById('nprogress'); | |
268 | + }; | |
269 | + | |
270 | + /** | |
271 | + * Determine which positioning CSS rule to use. | |
272 | + */ | |
273 | + | |
274 | + NProgress.getPositioningCSS = function() { | |
275 | + // Sniff on document.body.style | |
276 | + var bodyStyle = document.body.style; | |
277 | + | |
278 | + // Sniff prefixes | |
279 | + var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' : | |
280 | + ('MozTransform' in bodyStyle) ? 'Moz' : | |
281 | + ('msTransform' in bodyStyle) ? 'ms' : | |
282 | + ('OTransform' in bodyStyle) ? 'O' : ''; | |
283 | + | |
284 | + if (vendorPrefix + 'Perspective' in bodyStyle) { | |
285 | + // Modern browsers with 3D support, e.g. Webkit, IE10 | |
286 | + return 'translate3d'; | |
287 | + } else if (vendorPrefix + 'Transform' in bodyStyle) { | |
288 | + // Browsers without 3D support, e.g. IE9 | |
289 | + return 'translate'; | |
290 | + } else { | |
291 | + // Browsers without translate() support, e.g. IE7-8 | |
292 | + return 'margin'; | |
293 | + } | |
294 | + }; | |
295 | + | |
296 | + /** | |
297 | + * Helpers | |
298 | + */ | |
299 | + | |
300 | + function clamp(n, min, max) { | |
301 | + if (n < min) return min; | |
302 | + if (n > max) return max; | |
303 | + return n; | |
304 | + } | |
305 | + | |
306 | + /** | |
307 | + * (Internal) converts a percentage (`0..1`) to a bar translateX | |
308 | + * percentage (`-100%..0%`). | |
309 | + */ | |
310 | + | |
311 | + function toBarPerc(n) { | |
312 | + return (-1 + n) * 100; | |
313 | + } | |
314 | + | |
315 | + | |
316 | + /** | |
317 | + * (Internal) returns the correct CSS for changing the bar's | |
318 | + * position given an n percentage, and speed and ease from Settings | |
319 | + */ | |
320 | + | |
321 | + function barPositionCSS(n, speed, ease) { | |
322 | + var barCSS; | |
323 | + | |
324 | + if (Settings.positionUsing === 'translate3d') { | |
325 | + barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' }; | |
326 | + } else if (Settings.positionUsing === 'translate') { | |
327 | + barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' }; | |
328 | + } else { | |
329 | + barCSS = { 'margin-left': toBarPerc(n)+'%' }; | |
330 | + } | |
331 | + | |
332 | + barCSS.transition = 'all '+speed+'ms '+ease; | |
333 | + | |
334 | + return barCSS; | |
335 | + } | |
336 | + | |
337 | + /** | |
338 | + * (Internal) Queues a function to be executed. | |
339 | + */ | |
340 | + | |
341 | + var queue = (function() { | |
342 | + var pending = []; | |
343 | + | |
344 | + function next() { | |
345 | + var fn = pending.shift(); | |
346 | + if (fn) { | |
347 | + fn(next); | |
348 | + } | |
349 | + } | |
350 | + | |
351 | + return function(fn) { | |
352 | + pending.push(fn); | |
353 | + if (pending.length == 1) next(); | |
354 | + }; | |
355 | + })(); | |
356 | + | |
357 | + /** | |
358 | + * (Internal) Applies css properties to an element, similar to the jQuery | |
359 | + * css method. | |
360 | + * | |
361 | + * While this helper does assist with vendor prefixed property names, it | |
362 | + * does not perform any manipulation of values prior to setting styles. | |
363 | + */ | |
364 | + | |
365 | + var css = (function() { | |
366 | + var cssPrefixes = [ 'Webkit', 'O', 'Moz', 'ms' ], | |
367 | + cssProps = {}; | |
368 | + | |
369 | + function camelCase(string) { | |
370 | + return string.replace(/^-ms-/, 'ms-').replace(/-([\da-z])/gi, function(match, letter) { | |
371 | + return letter.toUpperCase(); | |
372 | + }); | |
373 | + } | |
374 | + | |
375 | + function getVendorProp(name) { | |
376 | + var style = document.body.style; | |
377 | + if (name in style) return name; | |
378 | + | |
379 | + var i = cssPrefixes.length, | |
380 | + capName = name.charAt(0).toUpperCase() + name.slice(1), | |
381 | + vendorName; | |
382 | + while (i--) { | |
383 | + vendorName = cssPrefixes[i] + capName; | |
384 | + if (vendorName in style) return vendorName; | |
385 | + } | |
386 | + | |
387 | + return name; | |
388 | + } | |
389 | + | |
390 | + function getStyleProp(name) { | |
391 | + name = camelCase(name); | |
392 | + return cssProps[name] || (cssProps[name] = getVendorProp(name)); | |
393 | + } | |
394 | + | |
395 | + function applyCss(element, prop, value) { | |
396 | + prop = getStyleProp(prop); | |
397 | + element.style[prop] = value; | |
398 | + } | |
399 | + | |
400 | + return function(element, properties) { | |
401 | + var args = arguments, | |
402 | + prop, | |
403 | + value; | |
404 | + | |
405 | + if (args.length == 2) { | |
406 | + for (prop in properties) { | |
407 | + value = properties[prop]; | |
408 | + if (value !== undefined && properties.hasOwnProperty(prop)) applyCss(element, prop, value); | |
409 | + } | |
410 | + } else { | |
411 | + applyCss(element, args[1], args[2]); | |
412 | + } | |
413 | + } | |
414 | + })(); | |
415 | + | |
416 | + /** | |
417 | + * (Internal) Determines if an element or space separated list of class names contains a class name. | |
418 | + */ | |
419 | + | |
420 | + function hasClass(element, name) { | |
421 | + var list = typeof element == 'string' ? element : classList(element); | |
422 | + return list.indexOf(' ' + name + ' ') >= 0; | |
423 | + } | |
424 | + | |
425 | + /** | |
426 | + * (Internal) Adds a class to an element. | |
427 | + */ | |
428 | + | |
429 | + function addClass(element, name) { | |
430 | + var oldList = classList(element), | |
431 | + newList = oldList + name; | |
432 | + | |
433 | + if (hasClass(oldList, name)) return; | |
434 | + | |
435 | + // Trim the opening space. | |
436 | + element.className = newList.substring(1); | |
437 | + } | |
438 | + | |
439 | + /** | |
440 | + * (Internal) Removes a class from an element. | |
441 | + */ | |
442 | + | |
443 | + function removeClass(element, name) { | |
444 | + var oldList = classList(element), | |
445 | + newList; | |
446 | + | |
447 | + if (!hasClass(element, name)) return; | |
448 | + | |
449 | + // Replace the class name. | |
450 | + newList = oldList.replace(' ' + name + ' ', ' '); | |
451 | + | |
452 | + // Trim the opening and closing spaces. | |
453 | + element.className = newList.substring(1, newList.length - 1); | |
454 | + } | |
455 | + | |
456 | + /** | |
457 | + * (Internal) Gets a space separated list of the class names on the element. | |
458 | + * The list is wrapped with a single space on each end to facilitate finding | |
459 | + * matches within the list. | |
460 | + */ | |
461 | + | |
462 | + function classList(element) { | |
463 | + return (' ' + (element.className || '') + ' ').replace(/\s+/gi, ' '); | |
464 | + } | |
465 | + | |
466 | + /** | |
467 | + * (Internal) Removes an element from the DOM. | |
468 | + */ | |
469 | + | |
470 | + function removeElement(element) { | |
471 | + element && element.parentNode && element.parentNode.removeChild(element); | |
472 | + } | |
473 | + | |
474 | + return NProgress; | |
475 | +}); | |
476 | + |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?