PluginProbe ʕ •ᴥ•ʔ
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI / 3.5.2
Everest Forms – Contact Form, Payment Form, Quiz, Survey & Custom Form Builder with AI v3.5.2
3.5.2 3.5.1 3.5.0 3.4.8 3.4.7 3.4.6 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.5.1 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.10 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.6.1 1.6.7 1.7.0 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.2 1.7.2.1 1.7.2.2 1.7.3 1.7.4 1.7.5 1.7.5.1 1.7.5.2 1.7.6 1.7.7 1.7.7.1 1.7.7.2 1.7.8 1.7.9 1.8.0 1.8.0.1 1.8.1 1.8.2 1.8.2.1 1.8.2.2 1.8.2.3 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.0.1 1.9.1 1.9.2 1.9.3 1.9.4 1.9.4.1 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.0.1 2.0.1 2.0.2 2.0.3 2.0.3.1 2.0.4 2.0.4.1 2.0.5 2.0.6 2.0.7 2.0.8 2.0.8.1 2.0.9 3.0.0 3.0.0.1 3.0.1 3.0.2 3.0.3 3.0.3.1 3.0.4 3.0.4.1 3.0.4.2 3.0.5 3.0.5.1 3.0.5.2 3.0.6 3.0.6.1 3.0.7.1 3.0.8 3.0.8.1 3.0.9 3.0.9.1 3.0.9.2 3.0.9.3 3.0.9.4 3.0.9.5 3.1.0 3.1.1 3.1.2 3.2.0 3.2.1 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.3.0 3.4.0 3.4.1 3.4.2 3.4.2.1 3.4.3 3.4.4 3.4.5 trunk 1.0 1.0.1 1.0.2 1.0.3
everest-forms / assets / js / admin / progressbar.js
everest-forms / assets / js / admin Last commit date
admin.js 3 weeks ago admin.min.js 3 weeks ago chart.js 2 years ago chart.min.js 1 year ago customize-controls.js 1 year ago customize-controls.min.js 1 year ago customize-preview.js 1 year ago customize-preview.min.js 1 year ago deactivation-feedback.js 2 years ago deactivation-feedback.min.js 2 years ago editor.js 7 years ago editor.min.js 5 years ago everest-forms-survey-polls-quiz-builder.js 2 years ago everest-forms-survey-polls-quiz-builder.min.js 2 years ago evf-admin-email.js 2 years ago evf-admin-email.min.js 1 year ago evf-clipboard.js 7 years ago evf-clipboard.min.js 7 years ago evf-enhanced-select.js 3 years ago evf-enhanced-select.min.js 2 years ago evf-file-uploader.js 1 year ago evf-file-uploader.min.js 1 year ago evf-setup.js 1 year ago evf-setup.min.js 1 year ago extensions.js 2 years ago extensions.min.js 2 years ago form-builder.js 6 days ago form-builder.min.js 6 days ago form-template-controller.js 3 years ago form-template-controller.min.js 3 years ago printThis.min.js 2 years ago progressbar.js 2 years ago progressbar.min.js 1 year ago randomColor.js 2 years ago randomColor.min.js 2 years ago settings.js 3 weeks ago settings.min.js 3 weeks ago shortcode-form-embed.js 2 years ago shortcode-form-embed.min.js 2 years ago tool-import-entries.js 2 years ago tool-import-entries.min.js 2 years ago tools.js 3 weeks ago tools.min.js 3 weeks ago upgrade.js 3 weeks ago upgrade.min.js 3 weeks ago
progressbar.js
2484 lines
1 (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ProgressBar = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2 /* shifty - v1.5.3 - 2016-11-29 - http://jeremyckahn.github.io/shifty */
3 ;(function () {
4 var root = this || Function('return this')();
5
6 /**
7 * Shifty Core
8 * By Jeremy Kahn - jeremyckahn@gmail.com
9 */
10
11 var Tweenable = (function () {
12
13 'use strict';
14
15 // Aliases that get defined later in this function
16 var formula;
17
18 // CONSTANTS
19 var DEFAULT_SCHEDULE_FUNCTION;
20 var DEFAULT_EASING = 'linear';
21 var DEFAULT_DURATION = 500;
22 var UPDATE_TIME = 1000 / 60;
23
24 var _now = Date.now
25 ? Date.now
26 : function () {return +new Date();};
27
28 var now = typeof SHIFTY_DEBUG_NOW !== 'undefined' ? SHIFTY_DEBUG_NOW : _now;
29
30 if (typeof window !== 'undefined') {
31 // requestAnimationFrame() shim by Paul Irish (modified for Shifty)
32 // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
33 DEFAULT_SCHEDULE_FUNCTION = window.requestAnimationFrame
34 || window.webkitRequestAnimationFrame
35 || window.oRequestAnimationFrame
36 || window.msRequestAnimationFrame
37 || (window.mozCancelRequestAnimationFrame
38 && window.mozRequestAnimationFrame)
39 || setTimeout;
40 } else {
41 DEFAULT_SCHEDULE_FUNCTION = setTimeout;
42 }
43
44 function noop () {
45 // NOOP!
46 }
47
48 /**
49 * Handy shortcut for doing a for-in loop. This is not a "normal" each
50 * function, it is optimized for Shifty. The iterator function only receives
51 * the property name, not the value.
52 * @param {Object} obj
53 * @param {Function(string)} fn
54 * @private
55 */
56 function each (obj, fn) {
57 var key;
58 for (key in obj) {
59 if (Object.hasOwnProperty.call(obj, key)) {
60 fn(key);
61 }
62 }
63 }
64
65 /**
66 * Perform a shallow copy of Object properties.
67 * @param {Object} targetObject The object to copy into
68 * @param {Object} srcObject The object to copy from
69 * @return {Object} A reference to the augmented `targetObj` Object
70 * @private
71 */
72 function shallowCopy (targetObj, srcObj) {
73 each(srcObj, function (prop) {
74 targetObj[prop] = srcObj[prop];
75 });
76
77 return targetObj;
78 }
79
80 /**
81 * Copies each property from src onto target, but only if the property to
82 * copy to target is undefined.
83 * @param {Object} target Missing properties in this Object are filled in
84 * @param {Object} src
85 * @private
86 */
87 function defaults (target, src) {
88 each(src, function (prop) {
89 if (typeof target[prop] === 'undefined') {
90 target[prop] = src[prop];
91 }
92 });
93 }
94
95 /**
96 * Calculates the interpolated tween values of an Object for a given
97 * timestamp.
98 * @param {Number} forPosition The position to compute the state for.
99 * @param {Object} currentState Current state properties.
100 * @param {Object} originalState: The original state properties the Object is
101 * tweening from.
102 * @param {Object} targetState: The destination state properties the Object
103 * is tweening to.
104 * @param {number} duration: The length of the tween in milliseconds.
105 * @param {number} timestamp: The UNIX epoch time at which the tween began.
106 * @param {Object} easing: This Object's keys must correspond to the keys in
107 * targetState.
108 * @private
109 */
110 function tweenProps (forPosition, currentState, originalState, targetState,
111 duration, timestamp, easing) {
112 var normalizedPosition =
113 forPosition < timestamp ? 0 : (forPosition - timestamp) / duration;
114
115
116 var prop;
117 var easingObjectProp;
118 var easingFn;
119 for (prop in currentState) {
120 if (currentState.hasOwnProperty(prop)) {
121 easingObjectProp = easing[prop];
122 easingFn = typeof easingObjectProp === 'function'
123 ? easingObjectProp
124 : formula[easingObjectProp];
125
126 currentState[prop] = tweenProp(
127 originalState[prop],
128 targetState[prop],
129 easingFn,
130 normalizedPosition
131 );
132 }
133 }
134
135 return currentState;
136 }
137
138 /**
139 * Tweens a single property.
140 * @param {number} start The value that the tween started from.
141 * @param {number} end The value that the tween should end at.
142 * @param {Function} easingFunc The easing curve to apply to the tween.
143 * @param {number} position The normalized position (between 0.0 and 1.0) to
144 * calculate the midpoint of 'start' and 'end' against.
145 * @return {number} The tweened value.
146 * @private
147 */
148 function tweenProp (start, end, easingFunc, position) {
149 return start + (end - start) * easingFunc(position);
150 }
151
152 /**
153 * Applies a filter to Tweenable instance.
154 * @param {Tweenable} tweenable The `Tweenable` instance to call the filter
155 * upon.
156 * @param {String} filterName The name of the filter to apply.
157 * @private
158 */
159 function applyFilter (tweenable, filterName) {
160 var filters = Tweenable.prototype.filter;
161 var args = tweenable._filterArgs;
162
163 each(filters, function (name) {
164 if (typeof filters[name][filterName] !== 'undefined') {
165 filters[name][filterName].apply(tweenable, args);
166 }
167 });
168 }
169
170 var timeoutHandler_endTime;
171 var timeoutHandler_currentTime;
172 var timeoutHandler_isEnded;
173 var timeoutHandler_offset;
174 /**
175 * Handles the update logic for one step of a tween.
176 * @param {Tweenable} tweenable
177 * @param {number} timestamp
178 * @param {number} delay
179 * @param {number} duration
180 * @param {Object} currentState
181 * @param {Object} originalState
182 * @param {Object} targetState
183 * @param {Object} easing
184 * @param {Function(Object, *, number)} step
185 * @param {Function(Function,number)}} schedule
186 * @param {number=} opt_currentTimeOverride Needed for accurate timestamp in
187 * Tweenable#seek.
188 * @private
189 */
190 function timeoutHandler (tweenable, timestamp, delay, duration, currentState,
191 originalState, targetState, easing, step, schedule,
192 opt_currentTimeOverride) {
193
194 timeoutHandler_endTime = timestamp + delay + duration;
195
196 timeoutHandler_currentTime =
197 Math.min(opt_currentTimeOverride || now(), timeoutHandler_endTime);
198
199 timeoutHandler_isEnded =
200 timeoutHandler_currentTime >= timeoutHandler_endTime;
201
202 timeoutHandler_offset = duration - (
203 timeoutHandler_endTime - timeoutHandler_currentTime);
204
205 if (tweenable.isPlaying()) {
206 if (timeoutHandler_isEnded) {
207 step(targetState, tweenable._attachment, timeoutHandler_offset);
208 tweenable.stop(true);
209 } else {
210 tweenable._scheduleId =
211 schedule(tweenable._timeoutHandler, UPDATE_TIME);
212
213 applyFilter(tweenable, 'beforeTween');
214
215 // If the animation has not yet reached the start point (e.g., there was
216 // delay that has not yet completed), just interpolate the starting
217 // position of the tween.
218 if (timeoutHandler_currentTime < (timestamp + delay)) {
219 tweenProps(1, currentState, originalState, targetState, 1, 1, easing);
220 } else {
221 tweenProps(timeoutHandler_currentTime, currentState, originalState,
222 targetState, duration, timestamp + delay, easing);
223 }
224
225 applyFilter(tweenable, 'afterTween');
226
227 step(currentState, tweenable._attachment, timeoutHandler_offset);
228 }
229 }
230 }
231
232
233 /**
234 * Creates a usable easing Object from a string, a function or another easing
235 * Object. If `easing` is an Object, then this function clones it and fills
236 * in the missing properties with `"linear"`.
237 * @param {Object.<string|Function>} fromTweenParams
238 * @param {Object|string|Function} easing
239 * @return {Object.<string|Function>}
240 * @private
241 */
242 function composeEasingObject (fromTweenParams, easing) {
243 var composedEasing = {};
244 var typeofEasing = typeof easing;
245
246 if (typeofEasing === 'string' || typeofEasing === 'function') {
247 each(fromTweenParams, function (prop) {
248 composedEasing[prop] = easing;
249 });
250 } else {
251 each(fromTweenParams, function (prop) {
252 if (!composedEasing[prop]) {
253 composedEasing[prop] = easing[prop] || DEFAULT_EASING;
254 }
255 });
256 }
257
258 return composedEasing;
259 }
260
261 /**
262 * Tweenable constructor.
263 * @class Tweenable
264 * @param {Object=} opt_initialState The values that the initial tween should
265 * start at if a `from` object is not provided to `{{#crossLink
266 * "Tweenable/tween:method"}}{{/crossLink}}` or `{{#crossLink
267 * "Tweenable/setConfig:method"}}{{/crossLink}}`.
268 * @param {Object=} opt_config Configuration object to be passed to
269 * `{{#crossLink "Tweenable/setConfig:method"}}{{/crossLink}}`.
270 * @module Tweenable
271 * @constructor
272 */
273 function Tweenable (opt_initialState, opt_config) {
274 this._currentState = opt_initialState || {};
275 this._configured = false;
276 this._scheduleFunction = DEFAULT_SCHEDULE_FUNCTION;
277
278 // To prevent unnecessary calls to setConfig do not set default
279 // configuration here. Only set default configuration immediately before
280 // tweening if none has been set.
281 if (typeof opt_config !== 'undefined') {
282 this.setConfig(opt_config);
283 }
284 }
285
286 /**
287 * Configure and start a tween.
288 * @method tween
289 * @param {Object=} opt_config Configuration object to be passed to
290 * `{{#crossLink "Tweenable/setConfig:method"}}{{/crossLink}}`.
291 * @chainable
292 */
293 Tweenable.prototype.tween = function (opt_config) {
294 if (this._isTweening) {
295 return this;
296 }
297
298 // Only set default config if no configuration has been set previously and
299 // none is provided now.
300 if (opt_config !== undefined || !this._configured) {
301 this.setConfig(opt_config);
302 }
303
304 this._timestamp = now();
305 this._start(this.get(), this._attachment);
306 return this.resume();
307 };
308
309 /**
310 * Configure a tween that will start at some point in the future.
311 *
312 * @method setConfig
313 * @param {Object} config The following values are valid:
314 * - __from__ (_Object=_): Starting position. If omitted, `{{#crossLink
315 * "Tweenable/get:method"}}get(){{/crossLink}}` is used.
316 * - __to__ (_Object=_): Ending position.
317 * - __duration__ (_number=_): How many milliseconds to animate for.
318 * - __delay__ (_delay=_): How many milliseconds to wait before starting the
319 * tween.
320 * - __start__ (_Function(Object, *)_): Function to execute when the tween
321 * begins. Receives the state of the tween as the first parameter and
322 * `attachment` as the second parameter.
323 * - __step__ (_Function(Object, *, number)_): Function to execute on every
324 * tick. Receives `{{#crossLink
325 * "Tweenable/get:method"}}get(){{/crossLink}}` as the first parameter,
326 * `attachment` as the second parameter, and the time elapsed since the
327 * start of the tween as the third. This function is not called on the
328 * final step of the animation, but `finish` is.
329 * - __finish__ (_Function(Object, *)_): Function to execute upon tween
330 * completion. Receives the state of the tween as the first parameter and
331 * `attachment` as the second parameter.
332 * - __easing__ (_Object.<string|Function>|string|Function=_): Easing curve
333 * name(s) or function(s) to use for the tween.
334 * - __attachment__ (_*_): Cached value that is passed to the
335 * `step`/`start`/`finish` methods.
336 * @chainable
337 */
338 Tweenable.prototype.setConfig = function (config) {
339 config = config || {};
340 this._configured = true;
341
342 // Attach something to this Tweenable instance (e.g.: a DOM element, an
343 // object, a string, etc.);
344 this._attachment = config.attachment;
345
346 // Init the internal state
347 this._pausedAtTime = null;
348 this._scheduleId = null;
349 this._delay = config.delay || 0;
350 this._start = config.start || noop;
351 this._step = config.step || noop;
352 this._finish = config.finish || noop;
353 this._duration = config.duration || DEFAULT_DURATION;
354 this._currentState = shallowCopy({}, config.from || this.get());
355 this._originalState = this.get();
356 this._targetState = shallowCopy({}, config.to || this.get());
357
358 var self = this;
359 this._timeoutHandler = function () {
360 timeoutHandler(self,
361 self._timestamp,
362 self._delay,
363 self._duration,
364 self._currentState,
365 self._originalState,
366 self._targetState,
367 self._easing,
368 self._step,
369 self._scheduleFunction
370 );
371 };
372
373 // Aliases used below
374 var currentState = this._currentState;
375 var targetState = this._targetState;
376
377 // Ensure that there is always something to tween to.
378 defaults(targetState, currentState);
379
380 this._easing = composeEasingObject(
381 currentState, config.easing || DEFAULT_EASING);
382
383 this._filterArgs =
384 [currentState, this._originalState, targetState, this._easing];
385
386 applyFilter(this, 'tweenCreated');
387 return this;
388 };
389
390 /**
391 * @method get
392 * @return {Object} The current state.
393 */
394 Tweenable.prototype.get = function () {
395 return shallowCopy({}, this._currentState);
396 };
397
398 /**
399 * @method set
400 * @param {Object} state The current state.
401 */
402 Tweenable.prototype.set = function (state) {
403 this._currentState = state;
404 };
405
406 /**
407 * Pause a tween. Paused tweens can be resumed from the point at which they
408 * were paused. This is different from `{{#crossLink
409 * "Tweenable/stop:method"}}{{/crossLink}}`, as that method
410 * causes a tween to start over when it is resumed.
411 * @method pause
412 * @chainable
413 */
414 Tweenable.prototype.pause = function () {
415 this._pausedAtTime = now();
416 this._isPaused = true;
417 return this;
418 };
419
420 /**
421 * Resume a paused tween.
422 * @method resume
423 * @chainable
424 */
425 Tweenable.prototype.resume = function () {
426 if (this._isPaused) {
427 this._timestamp += now() - this._pausedAtTime;
428 }
429
430 this._isPaused = false;
431 this._isTweening = true;
432
433 this._timeoutHandler();
434
435 return this;
436 };
437
438 /**
439 * Move the state of the animation to a specific point in the tween's
440 * timeline. If the animation is not running, this will cause the `step`
441 * handlers to be called.
442 * @method seek
443 * @param {millisecond} millisecond The millisecond of the animation to seek
444 * to. This must not be less than `0`.
445 * @chainable
446 */
447 Tweenable.prototype.seek = function (millisecond) {
448 millisecond = Math.max(millisecond, 0);
449 var currentTime = now();
450
451 if ((this._timestamp + millisecond) === 0) {
452 return this;
453 }
454
455 this._timestamp = currentTime - millisecond;
456
457 if (!this.isPlaying()) {
458 this._isTweening = true;
459 this._isPaused = false;
460
461 // If the animation is not running, call timeoutHandler to make sure that
462 // any step handlers are run.
463 timeoutHandler(this,
464 this._timestamp,
465 this._delay,
466 this._duration,
467 this._currentState,
468 this._originalState,
469 this._targetState,
470 this._easing,
471 this._step,
472 this._scheduleFunction,
473 currentTime
474 );
475
476 this.pause();
477 }
478
479 return this;
480 };
481
482 /**
483 * Stops and cancels a tween.
484 * @param {boolean=} gotoEnd If `false` or omitted, the tween just stops at
485 * its current state, and the `finish` handler is not invoked. If `true`,
486 * the tweened object's values are instantly set to the target values, and
487 * `finish` is invoked.
488 * @method stop
489 * @chainable
490 */
491 Tweenable.prototype.stop = function (gotoEnd) {
492 this._isTweening = false;
493 this._isPaused = false;
494 this._timeoutHandler = noop;
495
496 (root.cancelAnimationFrame ||
497 root.webkitCancelAnimationFrame ||
498 root.oCancelAnimationFrame ||
499 root.msCancelAnimationFrame ||
500 root.mozCancelRequestAnimationFrame ||
501 root.clearTimeout)(this._scheduleId);
502
503 if (gotoEnd) {
504 applyFilter(this, 'beforeTween');
505 tweenProps(
506 1,
507 this._currentState,
508 this._originalState,
509 this._targetState,
510 1,
511 0,
512 this._easing
513 );
514 applyFilter(this, 'afterTween');
515 applyFilter(this, 'afterTweenEnd');
516 this._finish.call(this, this._currentState, this._attachment);
517 }
518
519 return this;
520 };
521
522 /**
523 * @method isPlaying
524 * @return {boolean} Whether or not a tween is running.
525 */
526 Tweenable.prototype.isPlaying = function () {
527 return this._isTweening && !this._isPaused;
528 };
529
530 /**
531 * Set a custom schedule function.
532 *
533 * If a custom function is not set,
534 * [`requestAnimationFrame`](https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame)
535 * is used if available, otherwise
536 * [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/Window.setTimeout)
537 * is used.
538 * @method setScheduleFunction
539 * @param {Function(Function,number)} scheduleFunction The function to be
540 * used to schedule the next frame to be rendered.
541 */
542 Tweenable.prototype.setScheduleFunction = function (scheduleFunction) {
543 this._scheduleFunction = scheduleFunction;
544 };
545
546 /**
547 * `delete` all "own" properties. Call this when the `Tweenable` instance
548 * is no longer needed to free memory.
549 * @method dispose
550 */
551 Tweenable.prototype.dispose = function () {
552 var prop;
553 for (prop in this) {
554 if (this.hasOwnProperty(prop)) {
555 delete this[prop];
556 }
557 }
558 };
559
560 /**
561 * Filters are used for transforming the properties of a tween at various
562 * points in a Tweenable's life cycle. See the README for more info on this.
563 * @private
564 */
565 Tweenable.prototype.filter = {};
566
567 /**
568 * This object contains all of the tweens available to Shifty. It is
569 * extensible - simply attach properties to the `Tweenable.prototype.formula`
570 * Object following the same format as `linear`.
571 *
572 * `pos` should be a normalized `number` (between 0 and 1).
573 * @property formula
574 * @type {Object(function)}
575 */
576 Tweenable.prototype.formula = {
577 linear: function (pos) {
578 return pos;
579 }
580 };
581
582 formula = Tweenable.prototype.formula;
583
584 shallowCopy(Tweenable, {
585 'now': now
586 ,'each': each
587 ,'tweenProps': tweenProps
588 ,'tweenProp': tweenProp
589 ,'applyFilter': applyFilter
590 ,'shallowCopy': shallowCopy
591 ,'defaults': defaults
592 ,'composeEasingObject': composeEasingObject
593 });
594
595 // `root` is provided in the intro/outro files.
596
597 // A hook used for unit testing.
598 if (typeof SHIFTY_DEBUG_NOW === 'function') {
599 root.timeoutHandler = timeoutHandler;
600 }
601
602 // Bootstrap Tweenable appropriately for the environment.
603 if (typeof exports === 'object') {
604 // CommonJS
605 module.exports = Tweenable;
606 } else if (typeof define === 'function' && define.amd) {
607 // AMD
608 define(function () {return Tweenable;});
609 } else if (typeof root.Tweenable === 'undefined') {
610 // Browser: Make `Tweenable` globally accessible.
611 root.Tweenable = Tweenable;
612 }
613
614 return Tweenable;
615
616 } ());
617
618 /*!
619 * All equations are adapted from Thomas Fuchs'
620 * [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/penner.js).
621 *
622 * Based on Easing Equations (c) 2003 [Robert
623 * Penner](http://www.robertpenner.com/), all rights reserved. This work is
624 * [subject to terms](http://www.robertpenner.com/easing_terms_of_use.html).
625 */
626
627 /*!
628 * TERMS OF USE - EASING EQUATIONS
629 * Open source under the BSD License.
630 * Easing Equations (c) 2003 Robert Penner, all rights reserved.
631 */
632
633 ;(function () {
634
635 Tweenable.shallowCopy(Tweenable.prototype.formula, {
636 easeInQuad: function (pos) {
637 return Math.pow(pos, 2);
638 },
639
640 easeOutQuad: function (pos) {
641 return -(Math.pow((pos - 1), 2) - 1);
642 },
643
644 easeInOutQuad: function (pos) {
645 if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,2);}
646 return -0.5 * ((pos -= 2) * pos - 2);
647 },
648
649 easeInCubic: function (pos) {
650 return Math.pow(pos, 3);
651 },
652
653 easeOutCubic: function (pos) {
654 return (Math.pow((pos - 1), 3) + 1);
655 },
656
657 easeInOutCubic: function (pos) {
658 if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,3);}
659 return 0.5 * (Math.pow((pos - 2),3) + 2);
660 },
661
662 easeInQuart: function (pos) {
663 return Math.pow(pos, 4);
664 },
665
666 easeOutQuart: function (pos) {
667 return -(Math.pow((pos - 1), 4) - 1);
668 },
669
670 easeInOutQuart: function (pos) {
671 if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,4);}
672 return -0.5 * ((pos -= 2) * Math.pow(pos,3) - 2);
673 },
674
675 easeInQuint: function (pos) {
676 return Math.pow(pos, 5);
677 },
678
679 easeOutQuint: function (pos) {
680 return (Math.pow((pos - 1), 5) + 1);
681 },
682
683 easeInOutQuint: function (pos) {
684 if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,5);}
685 return 0.5 * (Math.pow((pos - 2),5) + 2);
686 },
687
688 easeInSine: function (pos) {
689 return -Math.cos(pos * (Math.PI / 2)) + 1;
690 },
691
692 easeOutSine: function (pos) {
693 return Math.sin(pos * (Math.PI / 2));
694 },
695
696 easeInOutSine: function (pos) {
697 return (-0.5 * (Math.cos(Math.PI * pos) - 1));
698 },
699
700 easeInExpo: function (pos) {
701 return (pos === 0) ? 0 : Math.pow(2, 10 * (pos - 1));
702 },
703
704 easeOutExpo: function (pos) {
705 return (pos === 1) ? 1 : -Math.pow(2, -10 * pos) + 1;
706 },
707
708 easeInOutExpo: function (pos) {
709 if (pos === 0) {return 0;}
710 if (pos === 1) {return 1;}
711 if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(2,10 * (pos - 1));}
712 return 0.5 * (-Math.pow(2, -10 * --pos) + 2);
713 },
714
715 easeInCirc: function (pos) {
716 return -(Math.sqrt(1 - (pos * pos)) - 1);
717 },
718
719 easeOutCirc: function (pos) {
720 return Math.sqrt(1 - Math.pow((pos - 1), 2));
721 },
722
723 easeInOutCirc: function (pos) {
724 if ((pos /= 0.5) < 1) {return -0.5 * (Math.sqrt(1 - pos * pos) - 1);}
725 return 0.5 * (Math.sqrt(1 - (pos -= 2) * pos) + 1);
726 },
727
728 easeOutBounce: function (pos) {
729 if ((pos) < (1 / 2.75)) {
730 return (7.5625 * pos * pos);
731 } else if (pos < (2 / 2.75)) {
732 return (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75);
733 } else if (pos < (2.5 / 2.75)) {
734 return (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375);
735 } else {
736 return (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375);
737 }
738 },
739
740 easeInBack: function (pos) {
741 var s = 1.70158;
742 return (pos) * pos * ((s + 1) * pos - s);
743 },
744
745 easeOutBack: function (pos) {
746 var s = 1.70158;
747 return (pos = pos - 1) * pos * ((s + 1) * pos + s) + 1;
748 },
749
750 easeInOutBack: function (pos) {
751 var s = 1.70158;
752 if ((pos /= 0.5) < 1) {
753 return 0.5 * (pos * pos * (((s *= (1.525)) + 1) * pos - s));
754 }
755 return 0.5 * ((pos -= 2) * pos * (((s *= (1.525)) + 1) * pos + s) + 2);
756 },
757
758 elastic: function (pos) {
759 // jshint maxlen:90
760 return -1 * Math.pow(4,-8 * pos) * Math.sin((pos * 6 - 1) * (2 * Math.PI) / 2) + 1;
761 },
762
763 swingFromTo: function (pos) {
764 var s = 1.70158;
765 return ((pos /= 0.5) < 1) ?
766 0.5 * (pos * pos * (((s *= (1.525)) + 1) * pos - s)) :
767 0.5 * ((pos -= 2) * pos * (((s *= (1.525)) + 1) * pos + s) + 2);
768 },
769
770 swingFrom: function (pos) {
771 var s = 1.70158;
772 return pos * pos * ((s + 1) * pos - s);
773 },
774
775 swingTo: function (pos) {
776 var s = 1.70158;
777 return (pos -= 1) * pos * ((s + 1) * pos + s) + 1;
778 },
779
780 bounce: function (pos) {
781 if (pos < (1 / 2.75)) {
782 return (7.5625 * pos * pos);
783 } else if (pos < (2 / 2.75)) {
784 return (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75);
785 } else if (pos < (2.5 / 2.75)) {
786 return (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375);
787 } else {
788 return (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375);
789 }
790 },
791
792 bouncePast: function (pos) {
793 if (pos < (1 / 2.75)) {
794 return (7.5625 * pos * pos);
795 } else if (pos < (2 / 2.75)) {
796 return 2 - (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75);
797 } else if (pos < (2.5 / 2.75)) {
798 return 2 - (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375);
799 } else {
800 return 2 - (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375);
801 }
802 },
803
804 easeFromTo: function (pos) {
805 if ((pos /= 0.5) < 1) {return 0.5 * Math.pow(pos,4);}
806 return -0.5 * ((pos -= 2) * Math.pow(pos,3) - 2);
807 },
808
809 easeFrom: function (pos) {
810 return Math.pow(pos,4);
811 },
812
813 easeTo: function (pos) {
814 return Math.pow(pos,0.25);
815 }
816 });
817
818 }());
819
820 // jshint maxlen:100
821 /**
822 * The Bezier magic in this file is adapted/copied almost wholesale from
823 * [Scripty2](https://github.com/madrobby/scripty2/blob/master/src/effects/transitions/cubic-bezier.js),
824 * which was adapted from Apple code (which probably came from
825 * [here](http://opensource.apple.com/source/WebCore/WebCore-955.66/platform/graphics/UnitBezier.h)).
826 * Special thanks to Apple and Thomas Fuchs for much of this code.
827 */
828
829 /**
830 * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
831 *
832 * Redistribution and use in source and binary forms, with or without
833 * modification, are permitted provided that the following conditions are met:
834 *
835 * 1. Redistributions of source code must retain the above copyright notice,
836 * this list of conditions and the following disclaimer.
837 *
838 * 2. Redistributions in binary form must reproduce the above copyright notice,
839 * this list of conditions and the following disclaimer in the documentation
840 * and/or other materials provided with the distribution.
841 *
842 * 3. Neither the name of the copyright holder(s) nor the names of any
843 * contributors may be used to endorse or promote products derived from
844 * this software without specific prior written permission.
845 *
846 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
847 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
848 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
849 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
850 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
851 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
852 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
853 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
854 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
855 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
856 * POSSIBILITY OF SUCH DAMAGE.
857 */
858 ;(function () {
859 // port of webkit cubic bezier handling by http://www.netzgesta.de/dev/
860 function cubicBezierAtTime(t,p1x,p1y,p2x,p2y,duration) {
861 var ax = 0,bx = 0,cx = 0,ay = 0,by = 0,cy = 0;
862 function sampleCurveX(t) {
863 return ((ax * t + bx) * t + cx) * t;
864 }
865 function sampleCurveY(t) {
866 return ((ay * t + by) * t + cy) * t;
867 }
868 function sampleCurveDerivativeX(t) {
869 return (3.0 * ax * t + 2.0 * bx) * t + cx;
870 }
871 function solveEpsilon(duration) {
872 return 1.0 / (200.0 * duration);
873 }
874 function solve(x,epsilon) {
875 return sampleCurveY(solveCurveX(x, epsilon));
876 }
877 function fabs(n) {
878 if (n >= 0) {
879 return n;
880 } else {
881 return 0 - n;
882 }
883 }
884 function solveCurveX(x, epsilon) {
885 var t0,t1,t2,x2,d2,i;
886 for (t2 = x, i = 0; i < 8; i++) {
887 x2 = sampleCurveX(t2) - x;
888 if (fabs(x2) < epsilon) {
889 return t2;
890 }
891 d2 = sampleCurveDerivativeX(t2);
892 if (fabs(d2) < 1e-6) {
893 break;
894 }
895 t2 = t2 - x2 / d2;
896 }
897 t0 = 0.0;
898 t1 = 1.0;
899 t2 = x;
900 if (t2 < t0) {
901 return t0;
902 }
903 if (t2 > t1) {
904 return t1;
905 }
906 while (t0 < t1) {
907 x2 = sampleCurveX(t2);
908 if (fabs(x2 - x) < epsilon) {
909 return t2;
910 }
911 if (x > x2) {
912 t0 = t2;
913 }else {
914 t1 = t2;
915 }
916 t2 = (t1 - t0) * 0.5 + t0;
917 }
918 return t2; // Failure.
919 }
920 cx = 3.0 * p1x;
921 bx = 3.0 * (p2x - p1x) - cx;
922 ax = 1.0 - cx - bx;
923 cy = 3.0 * p1y;
924 by = 3.0 * (p2y - p1y) - cy;
925 ay = 1.0 - cy - by;
926 return solve(t, solveEpsilon(duration));
927 }
928 /**
929 * getCubicBezierTransition(x1, y1, x2, y2) -> Function
930 *
931 * Generates a transition easing function that is compatible
932 * with WebKit's CSS transitions `-webkit-transition-timing-function`
933 * CSS property.
934 *
935 * The W3C has more information about CSS3 transition timing functions:
936 * http://www.w3.org/TR/css3-transitions/#transition-timing-function_tag
937 *
938 * @param {number} x1
939 * @param {number} y1
940 * @param {number} x2
941 * @param {number} y2
942 * @return {function}
943 * @private
944 */
945 function getCubicBezierTransition (x1, y1, x2, y2) {
946 return function (pos) {
947 return cubicBezierAtTime(pos,x1,y1,x2,y2,1);
948 };
949 }
950 // End ported code
951
952 /**
953 * Create a Bezier easing function and attach it to `{{#crossLink
954 * "Tweenable/formula:property"}}Tweenable#formula{{/crossLink}}`. This
955 * function gives you total control over the easing curve. Matthew Lein's
956 * [Ceaser](http://matthewlein.com/ceaser/) is a useful tool for visualizing
957 * the curves you can make with this function.
958 * @method setBezierFunction
959 * @param {string} name The name of the easing curve. Overwrites the old
960 * easing function on `{{#crossLink
961 * "Tweenable/formula:property"}}Tweenable#formula{{/crossLink}}` if it
962 * exists.
963 * @param {number} x1
964 * @param {number} y1
965 * @param {number} x2
966 * @param {number} y2
967 * @return {function} The easing function that was attached to
968 * Tweenable.prototype.formula.
969 */
970 Tweenable.setBezierFunction = function (name, x1, y1, x2, y2) {
971 var cubicBezierTransition = getCubicBezierTransition(x1, y1, x2, y2);
972 cubicBezierTransition.displayName = name;
973 cubicBezierTransition.x1 = x1;
974 cubicBezierTransition.y1 = y1;
975 cubicBezierTransition.x2 = x2;
976 cubicBezierTransition.y2 = y2;
977
978 return Tweenable.prototype.formula[name] = cubicBezierTransition;
979 };
980
981
982 /**
983 * `delete` an easing function from `{{#crossLink
984 * "Tweenable/formula:property"}}Tweenable#formula{{/crossLink}}`. Be
985 * careful with this method, as it `delete`s whatever easing formula matches
986 * `name` (which means you can delete standard Shifty easing functions).
987 * @method unsetBezierFunction
988 * @param {string} name The name of the easing function to delete.
989 * @return {function}
990 */
991 Tweenable.unsetBezierFunction = function (name) {
992 delete Tweenable.prototype.formula[name];
993 };
994
995 })();
996
997 ;(function () {
998
999 function getInterpolatedValues (
1000 from, current, targetState, position, easing, delay) {
1001 return Tweenable.tweenProps(
1002 position, current, from, targetState, 1, delay, easing);
1003 }
1004
1005 // Fake a Tweenable and patch some internals. This approach allows us to
1006 // skip uneccessary processing and object recreation, cutting down on garbage
1007 // collection pauses.
1008 var mockTweenable = new Tweenable();
1009 mockTweenable._filterArgs = [];
1010
1011 /**
1012 * Compute the midpoint of two Objects. This method effectively calculates a
1013 * specific frame of animation that `{{#crossLink
1014 * "Tweenable/tween:method"}}{{/crossLink}}` does many times over the course
1015 * of a full tween.
1016 *
1017 * var interpolatedValues = Tweenable.interpolate({
1018 * width: '100px',
1019 * opacity: 0,
1020 * color: '#fff'
1021 * }, {
1022 * width: '200px',
1023 * opacity: 1,
1024 * color: '#000'
1025 * }, 0.5);
1026 *
1027 * console.log(interpolatedValues);
1028 * // {opacity: 0.5, width: "150px", color: "rgb(127,127,127)"}
1029 *
1030 * @static
1031 * @method interpolate
1032 * @param {Object} from The starting values to tween from.
1033 * @param {Object} targetState The ending values to tween to.
1034 * @param {number} position The normalized position value (between `0.0` and
1035 * `1.0`) to interpolate the values between `from` and `to` for. `from`
1036 * represents `0` and `to` represents `1`.
1037 * @param {Object.<string|Function>|string|Function} easing The easing
1038 * curve(s) to calculate the midpoint against. You can reference any easing
1039 * function attached to `Tweenable.prototype.formula`, or provide the easing
1040 * function(s) directly. If omitted, this defaults to "linear".
1041 * @param {number=} opt_delay Optional delay to pad the beginning of the
1042 * interpolated tween with. This increases the range of `position` from (`0`
1043 * through `1`) to (`0` through `1 + opt_delay`). So, a delay of `0.5` would
1044 * increase all valid values of `position` to numbers between `0` and `1.5`.
1045 * @return {Object}
1046 */
1047 Tweenable.interpolate = function (
1048 from, targetState, position, easing, opt_delay) {
1049
1050 var current = Tweenable.shallowCopy({}, from);
1051 var delay = opt_delay || 0;
1052 var easingObject = Tweenable.composeEasingObject(
1053 from, easing || 'linear');
1054
1055 mockTweenable.set({});
1056
1057 // Alias and reuse the _filterArgs array instead of recreating it.
1058 var filterArgs = mockTweenable._filterArgs;
1059 filterArgs.length = 0;
1060 filterArgs[0] = current;
1061 filterArgs[1] = from;
1062 filterArgs[2] = targetState;
1063 filterArgs[3] = easingObject;
1064
1065 // Any defined value transformation must be applied
1066 Tweenable.applyFilter(mockTweenable, 'tweenCreated');
1067 Tweenable.applyFilter(mockTweenable, 'beforeTween');
1068
1069 var interpolatedValues = getInterpolatedValues(
1070 from, current, targetState, position, easingObject, delay);
1071
1072 // Transform values back into their original format
1073 Tweenable.applyFilter(mockTweenable, 'afterTween');
1074
1075 return interpolatedValues;
1076 };
1077
1078 }());
1079
1080 /**
1081 * This module adds string interpolation support to Shifty.
1082 *
1083 * The Token extension allows Shifty to tween numbers inside of strings. Among
1084 * other things, this allows you to animate CSS properties. For example, you
1085 * can do this:
1086 *
1087 * var tweenable = new Tweenable();
1088 * tweenable.tween({
1089 * from: { transform: 'translateX(45px)' },
1090 * to: { transform: 'translateX(90xp)' }
1091 * });
1092 *
1093 * `translateX(45)` will be tweened to `translateX(90)`. To demonstrate:
1094 *
1095 * var tweenable = new Tweenable();
1096 * tweenable.tween({
1097 * from: { transform: 'translateX(45px)' },
1098 * to: { transform: 'translateX(90px)' },
1099 * step: function (state) {
1100 * console.log(state.transform);
1101 * }
1102 * });
1103 *
1104 * The above snippet will log something like this in the console:
1105 *
1106 * translateX(60.3px)
1107 * ...
1108 * translateX(76.05px)
1109 * ...
1110 * translateX(90px)
1111 *
1112 * Another use for this is animating colors:
1113 *
1114 * var tweenable = new Tweenable();
1115 * tweenable.tween({
1116 * from: { color: 'rgb(0,255,0)' },
1117 * to: { color: 'rgb(255,0,255)' },
1118 * step: function (state) {
1119 * console.log(state.color);
1120 * }
1121 * });
1122 *
1123 * The above snippet will log something like this:
1124 *
1125 * rgb(84,170,84)
1126 * ...
1127 * rgb(170,84,170)
1128 * ...
1129 * rgb(255,0,255)
1130 *
1131 * This extension also supports hexadecimal colors, in both long (`#ff00ff`)
1132 * and short (`#f0f`) forms. Be aware that hexadecimal input values will be
1133 * converted into the equivalent RGB output values. This is done to optimize
1134 * for performance.
1135 *
1136 * var tweenable = new Tweenable();
1137 * tweenable.tween({
1138 * from: { color: '#0f0' },
1139 * to: { color: '#f0f' },
1140 * step: function (state) {
1141 * console.log(state.color);
1142 * }
1143 * });
1144 *
1145 * This snippet will generate the same output as the one before it because
1146 * equivalent values were supplied (just in hexadecimal form rather than RGB):
1147 *
1148 * rgb(84,170,84)
1149 * ...
1150 * rgb(170,84,170)
1151 * ...
1152 * rgb(255,0,255)
1153 *
1154 * ## Easing support
1155 *
1156 * Easing works somewhat differently in the Token extension. This is because
1157 * some CSS properties have multiple values in them, and you might need to
1158 * tween each value along its own easing curve. A basic example:
1159 *
1160 * var tweenable = new Tweenable();
1161 * tweenable.tween({
1162 * from: { transform: 'translateX(0px) translateY(0px)' },
1163 * to: { transform: 'translateX(100px) translateY(100px)' },
1164 * easing: { transform: 'easeInQuad' },
1165 * step: function (state) {
1166 * console.log(state.transform);
1167 * }
1168 * });
1169 *
1170 * The above snippet will create values like this:
1171 *
1172 * translateX(11.56px) translateY(11.56px)
1173 * ...
1174 * translateX(46.24px) translateY(46.24px)
1175 * ...
1176 * translateX(100px) translateY(100px)
1177 *
1178 * In this case, the values for `translateX` and `translateY` are always the
1179 * same for each step of the tween, because they have the same start and end
1180 * points and both use the same easing curve. We can also tween `translateX`
1181 * and `translateY` along independent curves:
1182 *
1183 * var tweenable = new Tweenable();
1184 * tweenable.tween({
1185 * from: { transform: 'translateX(0px) translateY(0px)' },
1186 * to: { transform: 'translateX(100px) translateY(100px)' },
1187 * easing: { transform: 'easeInQuad bounce' },
1188 * step: function (state) {
1189 * console.log(state.transform);
1190 * }
1191 * });
1192 *
1193 * The above snippet will create values like this:
1194 *
1195 * translateX(10.89px) translateY(82.35px)
1196 * ...
1197 * translateX(44.89px) translateY(86.73px)
1198 * ...
1199 * translateX(100px) translateY(100px)
1200 *
1201 * `translateX` and `translateY` are not in sync anymore, because `easeInQuad`
1202 * was specified for `translateX` and `bounce` for `translateY`. Mixing and
1203 * matching easing curves can make for some interesting motion in your
1204 * animations.
1205 *
1206 * The order of the space-separated easing curves correspond the token values
1207 * they apply to. If there are more token values than easing curves listed,
1208 * the last easing curve listed is used.
1209 * @submodule Tweenable.token
1210 */
1211
1212 // token function is defined above only so that dox-foundation sees it as
1213 // documentation and renders it. It is never used, and is optimized away at
1214 // build time.
1215
1216 ;(function (Tweenable) {
1217
1218 /**
1219 * @typedef {{
1220 * formatString: string
1221 * chunkNames: Array.<string>
1222 * }}
1223 * @private
1224 */
1225 var formatManifest;
1226
1227 // CONSTANTS
1228
1229 var R_NUMBER_COMPONENT = /(\d|\-|\.)/;
1230 var R_FORMAT_CHUNKS = /([^\-0-9\.]+)/g;
1231 var R_UNFORMATTED_VALUES = /[0-9.\-]+/g;
1232 var R_RGB = new RegExp(
1233 'rgb\\(' + R_UNFORMATTED_VALUES.source +
1234 (/,\s*/.source) + R_UNFORMATTED_VALUES.source +
1235 (/,\s*/.source) + R_UNFORMATTED_VALUES.source + '\\)', 'g');
1236 var R_RGB_PREFIX = /^.*\(/;
1237 var R_HEX = /#([0-9]|[a-f]){3,6}/gi;
1238 var VALUE_PLACEHOLDER = 'VAL';
1239
1240 // HELPERS
1241
1242 /**
1243 * @param {Array.number} rawValues
1244 * @param {string} prefix
1245 *
1246 * @return {Array.<string>}
1247 * @private
1248 */
1249 function getFormatChunksFrom (rawValues, prefix) {
1250 var accumulator = [];
1251
1252 var rawValuesLength = rawValues.length;
1253 var i;
1254
1255 for (i = 0; i < rawValuesLength; i++) {
1256 accumulator.push('_' + prefix + '_' + i);
1257 }
1258
1259 return accumulator;
1260 }
1261
1262 /**
1263 * @param {string} formattedString
1264 *
1265 * @return {string}
1266 * @private
1267 */
1268 function getFormatStringFrom (formattedString) {
1269 var chunks = formattedString.match(R_FORMAT_CHUNKS);
1270
1271 if (!chunks) {
1272 // chunks will be null if there were no tokens to parse in
1273 // formattedString (for example, if formattedString is '2'). Coerce
1274 // chunks to be useful here.
1275 chunks = ['', ''];
1276
1277 // If there is only one chunk, assume that the string is a number
1278 // followed by a token...
1279 // NOTE: This may be an unwise assumption.
1280 } else if (chunks.length === 1 ||
1281 // ...or if the string starts with a number component (".", "-", or a
1282 // digit)...
1283 formattedString.charAt(0).match(R_NUMBER_COMPONENT)) {
1284 // ...prepend an empty string here to make sure that the formatted number
1285 // is properly replaced by VALUE_PLACEHOLDER
1286 chunks.unshift('');
1287 }
1288
1289 return chunks.join(VALUE_PLACEHOLDER);
1290 }
1291
1292 /**
1293 * Convert all hex color values within a string to an rgb string.
1294 *
1295 * @param {Object} stateObject
1296 *
1297 * @return {Object} The modified obj
1298 * @private
1299 */
1300 function sanitizeObjectForHexProps (stateObject) {
1301 Tweenable.each(stateObject, function (prop) {
1302 var currentProp = stateObject[prop];
1303
1304 if (typeof currentProp === 'string' && currentProp.match(R_HEX)) {
1305 stateObject[prop] = sanitizeHexChunksToRGB(currentProp);
1306 }
1307 });
1308 }
1309
1310 /**
1311 * @param {string} str
1312 *
1313 * @return {string}
1314 * @private
1315 */
1316 function sanitizeHexChunksToRGB (str) {
1317 return filterStringChunks(R_HEX, str, convertHexToRGB);
1318 }
1319
1320 /**
1321 * @param {string} hexString
1322 *
1323 * @return {string}
1324 * @private
1325 */
1326 function convertHexToRGB (hexString) {
1327 var rgbArr = hexToRGBArray(hexString);
1328 return 'rgb(' + rgbArr[0] + ',' + rgbArr[1] + ',' + rgbArr[2] + ')';
1329 }
1330
1331 var hexToRGBArray_returnArray = [];
1332 /**
1333 * Convert a hexadecimal string to an array with three items, one each for
1334 * the red, blue, and green decimal values.
1335 *
1336 * @param {string} hex A hexadecimal string.
1337 *
1338 * @returns {Array.<number>} The converted Array of RGB values if `hex` is a
1339 * valid string, or an Array of three 0's.
1340 * @private
1341 */
1342 function hexToRGBArray (hex) {
1343
1344 hex = hex.replace(/#/, '');
1345
1346 // If the string is a shorthand three digit hex notation, normalize it to
1347 // the standard six digit notation
1348 if (hex.length === 3) {
1349 hex = hex.split('');
1350 hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
1351 }
1352
1353 hexToRGBArray_returnArray[0] = hexToDec(hex.substr(0, 2));
1354 hexToRGBArray_returnArray[1] = hexToDec(hex.substr(2, 2));
1355 hexToRGBArray_returnArray[2] = hexToDec(hex.substr(4, 2));
1356
1357 return hexToRGBArray_returnArray;
1358 }
1359
1360 /**
1361 * Convert a base-16 number to base-10.
1362 *
1363 * @param {Number|String} hex The value to convert
1364 *
1365 * @returns {Number} The base-10 equivalent of `hex`.
1366 * @private
1367 */
1368 function hexToDec (hex) {
1369 return parseInt(hex, 16);
1370 }
1371
1372 /**
1373 * Runs a filter operation on all chunks of a string that match a RegExp
1374 *
1375 * @param {RegExp} pattern
1376 * @param {string} unfilteredString
1377 * @param {function(string)} filter
1378 *
1379 * @return {string}
1380 * @private
1381 */
1382 function filterStringChunks (pattern, unfilteredString, filter) {
1383 var pattenMatches = unfilteredString.match(pattern);
1384 var filteredString = unfilteredString.replace(pattern, VALUE_PLACEHOLDER);
1385
1386 if (pattenMatches) {
1387 var pattenMatchesLength = pattenMatches.length;
1388 var currentChunk;
1389
1390 for (var i = 0; i < pattenMatchesLength; i++) {
1391 currentChunk = pattenMatches.shift();
1392 filteredString = filteredString.replace(
1393 VALUE_PLACEHOLDER, filter(currentChunk));
1394 }
1395 }
1396
1397 return filteredString;
1398 }
1399
1400 /**
1401 * Check for floating point values within rgb strings and rounds them.
1402 *
1403 * @param {string} formattedString
1404 *
1405 * @return {string}
1406 * @private
1407 */
1408 function sanitizeRGBChunks (formattedString) {
1409 return filterStringChunks(R_RGB, formattedString, sanitizeRGBChunk);
1410 }
1411
1412 /**
1413 * @param {string} rgbChunk
1414 *
1415 * @return {string}
1416 * @private
1417 */
1418 function sanitizeRGBChunk (rgbChunk) {
1419 var numbers = rgbChunk.match(R_UNFORMATTED_VALUES);
1420 var numbersLength = numbers.length;
1421 var sanitizedString = rgbChunk.match(R_RGB_PREFIX)[0];
1422
1423 for (var i = 0; i < numbersLength; i++) {
1424 sanitizedString += parseInt(numbers[i], 10) + ',';
1425 }
1426
1427 sanitizedString = sanitizedString.slice(0, -1) + ')';
1428
1429 return sanitizedString;
1430 }
1431
1432 /**
1433 * @param {Object} stateObject
1434 *
1435 * @return {Object} An Object of formatManifests that correspond to
1436 * the string properties of stateObject
1437 * @private
1438 */
1439 function getFormatManifests (stateObject) {
1440 var manifestAccumulator = {};
1441
1442 Tweenable.each(stateObject, function (prop) {
1443 var currentProp = stateObject[prop];
1444
1445 if (typeof currentProp === 'string') {
1446 var rawValues = getValuesFrom(currentProp);
1447
1448 manifestAccumulator[prop] = {
1449 'formatString': getFormatStringFrom(currentProp)
1450 ,'chunkNames': getFormatChunksFrom(rawValues, prop)
1451 };
1452 }
1453 });
1454
1455 return manifestAccumulator;
1456 }
1457
1458 /**
1459 * @param {Object} stateObject
1460 * @param {Object} formatManifests
1461 * @private
1462 */
1463 function expandFormattedProperties (stateObject, formatManifests) {
1464 Tweenable.each(formatManifests, function (prop) {
1465 var currentProp = stateObject[prop];
1466 var rawValues = getValuesFrom(currentProp);
1467 var rawValuesLength = rawValues.length;
1468
1469 for (var i = 0; i < rawValuesLength; i++) {
1470 stateObject[formatManifests[prop].chunkNames[i]] = +rawValues[i];
1471 }
1472
1473 delete stateObject[prop];
1474 });
1475 }
1476
1477 /**
1478 * @param {Object} stateObject
1479 * @param {Object} formatManifests
1480 * @private
1481 */
1482 function collapseFormattedProperties (stateObject, formatManifests) {
1483 Tweenable.each(formatManifests, function (prop) {
1484 var currentProp = stateObject[prop];
1485 var formatChunks = extractPropertyChunks(
1486 stateObject, formatManifests[prop].chunkNames);
1487 var valuesList = getValuesList(
1488 formatChunks, formatManifests[prop].chunkNames);
1489 currentProp = getFormattedValues(
1490 formatManifests[prop].formatString, valuesList);
1491 stateObject[prop] = sanitizeRGBChunks(currentProp);
1492 });
1493 }
1494
1495 /**
1496 * @param {Object} stateObject
1497 * @param {Array.<string>} chunkNames
1498 *
1499 * @return {Object} The extracted value chunks.
1500 * @private
1501 */
1502 function extractPropertyChunks (stateObject, chunkNames) {
1503 var extractedValues = {};
1504 var currentChunkName, chunkNamesLength = chunkNames.length;
1505
1506 for (var i = 0; i < chunkNamesLength; i++) {
1507 currentChunkName = chunkNames[i];
1508 extractedValues[currentChunkName] = stateObject[currentChunkName];
1509 delete stateObject[currentChunkName];
1510 }
1511
1512 return extractedValues;
1513 }
1514
1515 var getValuesList_accumulator = [];
1516 /**
1517 * @param {Object} stateObject
1518 * @param {Array.<string>} chunkNames
1519 *
1520 * @return {Array.<number>}
1521 * @private
1522 */
1523 function getValuesList (stateObject, chunkNames) {
1524 getValuesList_accumulator.length = 0;
1525 var chunkNamesLength = chunkNames.length;
1526
1527 for (var i = 0; i < chunkNamesLength; i++) {
1528 getValuesList_accumulator.push(stateObject[chunkNames[i]]);
1529 }
1530
1531 return getValuesList_accumulator;
1532 }
1533
1534 /**
1535 * @param {string} formatString
1536 * @param {Array.<number>} rawValues
1537 *
1538 * @return {string}
1539 * @private
1540 */
1541 function getFormattedValues (formatString, rawValues) {
1542 var formattedValueString = formatString;
1543 var rawValuesLength = rawValues.length;
1544
1545 for (var i = 0; i < rawValuesLength; i++) {
1546 formattedValueString = formattedValueString.replace(
1547 VALUE_PLACEHOLDER, +rawValues[i].toFixed(4));
1548 }
1549
1550 return formattedValueString;
1551 }
1552
1553 /**
1554 * Note: It's the duty of the caller to convert the Array elements of the
1555 * return value into numbers. This is a performance optimization.
1556 *
1557 * @param {string} formattedString
1558 *
1559 * @return {Array.<string>|null}
1560 * @private
1561 */
1562 function getValuesFrom (formattedString) {
1563 return formattedString.match(R_UNFORMATTED_VALUES);
1564 }
1565
1566 /**
1567 * @param {Object} easingObject
1568 * @param {Object} tokenData
1569 * @private
1570 */
1571 function expandEasingObject (easingObject, tokenData) {
1572 Tweenable.each(tokenData, function (prop) {
1573 var currentProp = tokenData[prop];
1574 var chunkNames = currentProp.chunkNames;
1575 var chunkLength = chunkNames.length;
1576
1577 var easing = easingObject[prop];
1578 var i;
1579
1580 if (typeof easing === 'string') {
1581 var easingChunks = easing.split(' ');
1582 var lastEasingChunk = easingChunks[easingChunks.length - 1];
1583
1584 for (i = 0; i < chunkLength; i++) {
1585 easingObject[chunkNames[i]] = easingChunks[i] || lastEasingChunk;
1586 }
1587
1588 } else {
1589 for (i = 0; i < chunkLength; i++) {
1590 easingObject[chunkNames[i]] = easing;
1591 }
1592 }
1593
1594 delete easingObject[prop];
1595 });
1596 }
1597
1598 /**
1599 * @param {Object} easingObject
1600 * @param {Object} tokenData
1601 * @private
1602 */
1603 function collapseEasingObject (easingObject, tokenData) {
1604 Tweenable.each(tokenData, function (prop) {
1605 var currentProp = tokenData[prop];
1606 var chunkNames = currentProp.chunkNames;
1607 var chunkLength = chunkNames.length;
1608
1609 var firstEasing = easingObject[chunkNames[0]];
1610 var typeofEasings = typeof firstEasing;
1611
1612 if (typeofEasings === 'string') {
1613 var composedEasingString = '';
1614
1615 for (var i = 0; i < chunkLength; i++) {
1616 composedEasingString += ' ' + easingObject[chunkNames[i]];
1617 delete easingObject[chunkNames[i]];
1618 }
1619
1620 easingObject[prop] = composedEasingString.substr(1);
1621 } else {
1622 easingObject[prop] = firstEasing;
1623 }
1624 });
1625 }
1626
1627 Tweenable.prototype.filter.token = {
1628 'tweenCreated': function (currentState, fromState, toState, easingObject) {
1629 sanitizeObjectForHexProps(currentState);
1630 sanitizeObjectForHexProps(fromState);
1631 sanitizeObjectForHexProps(toState);
1632 this._tokenData = getFormatManifests(currentState);
1633 },
1634
1635 'beforeTween': function (currentState, fromState, toState, easingObject) {
1636 expandEasingObject(easingObject, this._tokenData);
1637 expandFormattedProperties(currentState, this._tokenData);
1638 expandFormattedProperties(fromState, this._tokenData);
1639 expandFormattedProperties(toState, this._tokenData);
1640 },
1641
1642 'afterTween': function (currentState, fromState, toState, easingObject) {
1643 collapseFormattedProperties(currentState, this._tokenData);
1644 collapseFormattedProperties(fromState, this._tokenData);
1645 collapseFormattedProperties(toState, this._tokenData);
1646 collapseEasingObject(easingObject, this._tokenData);
1647 }
1648 };
1649
1650 } (Tweenable));
1651
1652 }).call(null);
1653
1654 },{}],2:[function(require,module,exports){
1655 // Circle shaped progress bar
1656
1657 var Shape = require('./shape');
1658 var utils = require('./utils');
1659
1660 var Circle = function Circle(container, options) {
1661 // Use two arcs to form a circle
1662 // See this answer http://stackoverflow.com/a/10477334/1446092
1663 this._pathTemplate =
1664 'M 50,50 m 0,-{radius}' +
1665 ' a {radius},{radius} 0 1 1 0,{2radius}' +
1666 ' a {radius},{radius} 0 1 1 0,-{2radius}';
1667
1668 this.containerAspectRatio = 1;
1669
1670 Shape.apply(this, arguments);
1671 };
1672
1673 Circle.prototype = new Shape();
1674 Circle.prototype.constructor = Circle;
1675
1676 Circle.prototype._pathString = function _pathString(opts) {
1677 var widthOfWider = opts.strokeWidth;
1678 if (opts.trailWidth && opts.trailWidth > opts.strokeWidth) {
1679 widthOfWider = opts.trailWidth;
1680 }
1681
1682 var r = 50 - widthOfWider / 2;
1683
1684 return utils.render(this._pathTemplate, {
1685 radius: r,
1686 '2radius': r * 2
1687 });
1688 };
1689
1690 Circle.prototype._trailString = function _trailString(opts) {
1691 return this._pathString(opts);
1692 };
1693
1694 module.exports = Circle;
1695
1696 },{"./shape":7,"./utils":9}],3:[function(require,module,exports){
1697 // Line shaped progress bar
1698
1699 var Shape = require('./shape');
1700 var utils = require('./utils');
1701
1702 var Line = function Line(container, options) {
1703 this._pathTemplate = 'M 0,{center} L 100,{center}';
1704 Shape.apply(this, arguments);
1705 };
1706
1707 Line.prototype = new Shape();
1708 Line.prototype.constructor = Line;
1709
1710 Line.prototype._initializeSvg = function _initializeSvg(svg, opts) {
1711 svg.setAttribute('viewBox', '0 0 100 ' + opts.strokeWidth);
1712 svg.setAttribute('preserveAspectRatio', 'none');
1713 };
1714
1715 Line.prototype._pathString = function _pathString(opts) {
1716 return utils.render(this._pathTemplate, {
1717 center: opts.strokeWidth / 2
1718 });
1719 };
1720
1721 Line.prototype._trailString = function _trailString(opts) {
1722 return this._pathString(opts);
1723 };
1724
1725 module.exports = Line;
1726
1727 },{"./shape":7,"./utils":9}],4:[function(require,module,exports){
1728 module.exports = {
1729 // Higher level API, different shaped progress bars
1730 Line: require('./line'),
1731 Circle: require('./circle'),
1732 SemiCircle: require('./semicircle'),
1733 Square: require('./square'),
1734
1735 // Lower level API to use any SVG path
1736 Path: require('./path'),
1737
1738 // Base-class for creating new custom shapes
1739 // to be in line with the API of built-in shapes
1740 // Undocumented.
1741 Shape: require('./shape'),
1742
1743 // Internal utils, undocumented.
1744 utils: require('./utils')
1745 };
1746
1747 },{"./circle":2,"./line":3,"./path":5,"./semicircle":6,"./shape":7,"./square":8,"./utils":9}],5:[function(require,module,exports){
1748 // Lower level API to animate any kind of svg path
1749
1750 var Tweenable = require('shifty');
1751 var utils = require('./utils');
1752
1753 var EASING_ALIASES = {
1754 easeIn: 'easeInCubic',
1755 easeOut: 'easeOutCubic',
1756 easeInOut: 'easeInOutCubic'
1757 };
1758
1759 var Path = function Path(path, opts) {
1760 // Throw a better error if not initialized with `new` keyword
1761 if (!(this instanceof Path)) {
1762 throw new Error('Constructor was called without new keyword');
1763 }
1764
1765 // Default parameters for animation
1766 opts = utils.extend({
1767 duration: 800,
1768 easing: 'linear',
1769 from: {},
1770 to: {},
1771 step: function() {}
1772 }, opts);
1773
1774 var element;
1775 if (utils.isString(path)) {
1776 element = document.querySelector(path);
1777 } else {
1778 element = path;
1779 }
1780
1781 // Reveal .path as public attribute
1782 this.path = element;
1783 this._opts = opts;
1784 this._tweenable = null;
1785
1786 // Set up the starting positions
1787 var length = this.path.getTotalLength();
1788 this.path.style.strokeDasharray = length + ' ' + length;
1789 this.set(0);
1790 };
1791
1792 Path.prototype.value = function value() {
1793 var offset = this._getComputedDashOffset();
1794 var length = this.path.getTotalLength();
1795
1796 var progress = 1 - offset / length;
1797 // Round number to prevent returning very small number like 1e-30, which
1798 // is practically 0
1799 return parseFloat(progress.toFixed(6), 10);
1800 };
1801
1802 Path.prototype.set = function set(progress) {
1803 this.stop();
1804
1805 this.path.style.strokeDashoffset = this._progressToOffset(progress);
1806
1807 var step = this._opts.step;
1808 if (utils.isFunction(step)) {
1809 var easing = this._easing(this._opts.easing);
1810 var values = this._calculateTo(progress, easing);
1811 var reference = this._opts.shape || this;
1812 step(values, reference, this._opts.attachment);
1813 }
1814 };
1815
1816 Path.prototype.stop = function stop() {
1817 this._stopTween();
1818 this.path.style.strokeDashoffset = this._getComputedDashOffset();
1819 };
1820
1821 // Method introduced here:
1822 // http://jakearchibald.com/2013/animated-line-drawing-svg/
1823 Path.prototype.animate = function animate(progress, opts, cb) {
1824 opts = opts || {};
1825
1826 if (utils.isFunction(opts)) {
1827 cb = opts;
1828 opts = {};
1829 }
1830
1831 var passedOpts = utils.extend({}, opts);
1832
1833 // Copy default opts to new object so defaults are not modified
1834 var defaultOpts = utils.extend({}, this._opts);
1835 opts = utils.extend(defaultOpts, opts);
1836
1837 var shiftyEasing = this._easing(opts.easing);
1838 var values = this._resolveFromAndTo(progress, shiftyEasing, passedOpts);
1839
1840 this.stop();
1841
1842 // Trigger a layout so styles are calculated & the browser
1843 // picks up the starting position before animating
1844 this.path.getBoundingClientRect();
1845
1846 var offset = this._getComputedDashOffset();
1847 var newOffset = this._progressToOffset(progress);
1848
1849 var self = this;
1850 this._tweenable = new Tweenable();
1851 this._tweenable.tween({
1852 from: utils.extend({ offset: offset }, values.from),
1853 to: utils.extend({ offset: newOffset }, values.to),
1854 duration: opts.duration,
1855 easing: shiftyEasing,
1856 step: function(state) {
1857 self.path.style.strokeDashoffset = state.offset;
1858 var reference = opts.shape || self;
1859 opts.step(state, reference, opts.attachment);
1860 },
1861 finish: function(state) {
1862 if (utils.isFunction(cb)) {
1863 cb();
1864 }
1865 }
1866 });
1867 };
1868
1869 Path.prototype._getComputedDashOffset = function _getComputedDashOffset() {
1870 var computedStyle = window.getComputedStyle(this.path, null);
1871 return parseFloat(computedStyle.getPropertyValue('stroke-dashoffset'), 10);
1872 };
1873
1874 Path.prototype._progressToOffset = function _progressToOffset(progress) {
1875 var length = this.path.getTotalLength();
1876 return length - progress * length;
1877 };
1878
1879 // Resolves from and to values for animation.
1880 Path.prototype._resolveFromAndTo = function _resolveFromAndTo(progress, easing, opts) {
1881 if (opts.from && opts.to) {
1882 return {
1883 from: opts.from,
1884 to: opts.to
1885 };
1886 }
1887
1888 return {
1889 from: this._calculateFrom(easing),
1890 to: this._calculateTo(progress, easing)
1891 };
1892 };
1893
1894 // Calculate `from` values from options passed at initialization
1895 Path.prototype._calculateFrom = function _calculateFrom(easing) {
1896 return Tweenable.interpolate(this._opts.from, this._opts.to, this.value(), easing);
1897 };
1898
1899 // Calculate `to` values from options passed at initialization
1900 Path.prototype._calculateTo = function _calculateTo(progress, easing) {
1901 return Tweenable.interpolate(this._opts.from, this._opts.to, progress, easing);
1902 };
1903
1904 Path.prototype._stopTween = function _stopTween() {
1905 if (this._tweenable !== null) {
1906 this._tweenable.stop();
1907 this._tweenable = null;
1908 }
1909 };
1910
1911 Path.prototype._easing = function _easing(easing) {
1912 if (EASING_ALIASES.hasOwnProperty(easing)) {
1913 return EASING_ALIASES[easing];
1914 }
1915
1916 return easing;
1917 };
1918
1919 module.exports = Path;
1920
1921 },{"./utils":9,"shifty":1}],6:[function(require,module,exports){
1922 // Semi-SemiCircle shaped progress bar
1923
1924 var Shape = require('./shape');
1925 var Circle = require('./circle');
1926 var utils = require('./utils');
1927
1928 var SemiCircle = function SemiCircle(container, options) {
1929 // Use one arc to form a SemiCircle
1930 // See this answer http://stackoverflow.com/a/10477334/1446092
1931 this._pathTemplate =
1932 'M 50,50 m -{radius},0' +
1933 ' a {radius},{radius} 0 1 1 {2radius},0';
1934
1935 this.containerAspectRatio = 2;
1936
1937 Shape.apply(this, arguments);
1938 };
1939
1940 SemiCircle.prototype = new Shape();
1941 SemiCircle.prototype.constructor = SemiCircle;
1942
1943 SemiCircle.prototype._initializeSvg = function _initializeSvg(svg, opts) {
1944 svg.setAttribute('viewBox', '0 0 100 50');
1945 };
1946
1947 SemiCircle.prototype._initializeTextContainer = function _initializeTextContainer(
1948 opts,
1949 container,
1950 textContainer
1951 ) {
1952 if (opts.text.style) {
1953 // Reset top style
1954 textContainer.style.top = 'auto';
1955 textContainer.style.bottom = '0';
1956
1957 if (opts.text.alignToBottom) {
1958 utils.setStyle(textContainer, 'transform', 'translate(-50%, 0)');
1959 } else {
1960 utils.setStyle(textContainer, 'transform', 'translate(-50%, 50%)');
1961 }
1962 }
1963 };
1964
1965 // Share functionality with Circle, just have different path
1966 SemiCircle.prototype._pathString = Circle.prototype._pathString;
1967 SemiCircle.prototype._trailString = Circle.prototype._trailString;
1968
1969 module.exports = SemiCircle;
1970
1971 },{"./circle":2,"./shape":7,"./utils":9}],7:[function(require,module,exports){
1972 // Base object for different progress bar shapes
1973
1974 var Path = require('./path');
1975 var utils = require('./utils');
1976
1977 var DESTROYED_ERROR = 'Object is destroyed';
1978
1979 var Shape = function Shape(container, opts) {
1980 // Throw a better error if progress bars are not initialized with `new`
1981 // keyword
1982 if (!(this instanceof Shape)) {
1983 throw new Error('Constructor was called without new keyword');
1984 }
1985
1986 // Prevent calling constructor without parameters so inheritance
1987 // works correctly. To understand, this is how Shape is inherited:
1988 //
1989 // Line.prototype = new Shape();
1990 //
1991 // We just want to set the prototype for Line.
1992 if (arguments.length === 0) {
1993 return;
1994 }
1995
1996 // Default parameters for progress bar creation
1997 this._opts = utils.extend({
1998 color: '#555',
1999 strokeWidth: 1.0,
2000 trailColor: null,
2001 trailWidth: null,
2002 fill: null,
2003 text: {
2004 style: {
2005 color: null,
2006 position: 'absolute',
2007 left: '50%',
2008 top: '50%',
2009 padding: 0,
2010 margin: 0,
2011 transform: {
2012 prefix: true,
2013 value: 'translate(-50%, -50%)'
2014 }
2015 },
2016 autoStyleContainer: true,
2017 alignToBottom: true,
2018 value: null,
2019 className: 'progressbar-text'
2020 },
2021 svgStyle: {
2022 display: 'block',
2023 width: '100%'
2024 },
2025 warnings: false
2026 }, opts, true); // Use recursive extend
2027
2028 // If user specifies e.g. svgStyle or text style, the whole object
2029 // should replace the defaults to make working with styles easier
2030 if (utils.isObject(opts) && opts.svgStyle !== undefined) {
2031 this._opts.svgStyle = opts.svgStyle;
2032 }
2033 if (utils.isObject(opts) && utils.isObject(opts.text) && opts.text.style !== undefined) {
2034 this._opts.text.style = opts.text.style;
2035 }
2036
2037 var svgView = this._createSvgView(this._opts);
2038
2039 var element;
2040 if (utils.isString(container)) {
2041 element = document.querySelector(container);
2042 } else {
2043 element = container;
2044 }
2045
2046 if (!element) {
2047 throw new Error('Container does not exist: ' + container);
2048 }
2049
2050 this._container = element;
2051 this._container.appendChild(svgView.svg);
2052 if (this._opts.warnings) {
2053 this._warnContainerAspectRatio(this._container);
2054 }
2055
2056 if (this._opts.svgStyle) {
2057 utils.setStyles(svgView.svg, this._opts.svgStyle);
2058 }
2059
2060 // Expose public attributes before Path initialization
2061 this.svg = svgView.svg;
2062 this.path = svgView.path;
2063 this.trail = svgView.trail;
2064 this.text = null;
2065
2066 var newOpts = utils.extend({
2067 attachment: undefined,
2068 shape: this
2069 }, this._opts);
2070 this._progressPath = new Path(svgView.path, newOpts);
2071
2072 if (utils.isObject(this._opts.text) && this._opts.text.value !== null) {
2073 this.setText(this._opts.text.value);
2074 }
2075 };
2076
2077 Shape.prototype.animate = function animate(progress, opts, cb) {
2078 if (this._progressPath === null) {
2079 throw new Error(DESTROYED_ERROR);
2080 }
2081
2082 this._progressPath.animate(progress, opts, cb);
2083 };
2084
2085 Shape.prototype.stop = function stop() {
2086 if (this._progressPath === null) {
2087 throw new Error(DESTROYED_ERROR);
2088 }
2089
2090 // Don't crash if stop is called inside step function
2091 if (this._progressPath === undefined) {
2092 return;
2093 }
2094
2095 this._progressPath.stop();
2096 };
2097
2098 Shape.prototype.destroy = function destroy() {
2099 if (this._progressPath === null) {
2100 throw new Error(DESTROYED_ERROR);
2101 }
2102
2103 this.stop();
2104 this.svg.parentNode.removeChild(this.svg);
2105 this.svg = null;
2106 this.path = null;
2107 this.trail = null;
2108 this._progressPath = null;
2109
2110 if (this.text !== null) {
2111 this.text.parentNode.removeChild(this.text);
2112 this.text = null;
2113 }
2114 };
2115
2116 Shape.prototype.set = function set(progress) {
2117 if (this._progressPath === null) {
2118 throw new Error(DESTROYED_ERROR);
2119 }
2120
2121 this._progressPath.set(progress);
2122 };
2123
2124 Shape.prototype.value = function value() {
2125 if (this._progressPath === null) {
2126 throw new Error(DESTROYED_ERROR);
2127 }
2128
2129 if (this._progressPath === undefined) {
2130 return 0;
2131 }
2132
2133 return this._progressPath.value();
2134 };
2135
2136 Shape.prototype.setText = function setText(newText) {
2137 if (this._progressPath === null) {
2138 throw new Error(DESTROYED_ERROR);
2139 }
2140
2141 if (this.text === null) {
2142 // Create new text node
2143 this.text = this._createTextContainer(this._opts, this._container);
2144 this._container.appendChild(this.text);
2145 }
2146
2147 // Remove previous text and add new
2148 if (utils.isObject(newText)) {
2149 utils.removeChildren(this.text);
2150 this.text.appendChild(newText);
2151 } else {
2152 this.text.innerHTML = newText;
2153 }
2154 };
2155
2156 Shape.prototype._createSvgView = function _createSvgView(opts) {
2157 var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
2158 this._initializeSvg(svg, opts);
2159
2160 var trailPath = null;
2161 // Each option listed in the if condition are 'triggers' for creating
2162 // the trail path
2163 if (opts.trailColor || opts.trailWidth) {
2164 trailPath = this._createTrail(opts);
2165 svg.appendChild(trailPath);
2166 }
2167
2168 var path = this._createPath(opts);
2169 svg.appendChild(path);
2170
2171 return {
2172 svg: svg,
2173 path: path,
2174 trail: trailPath
2175 };
2176 };
2177
2178 Shape.prototype._initializeSvg = function _initializeSvg(svg, opts) {
2179 svg.setAttribute('viewBox', '0 0 100 100');
2180 };
2181
2182 Shape.prototype._createPath = function _createPath(opts) {
2183 var pathString = this._pathString(opts);
2184 return this._createPathElement(pathString, opts);
2185 };
2186
2187 Shape.prototype._createTrail = function _createTrail(opts) {
2188 // Create path string with original passed options
2189 var pathString = this._trailString(opts);
2190
2191 // Prevent modifying original
2192 var newOpts = utils.extend({}, opts);
2193
2194 // Defaults for parameters which modify trail path
2195 if (!newOpts.trailColor) {
2196 newOpts.trailColor = '#eee';
2197 }
2198 if (!newOpts.trailWidth) {
2199 newOpts.trailWidth = newOpts.strokeWidth;
2200 }
2201
2202 newOpts.color = newOpts.trailColor;
2203 newOpts.strokeWidth = newOpts.trailWidth;
2204
2205 // When trail path is set, fill must be set for it instead of the
2206 // actual path to prevent trail stroke from clipping
2207 newOpts.fill = null;
2208
2209 return this._createPathElement(pathString, newOpts);
2210 };
2211
2212 Shape.prototype._createPathElement = function _createPathElement(pathString, opts) {
2213 var path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
2214 path.setAttribute('d', pathString);
2215 path.setAttribute('stroke', opts.color);
2216 path.setAttribute('stroke-width', opts.strokeWidth);
2217
2218 if (opts.fill) {
2219 path.setAttribute('fill', opts.fill);
2220 } else {
2221 path.setAttribute('fill-opacity', '0');
2222 }
2223
2224 return path;
2225 };
2226
2227 Shape.prototype._createTextContainer = function _createTextContainer(opts, container) {
2228 var textContainer = document.createElement('div');
2229 textContainer.className = opts.text.className;
2230
2231 var textStyle = opts.text.style;
2232 if (textStyle) {
2233 if (opts.text.autoStyleContainer) {
2234 container.style.position = 'relative';
2235 }
2236
2237 utils.setStyles(textContainer, textStyle);
2238 // Default text color to progress bar's color
2239 if (!textStyle.color) {
2240 textContainer.style.color = opts.color;
2241 }
2242 }
2243
2244 this._initializeTextContainer(opts, container, textContainer);
2245 return textContainer;
2246 };
2247
2248 // Give custom shapes possibility to modify text element
2249 Shape.prototype._initializeTextContainer = function(opts, container, element) {
2250 // By default, no-op
2251 // Custom shapes should respect API options, such as text.style
2252 };
2253
2254 Shape.prototype._pathString = function _pathString(opts) {
2255 throw new Error('Override this function for each progress bar');
2256 };
2257
2258 Shape.prototype._trailString = function _trailString(opts) {
2259 throw new Error('Override this function for each progress bar');
2260 };
2261
2262 Shape.prototype._warnContainerAspectRatio = function _warnContainerAspectRatio(container) {
2263 if (!this.containerAspectRatio) {
2264 return;
2265 }
2266
2267 var computedStyle = window.getComputedStyle(container, null);
2268 var width = parseFloat(computedStyle.getPropertyValue('width'), 10);
2269 var height = parseFloat(computedStyle.getPropertyValue('height'), 10);
2270 if (!utils.floatEquals(this.containerAspectRatio, width / height)) {
2271 console.warn(
2272 'Incorrect aspect ratio of container',
2273 '#' + container.id,
2274 'detected:',
2275 computedStyle.getPropertyValue('width') + '(width)',
2276 '/',
2277 computedStyle.getPropertyValue('height') + '(height)',
2278 '=',
2279 width / height
2280 );
2281
2282 console.warn(
2283 'Aspect ratio of should be',
2284 this.containerAspectRatio
2285 );
2286 }
2287 };
2288
2289 module.exports = Shape;
2290
2291 },{"./path":5,"./utils":9}],8:[function(require,module,exports){
2292 // Square shaped progress bar
2293 // Note: Square is not core part of API anymore. It's left here
2294 // for reference. square is not included to the progressbar
2295 // build anymore
2296
2297 var Shape = require('./shape');
2298 var utils = require('./utils');
2299
2300 var Square = function Square(container, options) {
2301 this._pathTemplate =
2302 'M 0,{halfOfStrokeWidth}' +
2303 ' L {width},{halfOfStrokeWidth}' +
2304 ' L {width},{width}' +
2305 ' L {halfOfStrokeWidth},{width}' +
2306 ' L {halfOfStrokeWidth},{strokeWidth}';
2307
2308 this._trailTemplate =
2309 'M {startMargin},{halfOfStrokeWidth}' +
2310 ' L {width},{halfOfStrokeWidth}' +
2311 ' L {width},{width}' +
2312 ' L {halfOfStrokeWidth},{width}' +
2313 ' L {halfOfStrokeWidth},{halfOfStrokeWidth}';
2314
2315 Shape.apply(this, arguments);
2316 };
2317
2318 Square.prototype = new Shape();
2319 Square.prototype.constructor = Square;
2320
2321 Square.prototype._pathString = function _pathString(opts) {
2322 var w = 100 - opts.strokeWidth / 2;
2323
2324 return utils.render(this._pathTemplate, {
2325 width: w,
2326 strokeWidth: opts.strokeWidth,
2327 halfOfStrokeWidth: opts.strokeWidth / 2
2328 });
2329 };
2330
2331 Square.prototype._trailString = function _trailString(opts) {
2332 var w = 100 - opts.strokeWidth / 2;
2333
2334 return utils.render(this._trailTemplate, {
2335 width: w,
2336 strokeWidth: opts.strokeWidth,
2337 halfOfStrokeWidth: opts.strokeWidth / 2,
2338 startMargin: opts.strokeWidth / 2 - opts.trailWidth / 2
2339 });
2340 };
2341
2342 module.exports = Square;
2343
2344 },{"./shape":7,"./utils":9}],9:[function(require,module,exports){
2345 // Utility functions
2346
2347 var PREFIXES = 'Webkit Moz O ms'.split(' ');
2348 var FLOAT_COMPARISON_EPSILON = 0.001;
2349
2350 // Copy all attributes from source object to destination object.
2351 // destination object is mutated.
2352 function extend(destination, source, recursive) {
2353 destination = destination || {};
2354 source = source || {};
2355 recursive = recursive || false;
2356
2357 for (var attrName in source) {
2358 if (source.hasOwnProperty(attrName)) {
2359 var destVal = destination[attrName];
2360 var sourceVal = source[attrName];
2361 if (recursive && isObject(destVal) && isObject(sourceVal)) {
2362 destination[attrName] = extend(destVal, sourceVal, recursive);
2363 } else {
2364 destination[attrName] = sourceVal;
2365 }
2366 }
2367 }
2368
2369 return destination;
2370 }
2371
2372 // Renders templates with given variables. Variables must be surrounded with
2373 // braces without any spaces, e.g. {variable}
2374 // All instances of variable placeholders will be replaced with given content
2375 // Example:
2376 // render('Hello, {message}!', {message: 'world'})
2377 function render(template, vars) {
2378 var rendered = template;
2379
2380 for (var key in vars) {
2381 if (vars.hasOwnProperty(key)) {
2382 var val = vars[key];
2383 var regExpString = '\\{' + key + '\\}';
2384 var regExp = new RegExp(regExpString, 'g');
2385
2386 rendered = rendered.replace(regExp, val);
2387 }
2388 }
2389
2390 return rendered;
2391 }
2392
2393 function setStyle(element, style, value) {
2394 var elStyle = element.style; // cache for performance
2395
2396 for (var i = 0; i < PREFIXES.length; ++i) {
2397 var prefix = PREFIXES[i];
2398 elStyle[prefix + capitalize(style)] = value;
2399 }
2400
2401 elStyle[style] = value;
2402 }
2403
2404 function setStyles(element, styles) {
2405 forEachObject(styles, function(styleValue, styleName) {
2406 // Allow disabling some individual styles by setting them
2407 // to null or undefined
2408 if (styleValue === null || styleValue === undefined) {
2409 return;
2410 }
2411
2412 // If style's value is {prefix: true, value: '50%'},
2413 // Set also browser prefixed styles
2414 if (isObject(styleValue) && styleValue.prefix === true) {
2415 setStyle(element, styleName, styleValue.value);
2416 } else {
2417 element.style[styleName] = styleValue;
2418 }
2419 });
2420 }
2421
2422 function capitalize(text) {
2423 return text.charAt(0).toUpperCase() + text.slice(1);
2424 }
2425
2426 function isString(obj) {
2427 return typeof obj === 'string' || obj instanceof String;
2428 }
2429
2430 function isFunction(obj) {
2431 return typeof obj === 'function';
2432 }
2433
2434 function isArray(obj) {
2435 return Object.prototype.toString.call(obj) === '[object Array]';
2436 }
2437
2438 // Returns true if `obj` is object as in {a: 1, b: 2}, not if it's function or
2439 // array
2440 function isObject(obj) {
2441 if (isArray(obj)) {
2442 return false;
2443 }
2444
2445 var type = typeof obj;
2446 return type === 'object' && !!obj;
2447 }
2448
2449 function forEachObject(object, callback) {
2450 for (var key in object) {
2451 if (object.hasOwnProperty(key)) {
2452 var val = object[key];
2453 callback(val, key);
2454 }
2455 }
2456 }
2457
2458 function floatEquals(a, b) {
2459 return Math.abs(a - b) < FLOAT_COMPARISON_EPSILON;
2460 }
2461
2462 // https://coderwall.com/p/nygghw/don-t-use-innerhtml-to-empty-dom-elements
2463 function removeChildren(el) {
2464 while (el.firstChild) {
2465 el.removeChild(el.firstChild);
2466 }
2467 }
2468
2469 module.exports = {
2470 extend: extend,
2471 render: render,
2472 setStyle: setStyle,
2473 setStyles: setStyles,
2474 capitalize: capitalize,
2475 isString: isString,
2476 isFunction: isFunction,
2477 isObject: isObject,
2478 forEachObject: forEachObject,
2479 floatEquals: floatEquals,
2480 removeChildren: removeChildren
2481 };
2482
2483 },{}]},{},[4])(4)
2484 });