PageSourceSearch

https://www.chilischarf.at/typo3temp/assets/compressed/merged-591a…90909262c96a0fef252a4b10.js.gzip?1704293055

js chilischarf.at collected 2026-10-04 12:17:28 UTC 46,286 bytes, 1,165 lines download raw bytes

vendor: 38,013 bytes, lines 1-1139
1
2/**
3 * vivus - JavaScript library to make drawing animation on SVG
4 * @version v0.4.5
5 * @link https://github.com/maxwellito/vivus
6 * @license MIT
7 */
8
9(function () {
10
11    'use strict';
12
13    /**
14     * Pathformer
15     * Beta version
16     *
17     * Take any SVG version 1.1 and transform
18     * child elements to 'path' elements
19     *
20     * This code is purely forked from
21     * https://github.com/Waest/SVGPathConverter
22     */
23
24    /**
25     * Class constructor
26     *
27     * @param {DOM|String} element Dom element of the SVG or id of it
28     */
29    function Pathformer(element) {
30        // Test params
31        if (typeof element === 'undefined') {
32            throw new Error('Pathformer [constructor]: "element" parameter is required');
33        }
34
35        // Set the element
36        if (element.constructor === String) {
37            element = document.getElementById(element);
38            if (!element) {
39                throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID');
40            }
41        }
42        if (element instanceof window.SVGElement ||
43            element instanceof window.SVGGElement ||
44            /^svg$/i.test(element.nodeName)) {
45            this.el = element;
46        } else {
47            throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement');
48        }
49
50        // Start
51        this.scan(element);
52    }
53
54    /**
55     * List of tags which can be transformed
56     * to path elements
57     *
58     * @type {Array}
59     */
60    Pathformer.prototype.TYPES = ['line', 'ellipse', 'circle', 'polygon', 'polyline', 'rect'];
61
62    /**
63     * List of attribute names which contain
64     * data. This array list them to check if
65     * they contain bad values, like percentage.
66     *
67     * @type {Array}
68     */
69    Pathformer.prototype.ATTR_WATCH = ['cx', 'cy', 'points', 'r', 'rx', 'ry', 'x', 'x1', 'x2', 'y', 'y1', 'y2'];
70
71    /**
72     * Finds the elements compatible for transform
73     * and apply the liked method
74     *
75     * @param  {object} options Object from the constructor
76     */
77    Pathformer.prototype.scan = function (svg) {
78        var fn, element, pathData, pathDom,
79            elements = svg.querySelectorAll(this.TYPES.join(','));
80
81        for (var i = 0; i < elements.length; i++) {
82            element = elements[i];
83            fn = this[element.tagName.toLowerCase() + 'ToPath'];
84            pathData = fn(this.parseAttr(element.attributes));
85            pathDom = this.pathMaker(element, pathData);
86            element.parentNode.replaceChild(pathDom, element);
87        }
88    };
89
90
91    /**
92     * Read `line` element to extract and transform
93     * data, to make it ready for a `path` object.
94     *
95     * @param  {DOMelement} element Line element to transform
96     * @return {object}             Data for a `path` element
97     */
98    Pathformer.prototype.lineToPath = function (element) {
99        var newElement = {},
100            x1 = element.x1 || 0,
101            y1 = element.y1 || 0,
102            x2 = element.x2 || 0,
103            y2 = element.y2 || 0;
104
105        newElement.d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2;
106        return newElement;
107    };
108
109    /**
110     * Read `rect` element to extract and transform
111     * data, to make it ready for a `path` object.
112     * The radius-border is not taken in charge yet.
113     * (your help is more than welcomed)
114     *
115     * @param  {DOMelement} element Rect element to transform
116     * @return {object}             Data for a `path` element
117     */
118    Pathformer.prototype.rectToPath = function (element) {
119        var newElement = {},
120            x      = parseFloat(element.x)      || 0,
121            y      = parseFloat(element.y)      || 0,
122            width  = parseFloat(element.width)  || 0,
123            height = parseFloat(element.height) || 0;
124
125        if (element.rx || element.ry) {
126            var rx = parseInt(element.rx, 10) || -1,
127                ry = parseInt(element.ry, 10) || -1;
128            rx = Math.min(Math.max(rx < 0 ? ry : rx, 0), width/2);
129            ry = Math.min(Math.max(ry < 0 ? rx : ry, 0), height/2);
130
131            newElement.d = 'M ' + (x + rx) + ',' + y + ' ' +
132                'L ' + (x + width - rx) + ',' + y + ' ' +
133                'A ' + rx + ',' + ry + ',0,0,1,' + (x + width) + ',' + (y + ry) + ' ' +
134                'L ' + (x + width) + ',' + (y + height - ry) + ' ' +
135                'A ' + rx + ',' + ry + ',0,0,1,' + (x + width - rx) + ',' + (y + height) + ' ' +
136                'L ' + (x + rx) + ',' + (y + height) + ' ' +
137                'A ' + rx + ',' + ry + ',0,0,1,' + x + ',' + (y + height - ry) + ' ' +
138                'L ' + x + ',' + (y + ry) + ' ' +
139                'A ' + rx + ',' + ry + ',0,0,1,' + (x + rx) + ',' + y;
140        }
141        else {
142            newElement.d = 'M' + x + ' ' + y + ' ' +
143                'L' + (x + width) + ' ' + y + ' ' +
144                'L' + (x + width) + ' ' + (y + height) + ' ' +
145                'L' + x + ' ' + (y + height) + ' Z';
146        }
147        return newElement;
148    };
149
150    /**
151     * Read `polyline` element to extract and transform
152     * data, to make it ready for a `path` object.
153     *
154     * @param  {DOMelement} element Polyline element to transform
155     * @return {object}             Data for a `path` element
156     */
157    Pathformer.prototype.polylineToPath = function (element) {
158        var newElement = {},
159            points = element.points.trim().split(' '),
160            i, path;
161
162        // Reformatting if points are defined without commas
163        if (element.points.indexOf(',') === -1) {
164            var formattedPoints = [];
165            for (i = 0; i < points.length; i+=2) {
166                formattedPoints.push(points[i] + ',' + points[i+1]);
167            }
168            points = formattedPoints;
169        }
170
171        // Generate the path.d value
172        path = 'M' + points[0];
173        for(i = 1; i < points.length; i++) {
174            if (points[i].indexOf(',') !== -1) {
175                path += 'L' + points[i];
176            }
177        }
178        newElement.d = path;
179        return newElement;
180    };
181
182    /**
183     * Read `polygon` element to extract and transform
184     * data, to make it ready for a `path` object.
185     * This method rely on polylineToPath, because the
186     * logic is similar. The path created is just closed,
187     * so it needs an 'Z' at the end.
188     *
189     * @param  {DOMelement} element Polygon element to transform
190     * @return {object}             Data for a `path` element
191     */
192    Pathformer.prototype.polygonToPath = function (element) {
193        var newElement = Pathformer.prototype.polylineToPath(element);
194
195        newElement.d += 'Z';
196        return newElement;
197    };
198
199    /**
200     * Read `ellipse` element to extract and transform
201     * data, to make it ready for a `path` object.
202     *
203     * @param  {DOMelement} element ellipse element to transform
204     * @return {object}             Data for a `path` element
205     */
206    Pathformer.prototype.ellipseToPath = function (element) {
207        var newElement = {},
208            rx = parseFloat(element.rx) || 0,
209            ry = parseFloat(element.ry) || 0,
210            cx = parseFloat(element.cx) || 0,
211            cy = parseFloat(element.cy) || 0,
212            startX = cx - rx,
213            startY = cy,
214            endX = parseFloat(cx) + parseFloat(rx),
215            endY = cy;
216
217        newElement.d = 'M' + startX + ',' + startY +
218            'A' + rx + ',' + ry + ' 0,1,1 ' + endX + ',' + endY +
219            'A' + rx + ',' + ry + ' 0,1,1 ' + startX + ',' + endY;
220        return newElement;
221    };
222
223    /**
224     * Read `circle` element to extract and transform
225     * data, to make it ready for a `path` object.
226     *
227     * @param  {DOMelement} element Circle element to transform
228     * @return {object}             Data for a `path` element
229     */
230    Pathformer.prototype.circleToPath = function (element) {
231        var newElement = {},
232            r  = parseFloat(element.r)  || 0,
233            cx = parseFloat(element.cx) || 0,
234            cy = parseFloat(element.cy) || 0,
235            startX = cx - r,
236            startY = cy,
237            endX = parseFloat(cx) + parseFloat(r),
238            endY = cy;
239
240        newElement.d =  'M' + startX + ',' + startY +
241            'A' + r + ',' + r + ' 0,1,1 ' + endX + ',' + endY +
242            'A' + r + ',' + r + ' 0,1,1 ' + startX + ',' + endY;
243        return newElement;
244    };
245
246    /**
247     * Create `path` elements form original element
248     * and prepared objects
249     *
250     * @param  {DOMelement} element  Original element to transform
251     * @param  {object} pathData     Path data (from `toPath` methods)
252     * @return {DOMelement}          Path element
253     */
254    Pathformer.prototype.pathMaker = function (element, pathData) {
255        var i, attr, pathTag = document.createElementNS('http://www.w3.org/2000/svg','path');
256        for(i = 0; i < element.attributes.length; i++) {
257            attr = element.attributes[i];
258            if (this.ATTR_WATCH.indexOf(attr.name) === -1) {
259                pathTag.setAttribute(attr.name, attr.value);
260            }
261        }
262        for(i in pathData) {
263            pathTag.setAttribute(i, pathData[i]);
264        }
265        return pathTag;
266    };
267
268    /**
269     * Parse attributes of a DOM element to
270     * get an object of attribute => value
271     *
272     * @param  {NamedNodeMap} attributes Attributes object from DOM element to parse
273     * @return {object}                  Object of attributes
274     */
275    Pathformer.prototype.parseAttr = function (element) {
276        var attr, output = {};
277        for (var i = 0; i < element.length; i++) {
278            attr = element[i];
279            // Check if no data attribute contains '%', or the transformation is impossible
280            if (this.ATTR_WATCH.indexOf(attr.name) !== -1 && attr.value.indexOf('%') !== -1) {
281                throw new Error('Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into \'path\' tags. Please use \'viewBox\'.');
282            }
283            output[attr.name] = attr.value;
284        }
285        return output;
286    };
287
288    'use strict';
289
290    var setupEnv, requestAnimFrame, cancelAnimFrame, parsePositiveInt;
291
292    /**
293     * Vivus
294     * Beta version
295     *
296     * Take any SVG and make the animation
297     * to give give the impression of live drawing
298     *
299     * This in more than just inspired from codrops
300     * At that point, it's a pure fork.
301     */
302
303    /**
304     * Class constructor
305     * option structure
306     *   type: 'delayed'|'sync'|'oneByOne'|'script' (to know if the items must be drawn synchronously or not, default: delayed)
307     *   duration: <int> (in frames)
308     *   start: 'inViewport'|'manual'|'autostart' (start automatically the animation, default: inViewport)
309     *   delay: <int> (delay between the drawing of first and last path)
310     *   dashGap <integer> whitespace extra margin between dashes
311     *   pathTimingFunction <function> timing animation function for each path element of the SVG
312     *   animTimingFunction <function> timing animation function for the complete SVG
313     *   forceRender <boolean> force the browser to re-render all updated path items
314     *   selfDestroy <boolean> removes all extra styling on the SVG, and leaves it as original
315     *
316     * The attribute 'type' is by default on 'delayed'.
317     *  - 'delayed'
318     *    all paths are draw at the same time but with a
319     *    little delay between them before start
320     *  - 'sync'
321     *    all path are start and finish at the same time
322     *  - 'oneByOne'
323     *    only one path is draw at the time
324     *    the end of the first one will trigger the draw
325     *    of the next one
326     *
327     * All these values can be overwritten individually
328     * for each path item in the SVG
329     * The value of frames will always take the advantage of
330     * the duration value.
331     * If you fail somewhere, an error will be thrown.
332     * Good luck.
333     *
334     * @constructor
335     * @this {Vivus}
336     * @param {DOM|String}   element  Dom element of the SVG or id of it
337     * @param {Object}       options  Options about the animation
338     * @param {Function}     callback Callback for the end of the animation
339     */
340    function Vivus(element, options, callback) {
341        setupEnv();
342
343        // Setup
344        this.isReady = false;
345        this.setElement(element, options);
346        this.setOptions(options);
347        this.setCallback(callback);
348
349        if (this.isReady) {
350            this.init();
351        }
352    }
353
354    /**
355     * Timing functions
356     **************************************
357     *
358     * Default functions to help developers.
359     * It always take a number as parameter (between 0 to 1) then
360     * return a number (between 0 and 1)
361     */
362    Vivus.LINEAR = function(x) {
363        return x;
364    };
365    Vivus.EASE = function(x) {
366        return -Math.cos(x * Math.PI) / 2 + 0.5;
367    };
368    Vivus.EASE_OUT = function(x) {
369        return 1 - Math.pow(1 - x, 3);
370    };
371    Vivus.EASE_IN = function(x) {
372        return Math.pow(x, 3);
373    };
374    Vivus.EASE_OUT_BOUNCE = function(x) {
375        var base = -Math.cos(x * (0.5 * Math.PI)) + 1,
376            rate = Math.pow(base, 1.5),
377            rateR = Math.pow(1 - x, 2),
378            progress = -Math.abs(Math.cos(rate * (2.5 * Math.PI))) + 1;
379        return 1 - rateR + progress * rateR;
380    };
381
382    /**
383     * Setters
384     **************************************
385     */
386
387    /**
388     * Check and set the element in the instance
389     * The method will not return anything, but will throw an
390     * error if the parameter is invalid
391     *
392     * @param {DOM|String}   element  SVG Dom element or id of it
393     */
394    Vivus.prototype.setElement = function(element, options) {
395        var onLoad, self;
396
397        // Basic check
398        if (typeof element === 'undefined') {
399            throw new Error('Vivus [constructor]: "element" parameter is required');
400        }
401
402        // Set the element
403        if (element.constructor === String) {
404            element = document.getElementById(element);
405            if (!element) {
406                throw new Error(
407                    'Vivus [constructor]: "element" parameter is not related to an existing ID'
408                );
409            }
410        }
411        this.parentEl = element;
412
413        // Load the SVG with XMLHttpRequest and extract the SVG
414        if (options && options.file) {
415            self = this;
416            onLoad = function() {
417                var domSandbox = document.createElement('div');
418                domSandbox.innerHTML = this.responseText;
419
420                var svgTag = domSandbox.querySelector('svg');
421                if (!svgTag) {
422                    throw new Error(
423                        'Vivus [load]: Cannot find the SVG in the loaded file : ' +
424                        options.file
425                    );
426                }
427
428                self.el = svgTag;
429                self.el.setAttribute('width', '100%');
430                self.el.setAttribute('height', '100%');
431                self.parentEl.appendChild(self.el);
432                self.isReady = true;
433                self.init();
434                self = null;
435            };
436
437            var oReq = new window.XMLHttpRequest();
438            oReq.addEventListener('load', onLoad);
439            oReq.open('GET', options.file);
440            oReq.send();
441            return;
442        }
443
444        switch (element.constructor) {
445            case window.SVGSVGElement:
446            case window.SVGElement:
447            case window.SVGGElement:
448                this.el = element;
449                this.isReady = true;
450                break;
451
452            case window.HTMLObjectElement:
453                self = this;
454                onLoad = function(e) {
455                    if (self.isReady) {
456                        return;
457                    }
458                    self.el =
459                        element.contentDocument &&
460                        element.contentDocument.querySelector('svg');
461                    if (!self.el && e) {
462                        throw new Error(
463                            'Vivus [constructor]: object loaded does not contain any SVG'
464                        );
465                    } else if (self.el) {
466                        if (element.getAttribute('built-by-vivus')) {
467                            self.parentEl.insertBefore(self.el, element);
468                            self.parentEl.removeChild(element);
469                            self.el.setAttribute('width', '100%');
470                            self.el.setAttribute('height', '100%');
471                        }
472                        self.isReady = true;
473                        self.init();
474                        self = null;
475                    }
476                };
477
478                if (!onLoad()) {
479                    element.addEventListener('load', onLoad);
480                }
481                break;
482
483            default:
484                throw new Error(
485                    'Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)'
486                );
487        }
488    };
489
490    /**
491     * Set up user option to the instance
492     * The method will not return anything, but will throw an
493     * error if the parameter is invalid
494     *
495     * @param  {object} options Object from the constructor
496     */
497    Vivus.prototype.setOptions = function(options) {
498        var allowedTypes = [
499            'delayed',
500            'sync',
501            'async',
502            'nsync',
503            'oneByOne',
504            'scenario',
505            'scenario-sync'
506        ];
507        var allowedStarts = ['inViewport', 'manual', 'autostart'];
508
509        // Basic check
510        if (options !== undefined && options.constructor !== Object) {
511            throw new Error(
512                'Vivus [constructor]: "options" parameter must be an object'
513            );
514        } else {
515            options = options || {};
516        }
517
518        // Set the animation type
519        if (options.type && allowedTypes.indexOf(options.type) === -1) {
520            throw new Error(
521                'Vivus [constructor]: ' +
522                options.type +
523                ' is not an existing animation `type`'
524            );
525        } else {
526            this.type = options.type || allowedTypes[0];
527        }
528
529        // Set the start type
530        if (options.start && allowedStarts.indexOf(options.start) === -1) {
531            throw new Error(
532                'Vivus [constructor]: ' +
533                options.start +
534                ' is not an existing `start` option'
535            );
536        } else {
537            this.start = options.start || allowedStarts[0];
538        }
539
540        this.isIE =
541            window.navigator.userAgent.indexOf('MSIE') !== -1 ||
542            window.navigator.userAgent.indexOf('Trident/') !== -1 ||
543            window.navigator.userAgent.indexOf('Edge/') !== -1;
544        this.duration = parsePositiveInt(options.duration, 120);
545        this.delay = parsePositiveInt(options.delay, null);
546        this.dashGap = parsePositiveInt(options.dashGap, 1);
547        this.forceRender = options.hasOwnProperty('forceRender')
548            ? !!options.forceRender
549            : this.isIE;
550        this.reverseStack = !!options.reverseStack;
551        this.selfDestroy = !!options.selfDestroy;
552        this.onReady = options.onReady;
553        this.map = [];
554        this.frameLength = this.currentFrame = this.delayUnit = this.speed = this.handle = null;
555
556        this.ignoreInvisible = options.hasOwnProperty('ignoreInvisible')
557            ? !!options.ignoreInvisible
558            : false;
559
560        this.animTimingFunction = options.animTimingFunction || Vivus.LINEAR;
561        this.pathTimingFunction = options.pathTimingFunction || Vivus.LINEAR;
562
563        if (this.delay >= this.duration) {
564            throw new Error('Vivus [constructor]: delay must be shorter than duration');
565        }
566    };
567
568    /**
569     * Set up callback to the instance
570     * The method will not return enything, but will throw an
571     * error if the parameter is invalid
572     *
573     * @param  {Function} callback Callback for the animation end
574     */
575    Vivus.prototype.setCallback = function(callback) {
576        // Basic check
577        if (!!callback && callback.constructor !== Function) {
578            throw new Error(
579                'Vivus [constructor]: "callback" parameter must be a function'
580            );
581        }
582        this.callback = callback || function() {};
583    };
584
585    /**
586     * Core
587     **************************************
588     */
589
590    /**
591     * Map the svg, path by path.
592     * The method return nothing, it just fill the
593     * `map` array. Each item in this array represent
594     * a path element from the SVG, with informations for
595     * the animation.
596     *
597     * ```
598     * [
599     *   {
600     *     el: <DOMobj> the path element
601     *     length: <number> length of the path line
602     *     startAt: <number> time start of the path animation (in frames)
603     *     duration: <number> path animation duration (in frames)
604     *   },
605     *   ...
606     * ]
607     * ```
608     *
609     */
610    Vivus.prototype.mapping = function() {
611        var i, paths, path, pAttrs, pathObj, totalLength, lengthMeter, timePoint;
612        timePoint = totalLength = lengthMeter = 0;
613        paths = this.el.querySelectorAll('path');
614
615        for (i = 0; i < paths.length; i++) {
616            path = paths[i];
617            if (this.isInvisible(path)) {
618                continue;
619            }
620            pathObj = {
621                el: path,
622                length: Math.ceil(path.getTotalLength())
623            };
624            // Test if the path length is correct
625            if (isNaN(pathObj.length)) {
626                if (window.console && console.warn) {
627                    console.warn(
628                        'Vivus [mapping]: cannot retrieve a path element length',
629                        path
630                    );
631                }
632                continue;
633            }
634            this.map.push(pathObj);
635            path.style.strokeDasharray =
636                pathObj.length + ' ' + (pathObj.length + this.dashGap * 2);
637            path.style.strokeDashoffset = pathObj.length + this.dashGap;
638            pathObj.length += this.dashGap;
639            totalLength += pathObj.length;
640
641            this.renderPath(i);
642        }
643
644        totalLength = totalLength === 0 ? 1 : totalLength;
645        this.delay = this.delay === null ? this.duration / 3 : this.delay;
646        this.delayUnit = this.delay / (paths.length > 1 ? paths.length - 1 : 1);
647
648        // Reverse stack if asked
649        if (this.reverseStack) {
650            this.map.reverse();
651        }
652
653        for (i = 0; i < this.map.length; i++) {
654            pathObj = this.map[i];
655
656            switch (this.type) {
657                case 'delayed':
658                    pathObj.startAt = this.delayUnit * i;
659                    pathObj.duration = this.duration - this.delay;
660                    break;
661
662                case 'oneByOne':
663                    pathObj.startAt = (lengthMeter / totalLength) * this.duration;
664                    pathObj.duration = (pathObj.length / totalLength) * this.duration;
665                    break;
666
667                case 'sync':
668                case 'async':
669                case 'nsync':
670                    pathObj.startAt = 0;
671                    pathObj.duration = this.duration;
672                    break;
673
674                case 'scenario-sync':
675                    path = pathObj.el;
676                    pAttrs = this.parseAttr(path);
677                    pathObj.startAt =
678                        timePoint +
679                        (parsePositiveInt(pAttrs['data-delay'], this.delayUnit) || 0);
680                    pathObj.duration = parsePositiveInt(
681                        pAttrs['data-duration'],
682                        this.duration
683                    );
684                    timePoint =
685                        pAttrs['data-async'] !== undefined
686                            ? pathObj.startAt
687                            : pathObj.startAt + pathObj.duration;
688                    this.frameLength = Math.max(
689                        this.frameLength,
690                        pathObj.startAt + pathObj.duration
691                    );
692                    break;
693
694                case 'scenario':
695                    path = pathObj.el;
696                    pAttrs = this.parseAttr(path);
697                    pathObj.startAt =
698                        parsePositiveInt(pAttrs['data-start'], this.delayUnit) || 0;
699                    pathObj.duration = parsePositiveInt(
700                        pAttrs['data-duration'],
701                        this.duration
702                    );
703                    this.frameLength = Math.max(
704                        this.frameLength,
705                        pathObj.startAt + pathObj.duration
706                    );
707                    break;
708            }
709            lengthMeter += pathObj.length;
710            this.frameLength = this.frameLength || this.duration;
711        }
712    };
713
714    /**
715     * Interval method to draw the SVG from current
716     * position of the animation. It update the value of
717     * `currentFrame` and re-trace the SVG.
718     *
719     * It use this.handle to store the requestAnimationFrame
720     * and clear it one the animation is stopped. So this
721     * attribute can be used to know if the animation is
722     * playing.
723     *
724     * Once the animation at the end, this method will
725     * trigger the Vivus callback.
726     *
727     */
728    Vivus.prototype.drawer = function() {
729        var self = this;
730        this.currentFrame += this.speed;
731
732        if (this.currentFrame <= 0) {
733            this.stop();
734            this.reset();
735        } else if (this.currentFrame >= this.frameLength) {
736            this.stop();
737            this.currentFrame = this.frameLength;
738            this.trace();
739            if (this.selfDestroy) {
740                this.destroy();
741            }
742        } else {
743            this.trace();
744            this.handle = requestAnimFrame(function() {
745                self.drawer();
746            });
747            return;
748        }
749
750        this.callback(this);
751        if (this.instanceCallback) {
752            this.instanceCallback(this);
753            this.instanceCallback = null;
754        }
755    };
756
757    /**
758     * Draw the SVG at the current instant from the
759     * `currentFrame` value. Here is where most of the magic is.
760     * The trick is to use the `strokeDashoffset` style property.
761     *
762     * For optimisation reasons, a new property called `progress`
763     * is added in each item of `map`. This one contain the current
764     * progress of the path element. Only if the new value is different
765     * the new value will be applied to the DOM element. This
766     * method save a lot of resources to re-render the SVG. And could
767     * be improved if the animation couldn't be played forward.
768     *
769     */
770    Vivus.prototype.trace = function() {
771        var i, progress, path, currentFrame;
772        currentFrame =
773            this.animTimingFunction(this.currentFrame / this.frameLength) *
774            this.frameLength;
775        for (i = 0; i < this.map.length; i++) {
776            path = this.map[i];
777            progress = (currentFrame - path.startAt) / path.duration;
778            progress = this.pathTimingFunction(Math.max(0, Math.min(1, progress)));
779            if (path.progress !== progress) {
780                path.progress = progress;
781                path.el.style.strokeDashoffset = Math.floor(path.length * (1 - progress));
782                this.renderPath(i);
783            }
784        }
785    };
786
787    /**
788     * Method forcing the browser to re-render a path element
789     * from it's index in the map. Depending on the `forceRender`
790     * value.
791     * The trick is to replace the path element by it's clone.
792     * This practice is not recommended because it's asking more
793     * ressources, too much DOM manupulation..
794     * but it's the only way to let the magic happen on IE.
795     * By default, this fallback is only applied on IE.
796     *
797     * @param  {Number} index Path index
798     */
799    Vivus.prototype.renderPath = function(index) {
800        if (this.forceRender && this.map && this.map[index]) {
801            var pathObj = this.map[index],
802                newPath = pathObj.el.cloneNode(true);
803            pathObj.el.parentNode.replaceChild(newPath, pathObj.el);
804            pathObj.el = newPath;
805        }
806    };
807
808    /**
809     * When the SVG object is loaded and ready,
810     * this method will continue the initialisation.
811     *
812     * This this mainly due to the case of passing an
813     * object tag in the constructor. It will wait
814     * the end of the loading to initialise.
815     *
816     */
817    Vivus.prototype.init = function() {
818        // Set object variables
819        this.frameLength = 0;
820        this.currentFrame = 0;
821        this.map = [];
822
823        // Start
824        new Pathformer(this.el);
825        this.mapping();
826        this.starter();
827
828        if (this.onReady) {
829            this.onReady(this);
830        }
831    };
832
833    /**
834     * Trigger to start of the animation.
835     * Depending on the `start` value, a different script
836     * will be applied.
837     *
838     * If the `start` value is not valid, an error will be thrown.
839     * Even if technically, this is impossible.
840     *
841     */
842    Vivus.prototype.starter = function() {
843        switch (this.start) {
844            case 'manual':
845                return;
846
847            case 'autostart':
848                this.play();
849                break;
850
851            case 'inViewport':
852                var self = this,
853                    listener = function() {
854                        if (self.isInViewport(self.parentEl, 1)) {
855                            self.play();
856                            window.removeEventListener('scroll', listener);
857                        }
858                    };
859                window.addEventListener('scroll', listener);
860                listener();
861                break;
862        }
863    };
864
865    /**
866     * Controls
867     **************************************
868     */
869
870    /**
871     * Get the current status of the animation between
872     * three different states: 'start', 'progress', 'end'.
873     * @return {string} Instance status
874     */
875    Vivus.prototype.getStatus = function() {
876        return this.currentFrame === 0
877            ? 'start'
878            : this.currentFrame === this.frameLength
879                ? 'end'
880                : 'progress';
881    };
882
883    /**
884     * Reset the instance to the initial state : undraw
885     * Be careful, it just reset the animation, if you're
886     * playing the animation, this won't stop it. But just
887     * make it start from start.
888     *
889     */
890    Vivus.prototype.reset = function() {
891        return this.setFrameProgress(0);
892    };
893
894    /**
895     * Set the instance to the final state : drawn
896     * Be careful, it just set the animation, if you're
897     * playing the animation on rewind, this won't stop it.
898     * But just make it start from the end.
899     *
900     */
901    Vivus.prototype.finish = function() {
902        return this.setFrameProgress(1);
903    };
904
905    /**
906     * Set the level of progress of the drawing.
907     *
908     * @param {number} progress Level of progress to set
909     */
910    Vivus.prototype.setFrameProgress = function(progress) {
911        progress = Math.min(1, Math.max(0, progress));
912        this.currentFrame = Math.round(this.frameLength * progress);
913        this.trace();
914        return this;
915    };
916
917    /**
918     * Play the animation at the desired speed.
919     * Speed must be a valid number (no zero).
920     * By default, the speed value is 1.
921     * But a negative value is accepted to go forward.
922     *
923     * And works with float too.
924     * But don't forget we are in JavaScript, se be nice
925     * with him and give him a 1/2^x value.
926     *
927     * @param  {number} speed Animation speed [optional]
928     */
929    Vivus.prototype.play = function(speed, callback) {
930        this.instanceCallback = null;
931
932        if (speed && typeof speed === 'function') {
933            this.instanceCallback = speed; // first parameter is actually the callback function
934            speed = null;
935        } else if (speed && typeof speed !== 'number') {
936            throw new Error('Vivus [play]: invalid speed');
937        }
938        // if the first parameter wasn't the callback, check if the seconds was
939        if (callback && typeof callback === 'function' && !this.instanceCallback) {
940            this.instanceCallback = callback;
941        }
942
943        this.speed = speed || 1;
944        if (!this.handle) {
945            this.drawer();
946        }
947        return this;
948    };
949
950    /**
951     * Stop the current animation, if on progress.
952     * Should not trigger any error.
953     *
954     */
955    Vivus.prototype.stop = function() {
956        if (this.handle) {
957            cancelAnimFrame(this.handle);
958            this.handle = null;
959        }
960        return this;
961    };
962
963    /**
964     * Destroy the instance.
965     * Remove all bad styling attributes on all
966     * path tags
967     *
968     */
969    Vivus.prototype.destroy = function() {
970        this.stop();
971        var i, path;
972        for (i = 0; i < this.map.length; i++) {
973            path = this.map[i];
974            path.el.style.strokeDashoffset = null;
975            path.el.style.strokeDasharray = null;
976            this.renderPath(i);
977        }
978    };
979
980    /**
981     * Utils methods
982     * include methods from Codrops
983     **************************************
984     */
985
986    /**
987     * Method to best guess if a path should added into
988     * the animation or not.
989     *
990     * 1. Use the `data-vivus-ignore` attribute if set
991     * 2. Check if the instance must ignore invisible paths
992     * 3. Check if the path is visible
993     *
994     * For now the visibility checking is unstable.
995     * It will be used for a beta phase.
996     *
997     * Other improvments are planned. Like detecting
998     * is the path got a stroke or a valid opacity.
999     */
1000    Vivus.prototype.isInvisible = function(el) {
1001        var rect,
1002            ignoreAttr = el.getAttribute('data-ignore');
1003
1004        if (ignoreAttr !== null) {
1005            return ignoreAttr !== 'false';
1006        }
1007
1008        if (this.ignoreInvisible) {
1009            rect = el.getBoundingClientRect();
1010            return !rect.width && !rect.height;
1011        } else {
1012            return false;
1013        }
1014    };
1015
1016    /**
1017     * Parse attributes of a DOM element to
1018     * get an object of {attributeName => attributeValue}
1019     *
1020     * @param  {object} element DOM element to parse
1021     * @return {object}         Object of attributes
1022     */
1023    Vivus.prototype.parseAttr = function(element) {
1024        var attr,
1025            output = {};
1026        if (element && element.attributes) {
1027            for (var i = 0; i < element.attributes.length; i++) {
1028                attr = element.attributes[i];
1029                output[attr.name] = attr.value;
1030            }
1031        }
1032        return output;
1033    };
1034
1035    /**
1036     * Reply if an element is in the page viewport
1037     *
1038     * @param  {object} el Element to observe
1039     * @param  {number} h  Percentage of height
1040     * @return {boolean}
1041     */
1042    Vivus.prototype.isInViewport = function(el, h) {
1043        var scrolled = this.scrollY(),
1044            viewed = scrolled + this.getViewportH(),
1045            elBCR = el.getBoundingClientRect(),
1046            elHeight = elBCR.height,
1047            elTop = scrolled + elBCR.top,
1048            elBottom = elTop + elHeight;
1049
1050        // if 0, the element is considered in the viewport as soon as it enters.
1051        // if 1, the element is considered in the viewport only when it's fully inside
1052        // value in percentage (1 >= h >= 0)
1053        h = h || 0;
1054
1055        return elTop + elHeight * h <= viewed && elBottom >= scrolled;
1056    };
1057
1058    /**
1059     * Get the viewport height in pixels
1060     *
1061     * @return {integer} Viewport height
1062     */
1063    Vivus.prototype.getViewportH = function() {
1064        var client = this.docElem.clientHeight,
1065            inner = window.innerHeight;
1066
1067        if (client < inner) {
1068            return inner;
1069        } else {
1070            return client;
1071        }
1072    };
1073
1074    /**
1075     * Get the page Y offset
1076     *
1077     * @return {integer} Page Y offset
1078     */
1079    Vivus.prototype.scrollY = function() {
1080        return window.pageYOffset || this.docElem.scrollTop;
1081    };
1082
1083    setupEnv = function() {
1084        if (Vivus.prototype.docElem) {
1085            return;
1086        }
1087
1088        /**
1089         * Alias for document element
1090         *
1091         * @type {DOMelement}
1092         */
1093        Vivus.prototype.docElem = window.document.documentElement;
1094
1095        /**
1096         * Alias for `requestAnimationFrame` or
1097         * `setTimeout` function for deprecated browsers.
1098         *
1099         */
1100        requestAnimFrame = (function() {
1101            return (
1102                window.requestAnimationFrame ||
1103                window.webkitRequestAnimationFrame ||
1104                window.mozRequestAnimationFrame ||
1105                window.oRequestAnimationFrame ||
1106                window.msRequestAnimationFrame ||
1107                function(/* function */ callback) {
1108                    return window.setTimeout(callback, 1000 / 60);
1109                }
1110            );
1111        })();
1112
1113        /**
1114         * Alias for `cancelAnimationFrame` or
1115         * `cancelTimeout` function for deprecated browsers.
1116         *
1117         */
1118        cancelAnimFrame = (function() {
1119            return (
1120                window.cancelAnimationFrame ||
1121                window.webkitCancelAnimationFrame ||
1122                window.mozCancelAnimationFrame ||
1123                window.oCancelAnimationFrame ||
1124                window.msCancelAnimationFrame ||
1125                function(id) {
1126                    return window.clearTimeout(id);
1127                }
1128            );
1129        })();
1130    };
1131
1132    /**
1133     * Parse string to integer.
1134     * If the number is not positive or null
1135     * the method will return the default value
1136     * or 0 if undefined
1137     *
1138     * @param {string} value String to parse
1139     * @param {*}
1139 defaultValue Value to return if the result parsed is invalid
1140     * @return {number}
1141     *
1142     */
1143    parsePositiveInt = function(value, defaultValue) {
1144        var output = parseInt(value, 10);
1145        return output >= 0 ? output : defaultValue;
1146    };
1147
1148
1149    if (typeof define === 'function' && define.amd) {
1150        // AMD. Register as an anonymous module.
1151        define([], function() {
1152            return Vivus;
1153        });
1154    } else if (typeof exports === 'object') {
1155        // Node. Does not work with strict CommonJS, but
1156        // only CommonJS-like environments that support module.exports,
1157        // like Node.
1158        module.exports = Vivus;
1159    } else {
1160        // Browser globals
1161        window.Vivus = Vivus;
1162    }
1163
1164}());
1165!function(M,d,f,p){var o=[],e={_version:"3.12.0",_config:{classPrefix:"",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,t){var n=this;setTimeout(function(){t(n[e])},0)},addTest:function(e,t,n){o.push({name:e,fn:t,options:n})},addAsyncTest:function(e){o.push({name:null,fn:e})}},s=function(){},t=(s.prototype=e,s=new s,[]);function m(e,t){return typeof e===t}var c=f.documentElement,h="svg"===c.nodeName.toLowerCase();function i(e){var t,n=c.className,o=s._config.classPrefix||"";h&&(n=n.baseVal),s._config.enableJSClass&&(t=new RegExp("(^|\\s)"+o+"no-js(\\s|$)"),n=n.replace(t,"$1"+o+"js$2")),s._config.enableClasses&&(0<e.length&&(n+=" "+o+e.join(" "+o)),h?c.className.baseVal=n:c.className=n)}var a,n,r="Moz O ms Webkit",A=e._config.usePrefixes?r.toLowerCase().split(" "):[],l=(e._domPrefixes=A,e._config.usePrefixes?" -webkit- -moz- -o- -ms- ".split(" "):["",""]);function u(e,t){if("object"==typeof e)for(var n in e)a(e,n)&&u(n,e[n]);else{var o=(e=e.toLowerCase()).split("."),r=s[o[0]];if(void 0!==(r=2===o.length?r[o[1]]:r))return s;t="function"==typeof t?t():t,1===o.length?s[o[0]]=t:(!s[o[0]]||s[o[0]]instanceof Boolean||(s[o[0]]=new Boolean(s[o[0]])),s[o[0]][o[1]]=t),i([(t&&!1!==t?"":"no-")+o.join("-")]),s._trigger(e,t)}return s}function g(e){return"function"!=typeof f.createElement?f.createElement(e):h?f.createElementNS.call(f,"http://www.w3.org/2000/svg",e):f.createElement.apply(f,arguments)}e._prefixes=l,a=void 0!==(n={}.hasOwnProperty)&&void 0!==n.call?function(e,t){return n.call(e,t)}:function(e,t){return t in e&&void 0===e.constructor.prototype[t]},e._l={},e.on=function(e,t){this._l[e]||(this._l[e]=[]),this._l[e].push(t),s.hasOwnProperty(e)&&setTimeout(function(){s._trigger(e,s[e])},0)},e._trigger=function(e,t){var n;this._l[e]&&(n=this._l[e],setTimeout(function(){for(var e=0;e<n.length;e++)(0,n[e])(t)},0),delete this._l[e])},s._q.push(function(){e.addTest=u});v=!("onblur"in c);var v,y=function(e,t){var n;return!!e&&(!(n=(e="on"+e)in(t=t&&"string"!=typeof t?t:g(t||"div")))&&v&&((t=t.setAttribute?t:g("div")).setAttribute(e,""),n="function"==typeof t[e],t[e]!==p&&(t[e]=p),t.removeAttribute(e)),n)};function w(e,t,n,o){var r,s,i,a,l="modernizr",u=g("div");(a=f.body)||((a=g(h?"svg":"body")).fake=!0);if(parseInt(n,10))for(;n--;)(s=g("div")).id=o?o[n]:l+(n+1),u.appendChild(s);return(r=g("style")).type="text/css",r.id="s"+l,(a.fake?a:u).appendChild(r),a.appendChild(u),r.styleSheet?r.styleSheet.cssText=e:r.appendChild(f.createTextNode(e)),u.id=l,a.fake&&(a.style.background="",a.style.overflow="hidden",i=c.style.overflow,c.style.overflow="hidden",c.appendChild(a)),r=t(u,e),a.fake&&a.parentNode?(a.parentNode.removeChild(a),c.style.overflow=i,c.offsetHeight):u.parentNode.removeChild(u),!!r}function R(e,t,n){var o,r;return"getComputedStyle"in d?(o=getComputedStyle.call(d,e,t),r=d.console,null!==o?n&&(o=o.getPropertyValue(n)):r&&r[r.error?"error":"log"].call(r,"getComputedStyle returning null, its possible modernizr test results are inaccurate")):o=!t&&e.currentStyle&&e.currentStyle[n],o}e.hasEvent=y;var W,l=(W=d.matchMedia||d.msMatchMedia)?function(e){e=W(e);return e&&e.matches||!1}:function(e){var t=!1;return w("@media "+e+" { #modernizr { position: absolute; } }",function(e){t="absolute"===R(e,null,"position")}),t},q=(e.mq=l,e.prefixedCSSValue=function(e,t){var n=!1,o=g("div").style;if(e in o){var r=A.length;for(o[e]=t,n=o[e];r--&&!n;)o[e]="-"+A[r]+"-"+t,n=o[e]}return n=""===n?!1:n},e._config.usePrefixes?r.split(" "):[]);e._cssomPrefixes=q;var G={elem:g("modernizr")},C=(s._q.push(function(){delete G.elem}),{style:G.elem.style});function I(e){return e.replace(/([A-Z])/g,function(e,t){return"-"+t.toLowerCase()}).replace(/^ms-/,"-ms-")}function H(e,t,n,o){if(o=void 0!==o&&o,void 0!==n){var r=function(e,t){var n=e.length;if("CSS"in d&&"supports"in d.CSS){for(;n--;)if(d.CSS.supports(I(e[n]),t))return!0;return!1}if("CSSSupportsRule"in d){for(var o=[];n--;)o.push("("+I(e[n])+":"+t+")");return w("@supports ("+(o=o.join(" or "))+") { #modernizr { position: absolute; } }",function(e){return"absolute"===R(e,null,"position")})}return p}(e,n);if(void 0!==r)return r}for(var s,i,a,l,u,f=["modernizr","tspan","samp"];!C.style&&f.length;)s=!0,C.modElem=g(f.shift()),C.style=C.modElem.style;
1165function c(){s&&(delete C.style,delete C.modElem)}for(a=e.length,i=0;i<a;i++)if(l=e[i],u=C.style[l],~(""+l).indexOf("-")&&(l=l.replace(/([a-z])-([a-z])/g,function(e,t,n){return t+n.toUpperCase()}).replace(/^-/,"")),C.style[l]!==p){if(o||void 0===n)return c(),"pfx"!==t||l;try{C.style[l]=n}catch(e){}if(C.style[l]!==u)return c(),"pfx"!==t||l}return c(),!1}function V(e,t,n,o,r){var s=e.charAt(0).toUpperCase()+e.slice(1),i=(e+" "+q.join(s+" ")+s).split(" ");if(m(t,"string")||void 0===t)return H(i,t,o,r);var a,l,u,f,c=i=(e+" "+A.join(s+" ")+s).split(" "),d=t,p=n;for(a in c)if(c[a]in d)return!1===p?c[a]:m(f=d[c[a]],"function")?(l=f,u=p||d,function(){return l.apply(u,arguments)}):f;return!1}function b(e,t,n){return V(e,p,p,t,n)}s._q.unshift(function(){delete C.style}),e.testAllProps=V,e.testAllProps=b;e.testProp=function(e,t,n){return H([e],p,t,n)},e.testStyles=w;s.addTest("customelements","customElements"in d),s.addTest("history",function(){var e=navigator.userAgent;return!!e&&((-1===e.indexOf("Android 2.")&&-1===e.indexOf("Android 4.0")||-1===e.indexOf("Mobile Safari")||-1!==e.indexOf("Chrome")||-1!==e.indexOf("Windows Phone")||"file:"===location.protocol)&&(d.history&&"pushState"in d.history))});var S=[""].concat(A),$=(e._domPrefixesAll=S,s.addTest("pointerevents",function(){for(var e=0,t=S.length;e<t;e++)if(y(S[e]+"pointerdown"))return!0;return!1}),!0);try{d.postMessage({toString:function(){$=!1}},"*")}catch(e){}s.addTest("postmessage",new Boolean("postMessage"in d)),s.addTest("postmessage.structuredclones",$),s.addTest("webgl",function(){return"WebGLRenderingContext"in d});var x,_,T,P,k,B,E,l=!1;try{l="WebSocket"in d&&2===d.WebSocket.CLOSING}catch(e){}s.addTest("websockets",l),s.addTest("cssanimations",b("animationName","a",!0)),s.addTest("csscolumns",function(){var e=!1,t=b("columnCount");try{e=(e=!!t)&&new Boolean(e)}catch(e){}return e});for(var z,O,L=["Width","Span","Fill","Gap","Rule","RuleColor","RuleStyle","RuleWidth","BreakBefore","BreakAfter","BreakInside"],N=0;N<L.length;N++)z=L[N].toLowerCase(),O=b("column"+L[N]),"breakbefore"!==z&&"breakafter"!==z&&"breakinside"!==z||(O=O||b(L[N])),s.addTest("csscolumns."+z,O);for(E in s.addTest("flexbox",b("flexBasis","1px",!0)),s.addTest("picture","HTMLPictureElement"in d),s.addAsyncTest(function(){var e,t,n=g("img"),o="sizes"in n;!o&&"srcset"in n?(e="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",n.onload=t=function(){u("sizes",2===n.width)},n.onerror=t,n.setAttribute("sizes","9px"),n.srcset=e+" 1w,data:image/gif;base64,R0lGODlhAgABAPAAAP///wAAACH5BAAAAAAALAAAAAACAAEAAAICBAoAOw== 8w",n.src=e):u("sizes",o)}),s.addTest("srcset","srcset"in g("img")),s.addTest("webworkers","Worker"in d),o)if(o.hasOwnProperty(E)){if(x=[],(_=o[E]).name&&(x.push(_.name.toLowerCase()),_.options&&_.options.aliases&&_.options.aliases.length))for(T=0;T<_.options.aliases.length;T++)x.push(_.options.aliases[T].toLowerCase());for(P=m(_.fn,"function")?_.fn():_.fn,k=0;k<x.length;k++)1===(B=x[k].split(".")).length?s[B[0]]=P:(s[B[0]]&&(!s[B[0]]||s[B[0]]instanceof Boolean)||(s[B[0]]=new Boolean(s[B[0]])),s[B[0]][B[1]]=P),t.push((P?"":"no-")+B.join("-"))}i(t),delete e.addTest,delete e.addAsyncTest;for(var j=0;j<s._q.length;j++)s._q[j]();M.Modernizr=s}(window,window,document);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.