PageSourceSearch

https://www.appycouple.com/js/1475624094/marketing/plugins/anijs.js

js appycouple.com collected 2026-10-01 13:14:06 UTC 59,673 bytes, 1,493 lines download raw bytes

1/*!
2AniJS - http://anijs.github.io
3Licensed under the MIT license
4
5Copyright (c) 2014 Dariel Noel <[email protected]>
6
7Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
8
9The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
10
11THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12*/
13
14(function(root, factory) {
15    "use strict";
16    if (typeof module == "object" && typeof module.exports == "object") {
17        module.exports = root.document ?
18            factory(root, true) :
19            function(w) {
20                if (!w.document) {
21                    throw new Error("AniJS-RWWD");
22                }
23                return factory(w);
24        };
25    } else {
26        factory(root);
27    }
28
29})(typeof window !== "undefined" ? window : this, function(window, noGlobal) {
30
31
32    /**
33     * AniJS is library for write declarative animations in your static html documents
34     * @class AniJSit
35     * @constructor init
36     * @author @dariel_noel
37     */
38    var AniJS = (function(AniJS) {
39
40        //Shorthands
41        var ANIJS_DATATAG_NAME = 'data-anijs',
42            DEFAULT = 'default',
43            BODY = 'body',
44            PARAMS_SEPARATOR = '|',
45            MULTIPLE_CLASS_SEPARATOR = '$',
46            EVENT_RESERVED_WORD = 'if',
47            EVENT_TARGET_RESERVED_WORD = 'on',
48            BEHAVIOR_RESERVED_WORD = ['do', 'after', 'before', 'to'],
49            BEHAVIOR_TARGET_RESERVED_WORD = 'to',
50            REGEX_BEGIN = '(\\s+|^)',
51            REGEX_END = '(\\s+|$)',
52            ANIMATION_END = 'animationend',
53            TRANSITION_END = 'transitionend',
54            TARGET = 'target';
55
56        /////////////////////////////////////////////////////////
57        // Public API
58        /////////////////////////////////////////////////////////
59
60        AniJS = {
61
62            rootDOMTravelScope: {},
63
64            notifierCollection: {},
65
66            /**
67             * Initializer Function
68             * @method init
69             * @return
70             */
71            init: function() {
72
73                //ATTRS inicialization
74                selfish._helperCollection = {};
75
76                var defaultHelper = selfish._createDefaultHelper();
77
78                //Registering an empty helper
79                AniJS.registerHelper(DEFAULT, defaultHelper);
80
81                //Default Helper Index
82                selfish._helperDefaultIndex = DEFAULT;
83
84                AniJS.rootDOMTravelScope = document;
85
86                //Initialize the Parser Object
87                AniJS.Parser = selfish.Parser;
88
89                //AnimationEnd Correct Prefix Setup
90                selfish._animationEndEvent = selfish._animationEndPrefix();
91
92                //Add this class names when anim
93                selfish._classNamesWhenAnim = '';
94            },
95
96            /**
97             * You can use these to change the scope to run AniJS
98             * @method setDOMRootTravelScope
99             * @param {} selector
100             * @return
101             */
102            setDOMRootTravelScope: function(selector) {
103                var rootDOMTravelScope,
104                    domDocument = document;
105                try {
106                    if (selector === 'document') {
107                        rootDOMTravelScope = domDocument;
108                    } else {
109                        rootDOMTravelScope = domDocument.querySelector(selector);
110                        if (!rootDOMTravelScope) {
111                            rootDOMTravelScope = domDocument;
112                        }
113                    }
114
115                } catch (e) {
116                    rootDOMTravelScope = domDocument;
117                }
118                AniJS.rootDOMTravelScope = rootDOMTravelScope;
119            },
120
121            /**
122             * Parse Declarations and setup Anim in a founded elements
123             * @method run
124             * @return
125             */
126            run: function() {
127                var aniJSNodeCollection = [],
128                    aniJSParsedSentenceCollection = {};
129
130                //Clear all node listener
131                AniJS.purgeAll();
132
133                AniJS.notifierCollection = {};
134
135                aniJSNodeCollection = selfish._findAniJSNodeCollection(AniJS.rootDOMTravelScope);
136
137                var size = aniJSNodeCollection.length,
138                    i = 0,
139                    item;
140
141                for (i; i < size; i++) {
142                    item = aniJSNodeCollection[i];
143
144                    //IMPROVE: The datatag name migth come from configuration
145                    aniJSParsedSentenceCollection = selfish._getParsedAniJSSentenceCollection(item.getAttribute(ANIJS_DATATAG_NAME));
146
147                    //Le seteo su animacion
148                    selfish._setupElementAnim(item, aniJSParsedSentenceCollection);
149                }
150
151                //We can use this for supply the window load and DomContentLoaded in some context
152                var aniJSEventsNotifier = AniJS.getNotifier('AniJSNotifier');
153                if(aniJSEventsNotifier){
154                    aniJSEventsNotifier.dispatchEvent('onRunFinished');
155                }
156            },
157
158            /**
159             * Create an animation from a aniJSParsedSentenceCollection
160             * @method createAnimation
161             * @param {} aniJSParsedSentenceCollection
162             * @param {} element
163             * @return
164             */
165            createAnimation: function(aniJSParsedSentenceCollection, element) {
166                var nodeElement = element || '';
167
168                //BEAUTIFY: The params order migth be the same
169                selfish._setupElementAnim(nodeElement, aniJSParsedSentenceCollection);
170            },
171
172            /**
173             * Return a Helper by ID, you can use this to attach callback to the Helper
174             * @method getHelper
175             * @param {} helperID
176             * @return LogicalExpression
177             */
178            getHelper: function(helperID) {
179                var helperCollection = selfish._helperCollection;
180                return helperCollection[helperID] || helperCollection[DEFAULT];
181            },
182
183            /**
184             * A helper it's a callback function container
185             * using this function you can register your custom Helper
186             * @method registerHelper
187             * @param {} helperName
188             * @param {} helperInstance
189             * @return
190             */
191            registerHelper: function(helperName, helperInstance) {
192                selfish._helperCollection[helperName] = helperInstance;
193            },
194
195            /**
196             * Purge a NodeList By Selector
197             * @method purge
198             * @param {} selector
199             * @return
200             */
201            purge: function(selector) {
202                //TODO: Search a regular expression for test a valid CSS selector
203                if (selector && selector !== '' && selector !== ' ') {
204                    var purgeNodeCollection = document.querySelectorAll(selector),
205                        size = purgeNodeCollection.length,
206                        i = 0;
207
208                    for (i; i < size; i++) {
209                        AniJS.EventSystem.purgeEventTarget(purgeNodeCollection[i]);
210                    }
211                }
212            },
213
214            /**
215             * Purge all register elements handle
216             * you can use this when you run AniJS again
217             * @method purgeAll
218             * @return
219             */
220            purgeAll: function() {
221                AniJS.EventSystem.purgeAll();
222            },
223
224            /**
225             * Remove all listener from an element
226             * @method purgeEventTarget
227             * @param {} element
228             * @return
229             */
230            purgeEventTarget: function(element) {
231                AniJS.EventSystem.purgeEventTarget(element);
232            },
233
234            /**
235             * Add default class names while Anim
236             * @method setClassNamesWhenAnim
237             * @param {} defaultClasses
238             * @return
239             */
240            setClassNamesWhenAnim: function(defaultClasses) {
241                selfish._classNamesWhenAnim = ' ' + defaultClasses;
242            },
243
244            /**
245             * Create an EventTarget
246             * @method createNotifier
247             * @return EventTarget
248             */
249            createNotifier: function() {
250                return AniJS.EventSystem.createEventTarget();
251            },
252
253            /**
254             * Put an event Notifier in the notifierCollection
255             * @method registerNotifier
256             * @param {} notifier
257             * @return Literal
258             */
259            registerNotifier: function(notifier) {
260                var notifierCollection = AniJS.notifierCollection;
261
262                //TODO: Optimize lookups here
263                if (notifier.id && notifier.value && AniJS.EventSystem.isEventTarget(notifier.value)) {
264                    notifierCollection[notifier.id] = notifier.value;
265                    return 1;
266                }
267
268                return '';
269            },
270
271            /**
272             * Return an notifier instance
273             * @method getNotifier
274             * @param {} notifierID
275             * @return notifier
276             */
277            getNotifier: function(notifierID) {
278                return AniJS.notifierCollection[notifierID];
279            }
280
281        };
282
283        /////////////////////////////////////////////////////////
284        // Private Methods an Vars
285        /////////////////////////////////////////////////////////
286
287        var selfish = {
288
289        };
290
291        /**
292         * Description
293         * @method _createDefaultHelper
294         * @return defaultHelper
295         */
296        selfish._createDefaultHelper = function() {
297            //TODO: Why default helper here, migth be directly in the public API
298            var defaultHelper = {
299                /**
300                 * Remove the animation class added when animation is created
301                 * @method removeAnim
302                 * @param {} e
303                 * @param {} animationContext
304                 * @return
305                 */
306                removeAnim: function(e, animationContext) {
307                    if(e.target && e.type){
308                      animationContext.nodeHelper.removeClass(e.target, animationContext.behavior);
309                    }
310                },
311                /**
312                 * Holds the animation class added when animation is created
313                 * @method holdAnimClass
314                 * @param {} e
315                 * @param {} animationContext
316                 * @return
317                 */
318                holdAnimClass: function(e, animationContext) {
319                },
320
321                fireOnce: function(e, animationContext) {
322                    animationContext.eventSystem.removeEventListenerHelper(animationContext.eventTarget, animationContext.event.type, animationContext.listener);
323                },
324
325                /**
326                 * Fire custom event
327                 *
328                 * Examples:
329                 *
330                 *  Fire dummyEvent event of customNotifier
331                 *
332                 *  if: click, do: $addClass fadeIn animated, to: #container, after: emit customNotifier.dummyEvent
333                 *  if: dummyEvent, on: $customNotifier, do: $addClass hidden,  to: $children #container | div
334                 *
335                 *
336                 * @author Yolier Galan Tasse <[email protected]>
337                 * @since  2014-09-20
338                 * @param  {object}   e          The event handler
339                 * @param  {object}   ctx        AniJS Animation Context Object
340                 * @param  {[string]} params     [description]
341                 */
342                emit: function(e, ctx, params) {
343                    var cevent = params[0] || null,
344                        notifier = "";
345                    if(cevent !== null) {
346                        cevent = cevent.split('.');
347                        if(cevent.length > 1) {
348                            notifier = cevent[0];
349                            cevent = cevent[1];
350                        } else {
351                            notifier = "";
352                            cevent = cevent[0];
353                        }
354                        var customNotifier = AniJS.getNotifier(notifier) || null;
355                        if(customNotifier !== null)
356                            customNotifier.dispatchEvent(cevent);
357                    }
358                    //Run the animation
359                    if(!ctx.hasRunned){
360                        ctx.run();
361                    }
362                }
363            };
364
365            return defaultHelper;
366        };
367
368        /**
369         * Create a Parser Instance
370         * @method _createParser
371         * @return Parser
372         */
373        selfish._createParser = function() {
374            //TODO: The Parser could be an static class
375            return new Parser();
376        };
377
378        /**
379         * Setup the animation of the some element
380         * @method _setupElementAnim
381         * @param {} element
382         * @param {} aniJSParsedSentenceCollection
383         * @return
384         */
385        selfish._setupElementAnim = function(element, aniJSParsedSentenceCollection) {
386            var size = aniJSParsedSentenceCollection.length,
387                i = 0,
388                item,
389                before,
390                after,
391                behavior;
392
393            for (i; i < size; i++) {
394                item = aniJSParsedSentenceCollection[i];
395                after = item.after;
396                before = item.before;
397                behavior = item.behavior;
398
399                if(after){
400                    item.after = selfish.Parser.parseDoDefinition(after);
401                }
402                if(before){
403                    item.before = selfish.Parser.parseDoDefinition(before);
404                }
405                if(behavior){
406                    item.behavior = selfish.Parser.parseDoDefinition(behavior);
407                }
408                selfish._setupElementSentenceAnim(element, item);
409            }
410        };
411
412        /**
413         * Setup the element animation from a AniJS Sentence
414         * @method _setupElementSentenceAnim
415         * @param {} element
416         * @param {} aniJSParsedSentence
417         * @return
418         */
419        selfish._setupElementSentenceAnim = function(element, aniJSParsedSentence) {
420            //TODO: If the user use animationend or transitionend names to custom events the eventdispach will be not executed
421            var event = selfish._eventHelper(aniJSParsedSentence),
422                eventTargetList = selfish._eventTargetHelper(element, aniJSParsedSentence),
423                afterFunctionName;
424
425            if(aniJSParsedSentence.after && selfish.Util.beArray(aniJSParsedSentence.after)){
426                afterFunctionName =  aniJSParsedSentence.after[0];
427            }
428
429            //Es obligatorio definir de eventTarget ATTR
430            if (event !== '') {
431                var size = eventTargetList.length,
432                    i = 0,
433                    eventTargetItem;
434                for (i; i < size; i++) {
435                    eventTargetItem = eventTargetList[i];
436                    if (AniJS.EventSystem.isEventTarget(eventTargetItem)) {
437                        var listener = function(event) {
438
439                            //Si cambia algun parametro dinamicamente entonces hay que enterarse
440                            var behaviorTargetList = selfish._behaviorTargetHelper(element, aniJSParsedSentence, event),
441                                behavior = selfish._behaviorHelper(aniJSParsedSentence),
442                                before = selfish._beforeHelper(element, aniJSParsedSentence),
443                                after = selfish._afterHelper(element, aniJSParsedSentence);
444                            if (selfish._classNamesWhenAnim !== '') {
445                                if(!selfish.Util.beArray(behavior))
446                                    behavior += selfish._classNamesWhenAnim;
447                            }
448                            //Creo un nuevo animation context
449                            var animationContextConfig = {
450                                behaviorTargetList: behaviorTargetList,
451                                nodeHelper: selfish.NodeHelper,
452                                animationEndEvent: selfish._animationEndEvent,
453                                behavior: behavior,
454                                after: after,
455                                eventSystem: AniJS.EventSystem,
456                                eventTarget: event.currentTarget,
457                                afterFunctionName: afterFunctionName,
458                                dataAniJSOwner: element,
459                                listener: listener,
460                                event: event,
461                                before: before
462                                //TODO: eventSystem should be called directly
463                            },
464
465                            animationContextInstance = new AniJS.AnimationContext(animationContextConfig);
466
467                            animationContextInstance.runAll(animationContextConfig);
468                        };
469
470                        //TODO: Improve lookup here AniJS.EventSystem
471                        AniJS.EventSystem.addEventListenerHelper(eventTargetItem, event, listener, false);
472
473                        //Register event to feature handle
474                        AniJS.EventSystem.registerEventHandle(eventTargetItem, event, listener);
475                    }
476                }
477            }
478        };
479
480        /**
481         * Helper to setup the Event that trigger the animation from declaration
482         * https://developer.mozilla.org/en-US/docs/Web/Reference/Events
483         * http://www.w3schools.com/tags/ref_eventattributes.asp
484         * @method _eventHelper
485         * @param {} element
486         * @param {} aniJSParsedSentence
487         * @return event
488         */
489        selfish._eventHelper = function(aniJSParsedSentence) {
490            var defaultValue = '',
491                event = aniJSParsedSentence.event || defaultValue;
492
493            //TODO: Improve to reduce this ugly logic here
494            if (event === ANIMATION_END) {
495                event = selfish._animationEndPrefix();
496            } else if (event === TRANSITION_END) {
497                event = selfish._transitionEndPrefix();
498            }
499
500            return event;
501        };
502
503        /**
504         * Helper to setup the Place from listen the trigger event of the animation
505         * If is not specified one place, se asume que es himself
506         * Take in account that where it's just a selector
507         * @method _eventTargetHelper
508         * @param {} element
509         * @param {} aniJSParsedSentence
510         * @return eventTargetList
511         */
512        selfish._eventTargetHelper = function(element, aniJSParsedSentence) {
513            var defaultValue = element,
514                eventTargetList = [defaultValue],
515                rootDOMTravelScope = AniJS.rootDOMTravelScope,
516                notifierList;
517
518            //TODO: We could add other non direct DOM Objects
519            if (aniJSParsedSentence.eventTarget) {
520
521                notifierList = selfish._notifierHelper(aniJSParsedSentence.eventTarget);
522
523                if (notifierList.length > 0) {
524                    eventTargetList = notifierList;
525                } else if (aniJSParsedSentence.eventTarget === 'document') {
526                    eventTargetList = [document];
527                } else if (aniJSParsedSentence.eventTarget === 'window') {
528                    eventTargetList = [window];
529                } else if (aniJSParsedSentence.eventTarget.split) {
530                    try {
531                        eventTargetList = rootDOMTravelScope.querySelectorAll(aniJSParsedSentence.eventTarget);
532                    } catch (e) {
533                        console.log('Ugly Selector Here');
534                        eventTargetList = [];
535                    }
536                }
537            }
538            //It's not a nodeList any more
539            return eventTargetList;
540        };
541
542        /**
543         * Helper to setup the Node can be animated
544         * @method _behaviorTargetHelper
545         * @param {} element
546         * @param {} aniJSParsedSentence
547         * @return behaviorTargetNodeList
548         */
549        selfish._behaviorTargetHelper = function(element, aniJSParsedSentence, event) {
550            var defaultValue = element,
551                behaviorTargetNodeList = [defaultValue],
552                rootDOMTravelScope = AniJS.rootDOMTravelScope,
553                behaviorTarget = aniJSParsedSentence.behaviorTarget;
554
555            if (behaviorTarget) {
556                if(!selfish.Util.beArray(behaviorTarget)){
557                    if(behaviorTarget === TARGET && event.currentTarget){
558                        behaviorTargetNodeList = [event.currentTarget];
559                    } else{
560                        //Expression regular remplazar caracteres $ por comas
561                        //TODO: Estudiar si este caracter no esta agarrado
562                        behaviorTarget = behaviorTarget.split(MULTIPLE_CLASS_SEPARATOR).join(',');
563                        try {
564                            behaviorTargetNodeList = rootDOMTravelScope.querySelectorAll(behaviorTarget);
565                        } catch (e) {
566                            behaviorTargetNodeList = [];
567                        }
568                    }
569                } else{
570                    var behaviorObject = this._actionHelper(element, aniJSParsedSentence, behaviorTarget);
571                    if(behaviorObject && selfish.Util.isFunction(behaviorObject[0])){
572                        behaviorTargetNodeList = behaviorObject[0]
573                                                    (event,{dataAniJSOwner:element},
574                                                    selfish._paramsHelper(behaviorObject));
575                    }
576                }
577            }
578            return behaviorTargetNodeList;
579        };
580
581        /**
582         * Helper to setup the Animation type
583         * @method _behaviorHelper
584         * @param {} element
585         * @param {} aniJSParsedSentence
586         * @return defaultValue
587         */
588        selfish._behaviorHelper = function(aniJSParsedSentence) {
589            return this._actionHelper({}, aniJSParsedSentence, aniJSParsedSentence.behavior);
590        };
591
592        /**
593         * Helper to setup the after callback function
594         * @method _afterHelper
595         * @param {} element
596         * @param {} aniJSParsedSentence
597         * @return defaultValue
598         */
599        selfish._afterHelper = function(element, aniJSParsedSentence) {
600            var defaultValue =  aniJSParsedSentence.after;
601            // return defaultValue;
602            if(!selfish.Util.beArray(defaultValue))
603                return selfish._callbackHelper(element, aniJSParsedSentence, defaultValue);
604            return this._actionHelper(element, aniJSParsedSentence, defaultValue);
605        };
606
607        /**
608         * Helper to setup the after callback function
609         * @method _afterHelper
610         * @param {} element
611         * @param {} aniJSParsedSentence
612         * @return defaultValue
613         */
614        selfish._beforeHelper = function(element, aniJSParsedSentence) {
615            var defaultValue =  aniJSParsedSentence.before;
616            if(!selfish.Util.beArray(defaultValue))
617                return selfish._callbackHelper(element, aniJSParsedSentence, defaultValue);
618            return this._actionHelper(element, aniJSParsedSentence, defaultValue);
619        };
620        /**
621         * The executed actions helper
622         * @author Dariel Noel <[email protected]>
623         * @since  2014-09-10
624         * @param  {[type]}   element             [description]
625         * @param  {[type]}   aniJSParsedSentence [description]
626         * @param  {[type]}   action              [description]
627         * @return {[type]}                       [description]
628         */
629        selfish._actionHelper = function(element, aniJSParsedSentence, action) {
630            var defaultValue = action || '',
631                executeFunction;
632            if(selfish.Util.beArray(defaultValue)) {
633                executeFunction = selfish._callbackHelper(element, aniJSParsedSentence, defaultValue[0]);
634                if(executeFunction) {
635                    defaultValue[0] = executeFunction;
636                } else {
637                    defaultValue = defaultValue.join(' ');
638                }
639
640            }
641            return defaultValue;
642        };
643
644        /**
645         * Helper for before and after helpers refactoring
646         * @method _callbackHelper
647         * @param {} element
648         * @param {} aniJSParsedSentence
649         * @param {} callbackFunction
650         * @return defaultValue
651         */
652        selfish._callbackHelper = function(element, aniJSParsedSentence, callbackFunction) {
653            var defaultValue = callbackFunction || '',
654                helper = selfish._helperHelper(aniJSParsedSentence);
655
656            if (defaultValue) {
657                if (!selfish.Util.isFunction(defaultValue)) {
658                    var helperCollection = selfish._helperCollection,
659                        helperInstance = helperCollection[helper];
660
661                    if (helperInstance && selfish.Util.isFunction(helperInstance[defaultValue])) {
662                        defaultValue = helperInstance[defaultValue];
663                    } else {
664                        defaultValue = false;
665                    }
666                }
667            }
668
669            return defaultValue;
670        };
671
672        /**
673         * Helper to setup the helper of the animation
674         * @method _helperHelper
675         * @param {} element
676         * @param {} aniJSParsedSentence
677         * @return defaultValue
678         */
679        selfish._helperHelper = function(aniJSParsedSentence) {
680            var defaultValue = aniJSParsedSentence.helper || selfish._helperDefaultIndex;
681            return defaultValue;
682        };
683
684        /**
685         * Helper to setup the notifier
686         * @method _notifierHelper
687         * @param {} eventTargetDefinition
688         * @return defaultValue
689         */
690        selfish._notifierHelper = function(eventTargetDefinition) {
691            var defaultValue = [],
692                notifierCollection = AniJS.notifierCollection;
693
694            if (eventTargetDefinition) {
695                //{id: notifierID, value:notifierObject}
696                if (eventTargetDefinition.id && AniJS.EventSystem.isEventTarget(eventTargetDefinition.value)) {
697                    //TODO: In the near future could be an object list
698                    defaultValue.push(eventTargetDefinition.value);
699
700                    AniJS.registerNotifier(eventTargetDefinition);
701                } else if (eventTargetDefinition.split) {
702                    //Picar por signo de peso y obtener la lista de id de events Notifiers
703                    notifierIDList = eventTargetDefinition.split('$');
704                    var size = notifierIDList.length,
705                        i = 1,
706                        notifierID;
707
708                    for (i; i < size; i++) {
709                        notifierID = notifierIDList[i];
710                        if (notifierID && notifierID !== ' ') {
711                            //limpiarle los espacios alante y atras (trim)
712                            notifierID = notifierID.trim();
713
714                            //TODO: Big Refactoring here
715                            var value = AniJS.getNotifier(notifierID);
716                            if (!value) {
717                                value = AniJS.EventSystem.createEventTarget();
718                                AniJS.registerNotifier({
719                                    id: notifierID,
720                                    value: value
721                                });
722                            }
723                            defaultValue.push(value);
724                        }
725                    }
726                }
727            }
728
729            return defaultValue;
730        };
731
732        selfish._paramsHelper = function(paramsArray){
733            var arr = [],
734                i = paramsArray.length;
735            while(i-- > 1) arr[i - 1] = paramsArray[i];
736            return arr;
737        };
738
739        /**
740         * Parse an String Declaration
741         * @method _getParsedAniJSSentenceCollection
742         * @param {} stringDeclaration
743         * @return CallExpression
744         */
745        selfish._getParsedAniJSSentenceCollection = function(stringDeclaration) {
746            return selfish.Parser.parse(stringDeclaration);
747        };
748
749        /**
750         * Select all DOM nodes that have a AniJS declaration
751         * @method _findAniJSNodeCollection
752         * @param {} rootDOMTravelScope
753         * @return CallExpression
754         */
755        selfish._findAniJSNodeCollection = function(rootDOMTravelScope) {
756            //IMPROVE: Might a configuration option
757            var aniJSDataTagName = '[' + ANIJS_DATATAG_NAME + ']';
758            return rootDOMTravelScope.querySelectorAll(aniJSDataTagName);
759        };
760
761        /**
762         * Return the correct AnimationEnd Prefix according to the current browser
763         * @method _animationEndPrefix
764         * @return
765         */
766        selfish._animationEndPrefix = function() {
767            var endPrefixBrowserDetectionIndex = selfish._endPrefixBrowserDetectionIndex(),
768                animationEndBrowserPrefix = [ANIMATION_END, 'oAnimationEnd', ANIMATION_END, 'webkitAnimationEnd'];
769
770            return animationEndBrowserPrefix[endPrefixBrowserDetectionIndex];
771        };
772
773        /**
774         * Return the correct TransitionEnd Prefix according to the current browser
775         * @method _transitionEndPrefix
776         * @return
777         */
778        selfish._transitionEndPrefix = function() {
779            var endPrefixBrowserDetectionIndex = selfish._endPrefixBrowserDetectionIndex(),
780                transitionEndBrowserPrefix = [TRANSITION_END, 'oTransitionEnd', TRANSITION_END, 'webkitTransitionEnd'];
781
782            return transitionEndBrowserPrefix[endPrefixBrowserDetectionIndex];
783        };
784
785        /**
786         * Return the correct Transition and  Animation End Prefix helper according to the current browser
787         * @method _transitionEndPrefix
788         * @return index of the prefix acording to the browser
789         */
790        selfish._endPrefixBrowserDetectionIndex = function() {
791            //TODO: Delete de element after create this
792            var el = document.createElement('fe'),
793                ANIM = 'Animation',
794                animationBrowserDetection = ['animation', 'O'+ANIM, 'Moz'+ANIM, 'webkit'+ANIM];
795
796            for (var i = 0; i < animationBrowserDetection.length; i++) {
797                if (el.style[animationBrowserDetection[i]] !== undefined) {
798                    return i;
799                }
800            }
801        };
802
803        /////////////////////////////////////////////////////////
804        // Private SubModules
805        /////////////////////////////////////////////////////////
806
807        /**
808         * Encapsulate the animation Context
809         * @class animationContext
810         * @author @dariel_noel
811         */
812        AniJS.AnimationContext = (function(config) {
813
814            //TODO: Module aproach here
815            var animationContextInstance = this;
816
817            /**
818             * Class constructor
819             * @method init
820             * @param {} config
821             * @return
822             */
823            animationContextInstance.init = function(config) {
824
825                //TODO: Valorar la idea de usar prototype por performance reasons
826                //ATTRS
827                animationContextInstance.behaviorTargetList = config.behaviorTargetList || [];
828
829                animationContextInstance.nodeHelper = config.nodeHelper;
830
831                animationContextInstance.animationEndEvent = config.animationEndEvent;
832
833                animationContextInstance.behavior = config.behavior;
834
835                animationContextInstance.after = config.after;
836
837                animationContextInstance.eventSystem = config.eventSystem;
838
839                animationContextInstance.eventTarget = config.eventTarget;
840
841                animationContextInstance.afterFunctionName = config.afterFunctionName;
842
843                animationContextInstance.dataAniJSOwner = config.dataAniJSOwner;
844
845                animationContextInstance.listener = config.listener;
846
847                animationContextInstance.event = config.event;
848                animationContextInstance.before = config.before;
849            };
850
851            /**
852             * Custom AniJS animation behavior
853             * @author Dariel Noel <[email protected]>
854             * @since  2014-09-03
855             * @param  {[type]}   target   [description]
856             * @param  {[type]}   behavior [description]
857             * @return {[type]}            [description]
858             */
859            animationContextInstance.doDefaultAction = function(target, behavior){
860                var instance = animationContextInstance,
861                    nodeHelper = instance.nodeHelper,
862                    animationEndEvent = instance.animationEndEvent,
863                    after = instance.after,
864                    afterFunctionName = instance.afterFunctionName,
865                    lastBehavior;
866
867                //create event
868                instance.eventSystem.addEventListenerHelper(target, animationEndEvent, function(e) {
869                    e.stopPropagation();
870                    //remove event
871                    instance.eventSystem.removeEventListenerHelper(e.target, e.type, arguments.callee);
872                    if(after){
873                        if(selfish.Util.isFunction(after)){
874                            after(e, animationContextInstance);
875                        } else if(selfish.Util.beArray(after)) {
876                            after[0](e, animationContextInstance, selfish._paramsHelper(after));
877                        }
878                    }
879                });
880                // Backguard compatibility
881                if (afterFunctionName !== "holdAnimClass" && afterFunctionName !== "$holdAnimClass") {
882                    lastBehavior = target._ajLastBehavior;
883                    if(lastBehavior){
884                        // removing the animation by default if there are not hold animClass
885                        nodeHelper.removeClass(target, lastBehavior);
886                    }
887                    target._ajLastBehavior = behavior;
888                }
889                // Trigger a reflow in between removing and adding the class name.
890                // http://css-tricks.com/restart-css-animation/
891                target.offsetWidth = target.offsetWidth;
892                nodeHelper.addClass(target, behavior);
893            };
894
895            /**
896             * Allows to use a custom helpers function via do definitions
897             * @author Dariel Noel <[email protected]>
898             * @since  2014-09-03
899             * @param  {[type]}   target   [description]
900             * @param  {[type]}   behavior [description]
901             * @return {[type]}            [description]
902             */
903            animationContextInstance.doFunctionAction = function(target, behavior){
904                var instance = animationContextInstance,
905                    after = instance.after,
906                    e = {target:target};
907                behavior[0](e, animationContextInstance, selfish._paramsHelper(behavior));
908                if(selfish.Util.isFunction(after)){
909                    after(e, animationContextInstance);
910                } else {
911                    if(selfish.Util.beArray(after)) {
912                        after[0](e, animationContextInstance, selfish._paramsHelper(after));
913                    }
914                }
915            };
916
917            /**
918             * Create an animation context instance for every behavior target list
919             * and run it
920             * @method run
921             * @return
922             */
923            animationContextInstance.runAll = function() {
924                var instance = animationContextInstance,
925                    behaviorTargetList = instance.behaviorTargetList,
926                    behaviorTargetListSize = behaviorTargetList.length,
927                    behavior = instance.behavior,
928                    j = 0,
929                    before = instance.before,
930                    simpleAnimationContextInstance,
931                    event = animationContextInstance.event,
932                    animationContextConfig;
933
934                for (j; j < behaviorTargetListSize; j++) {
935
936                    animationContextConfig = {
937                        behaviorTargetList: [behaviorTargetList[j]],
938                        nodeHelper: animationContextInstance.nodeHelper,
939                        animationEndEvent: animationContextInstance.animationEndEvent,
940                        behavior: animationContextInstance.behavior,
941                        after: animationContextInstance.after,
942                        eventSystem: animationContextInstance.eventSystem,
943                        eventTarget: animationContextInstance.eventTarget,
944                        afterFunctionName: animationContextInstance.afterFunctionName,
945                        dataAniJSOwner: animationContextInstance.dataAniJSOwner,
946                        listener: animationContextInstance.listener,
947                        event: event
948                        //TODO: eventSystem should be called directly
949                    };
950
951                    simpleAnimationContextInstance = new AniJS.AnimationContext(animationContextConfig);
952                    if (before) {
953                        if(selfish.Util.isFunction(before)) {
954                            before(event, simpleAnimationContextInstance);
955                        } else if(selfish.Util.beArray(before)) {
956                            before[0](event, simpleAnimationContextInstance, selfish._paramsHelper(before));
957                        }
958                    } else {
959                        simpleAnimationContextInstance.run();
960                    }
961                }
962            };
963            /**
964             * Execute an animation context instance
965             * @method run
966             * @return
967             */
968            animationContextInstance.run = function() {
969                var instance = animationContextInstance,
970                    behavior = instance.behavior,
971                    behaviorTargetListItem = instance.behaviorTargetList[0];
972
973                animationContextInstance.hasRunned = 1;
974                if(selfish.Util.beArray(behavior)){
975                    instance
976                        .doFunctionAction(behaviorTargetListItem, behavior);
977                } else{
978                    instance
979                        .doDefaultAction(behaviorTargetListItem, behavior);
980                }
981            };
982
983            animationContextInstance.init(config);
984        });
985
986        /**
987         * Encapsulate the AnimJS sintax parser
988         * @class Parser
989         * @author @dariel_noel
990         */
991        selfish.Parser = {
992
993            /**
994             * Parse a aniJSDeclaration
995             * @method parse
996             * @param {} aniJSDeclaration
997             * @return CallExpression
998             */
999            parse: function(aniJSDeclaration) {
1000                return this.parseDeclaration(aniJSDeclaration);
1001            },
1002
1003            /**
1004             * Declaration parse
1005             *  Sintax: Declaration -> Sentence; | *
1006             *  Example: SentenceA; SentenceB
1007             * @method _parseDeclaration
1008             * @param {} declaration
1009             * @return parsedDeclaration
1010             */
1011            parseDeclaration: function(declaration) {
1012                var parsedDeclaration = [],
1013                    sentenceCollection,
1014                    parsedSentence;
1015
1016                sentenceCollection = declaration.split(';');
1017
1018                var size = sentenceCollection.length,
1019                    i = 0;
1020
1021                for (i; i < size; i++) {
1022                    parsedSentence = this.parseSentence(sentenceCollection[i]);
1023                    parsedDeclaration.push(parsedSentence);
1024                }
1025
1026                return parsedDeclaration;
1027            },
1028
1029            /**
1030             * Sentence Parse
1031             *  Sintax: Sentence -> if, on, do, to, after, helper
1032             *  Example: "if: DOMContentLoaded, on: document, do:flip, to: .animatecss, after: testcallback"
1033             *  note: The order it's not important
1034             * @method _parseSentence
1035             * @param {} sentence
1036             * @return parsedSentence
1037             */
1038            parseSentence: function(sentence) {
1039                var parsedSentence = {},
1040                    definitionCollection,
1041                    parsedDefinition;
1042
1043                definitionCollection = sentence.split(',');
1044
1045                var size = definitionCollection.length,
1046                    i = 0;
1047
1048                for (i; i < size; i++) {
1049                    parsedDefinition = this.parseDefinition(definitionCollection[i]);
1050                    parsedSentence[parsedDefinition.key] = parsedDefinition.value;
1051                }
1052                return parsedSentence;
1053            },
1054
1055            /**
1056             * Parse definition
1057             *  Sintax: Definition -> if | on | do | to | after | helper
1058             *  Example: "if: DOMContentLoaded, on: document, do:flip, to: .animatecss,  after: testcallback"
1059             * @method _parseDefinition
1060             * @param {} definition
1061             * @return parsedDefinition
1062             */
1063            parseDefinition: function(definition) {
1064                var parsedDefinition = {},
1065                    definitionBody,
1066                    definitionKey,
1067                    definitionValue,
1068                    EVENT_KEY = 'event',
1069                    EVENT_TARGET_KEY = 'eventTarget',
1070                    BEHAVIOR_KEY = ['behavior', 'after', 'before', 'behaviorTarget'];
1071
1072                //Performance reasons
1073                definitionBody = definition.split(':');
1074                if (definitionBody.length > 1) {
1075                    definitionKey = definitionBody[0].trim();
1076                    //CSS3 selectors support
1077                    if(definitionBody.length > 2){
1078                        definitionValue = definitionBody.slice(1);
1079                        definitionValue = definitionValue.join(':');
1080                        definitionValue = definitionValue.trim();
1081                    } else {
1082                        definitionValue = definitionBody[1].trim();
1083                    }
1084                    parsedDefinition.value = definitionValue;
1085                    //Change by reserved words
1086                    if (definitionKey === EVENT_RESERVED_WORD) {
1087                        definitionKey = EVENT_KEY;
1088                    } else if (definitionKey === EVENT_TARGET_RESERVED_WORD) {
1089                        definitionKey = EVENT_TARGET_KEY;
1090                    } else {
1091                        for (var i = BEHAVIOR_RESERVED_WORD.length - 1; i >= 0; i--) {
1092                              if(definitionKey === BEHAVIOR_RESERVED_WORD[i]) {
1093                                definitionKey = BEHAVIOR_KEY[i];
1094                                /**
1095                                 * TODO: This code is deprecated for next version
1096                                 */
1097                                if((definitionKey === 'after' || definitionKey === 'before') && definitionValue[0]!== '$') {
1098                                    definitionValue = '$' + definitionValue;
1099                                }
1100                                definitionValue = this.parseDoDefinition(definitionValue);
1101                              }
1102                        }
1103                    }
1104                    parsedDefinition.key = definitionKey;
1105                    parsedDefinition.value = definitionValue;
1106                }
1107
1108                return parsedDefinition;
1109            },
1110
1111            /**
1112             * Allow to parse do definitions
1113             * @author Dariel Noel <[email protected]>
1114             * @since  2014-09-03
1115             * @param  {[type]}   doDefinition [description]
1116             */
1117            parseDoDefinition: function(doDefinition) {
1118                var reg = /^\$(\w+)\s*/g,
1119                    regMatch = reg.exec(doDefinition),
1120                    functionName = "",
1121                    parametersArray = [], it = 1;
1122
1123                if(regMatch !== null) {
1124                    functionName = regMatch[1];
1125                    doDefinitionArray = doDefinition.split(regMatch[0])[1];
1126                    doDefinitionArray = doDefinitionArray !== null ? doDefinitionArray.split(PARAMS_SEPARATOR) : [];
1127                    doDefinition = [];
1128                    doDefinition[0] = functionName;
1129                    for (var i = 0; i < doDefinitionArray.length; i++) {
1130                        if(doDefinitionArray[i] !== "")
1131                            doDefinition[it++] = doDefinitionArray[i].trim();
1132                    }
1133                    return doDefinition;
1134                }
1135                return doDefinition;
1136            }
1137        };
1138
1139        /**
1140         * Helper to DOM manipulation
1141         * @class Parser
1142         * @author @dariel_noel
1143         */
1144        selfish.NodeHelper = {
1145
1146            /**
1147             * Add some classes to a node
1148             * @method addClass
1149             * @param {} elem
1150             * @param {} string
1151             * @return
1152             */
1153            addClass: function(elem, string) {
1154                if (!(string instanceof Array)) {
1155                    string = string.split(' ');
1156                }
1157                for (var i = 0, len = string.length; i < len; ++i) {
1158                    if (string[i] && !new RegExp(REGEX_BEGIN + string[i] + REGEX_END).test(elem.className)) {
1159                        elem.className = (elem.className === "") ?  string[i] : elem.className.trim() + ' ' + string[i];
1160                    }
1161                }
1162            },
1163
1164            /**
1165             * Remove class of some DOM element
1166             * @method removeClass
1167             * @param {} elem
1168             * @param {} string
1169             * @return
1170             */
1171            removeClass: function(elem, string) {
1172                if (!(string instanceof Array)) {
1173                    string = string.split(' ');
1174                }
1175                for (var i = 0, len = string.length; i < len; ++i) {
1176                    elem.className = elem.className.replace(new RegExp(REGEX_BEGIN + string[i] + REGEX_END), ' ').trim();
1177                }
1178            },
1179
1180            /**
1181             * Test if the nested element has the supply class
1182             * @method hasClass
1183             * @param {} elem
1184             * @param {} string
1185             * @return LogicalExpression
1186             */
1187            hasClass: function(elem, string) {
1188                return string && new RegExp(REGEX_BEGIN + string + REGEX_END).test(elem.className);
1189            }
1190        };
1191
1192        /**
1193         * A kind of util functions
1194         * @class Util
1195         * @author @dariel_noel
1196         */
1197        selfish.Util = {
1198
1199            /**
1200             * Thanks a lot to underscore guys
1201             * @method isFunction
1202             * @param {} obj
1203             * @return UnaryExpression
1204             */
1205            isFunction: function(obj) {
1206                return !!(obj && obj.constructor && obj.call && obj.apply);
1207            },
1208            /**
1209             * Test if some object is an array
1210             * @author Dariel Noel <[email protected]>
1211             * @since  2014-09-09
1212             * @return {Boolean}  [description]
1213             */
1214            beArray:function(object){
1215                return Array.isArray(object);
1216            }
1217        };
1218
1219        /////////////////////////////////////////////////////////
1220        // Public SubModules
1221        /////////////////////////////////////////////////////////
1222
1223        /**
1224         * Event System Interface (AniJS Current Implementation)
1225         * @class EventSystem
1226         * @author @dariel_noel
1227         */
1228        AniJS.EventSystem = {
1229
1230            //ATTRS
1231            eventCollection: {},
1232
1233            eventIdCounter: 0,
1234
1235            /**
1236             * Return true if the element it's an event target object
1237             * @method isEventTarget
1238             * @param {} element
1239             * @return true or false
1240             */
1241            isEventTarget: function(element) {
1242                return (element.addEventListener) ? 1 : 0;
1243            },
1244
1245            /**
1246             * Create new EventTarget element
1247             * @method createEventTarget
1248             * @return AniJS.EventTarget
1249             */
1250            createEventTarget: function() {
1251                return new AniJS.EventTarget();
1252            },
1253
1254            /**
1255             * Put a listener in the object
1256             * @method addEventListenerHelper
1257             * @param {} eventTargetItem
1258             * @param {} event
1259             * @param {} listener
1260             * @param {} other
1261             * @return
1262             */
1263            addEventListenerHelper: function(eventTargetItem, event, listener, other) {
1264                eventTargetItem.addEventListener(event, listener, false);
1265            },
1266
1267            /**
1268             * Put a listener of the object
1269             * @method removeEventListenerHelper
1270             * @param {} e
1271             * @param {} arguments
1272             * @return
1273             */
1274            removeEventListenerHelper: function(element, type, listener) {
1275                if(element){
1276                    element.removeEventListener(type, listener);
1277                }
1278            },
1279
1280
1281            /**
1282             * Purge all register elements handle
1283             * @method purgeAll
1284             * @return
1285             */
1286            purgeAll: function() {
1287                var instance = this,
1288                    eventCollection = instance.eventCollection,
1289                    eventCollectionKeyList = Object.keys(eventCollection),
1290                    size = eventCollectionKeyList.length,
1291                    i = 0,
1292                    key,
1293                    eventObject;
1294
1295                for (i; i < size; i++) {
1296                    key = eventCollectionKeyList[i];
1297                    eventObject = eventCollection[key];
1298
1299                    if (eventObject && eventObject.handleCollection && eventObject.handleCollection.length > 0) {
1300                        instance.purgeEventTarget(eventObject.handleCollection[0].element);
1301                    }
1302
1303                    delete eventCollection[key];
1304                }
1305            },
1306
1307            /**
1308             * Detach all AniJS subscriptions to the all nodes bellow this
1309             * @method purgeAllNodes
1310             * @param {} element
1311             * @return
1312             */
1313            purgeAllNodes: function(element){
1314                //Dame todos los que tengan data-anijs
1315                //a cada uno purgue
1316                var nodes = element.querySelectorAll("*");
1317                    size = nodes.length;
1318                for (var i = size - 1; i >= 0; i--) {
1319                    this.purgeEventTarget(nodes[i]);
1320                }
1321            },
1322
1323            /**
1324             * Detach all AniJS subscriptions to this element
1325             * @method purgeEventTarget
1326             * @param {} element
1327             * @return
1328             */
1329            purgeEventTarget: function(element) {
1330                var instance = this,
1331                    aniJSEventID = element._aniJSEventID,
1332                    elementHandleCollection;
1333                if (aniJSEventID) {
1334
1335                    //Se le quitan todos los eventos a los que este suscrito
1336                    elementHandleCollection = instance.eventCollection[aniJSEventID].handleCollection;
1337
1338                    var size = elementHandleCollection.length,
1339                        i = 0,
1340                        item;
1341
1342                    for (i; i < size; i++) {
1343                        item = elementHandleCollection[i];
1344
1345                        //Para cada handle
1346                        instance.removeEventListenerHelper(element, item.eventType, item.listener);
1347
1348                    }
1349                    instance.eventCollection[aniJSEventID] = element._aniJSEventID = null;
1350                    delete instance.eventCollection[aniJSEventID];
1351                    delete element._aniJSEventID;
1352                }
1353            },
1354
1355            /**
1356             * Create a handle to remove the listener when purge it
1357             * @method registerEventHandle
1358             * @param {} element
1359             * @param {} eventType
1360             * @param {} listener
1361             * @return
1362             */
1363            registerEventHandle: function(element, eventType, listener) {
1364                var instance = this,
1365                    aniJSEventID = element._aniJSEventID,
1366                    eventCollection = instance.eventCollection,
1367                    elementEventHandle = {
1368                        eventType: eventType,
1369                        listener: listener,
1370                        element: element
1371                    };
1372
1373                if (aniJSEventID) {
1374                    eventCollection[aniJSEventID].handleCollection.push(elementEventHandle);
1375                } else {
1376                    var tempEventHandle = {
1377                        handleCollection: [elementEventHandle]
1378                    };
1379
1380                    eventCollection[++instance.eventIdCounter] = tempEventHandle;
1381                    element._aniJSEventID = instance.eventIdCounter;
1382                }
1383            }
1384
1385        };
1386
1387
1388        /**
1389         * Helper the custom EventTarget
1390         * Copyright (c) 2010 Nicholas C. Zakas. All rights reserved.
1391         * MIT License
1392         * http://www.nczonline.net/blog/2010/03/09/custom-events-in-javascript/
1393         * @class EventTarget
1394         */
1395        AniJS.EventTarget = function EventTarget() {
1396            this._listeners = {};
1397        };
1398
1399        AniJS.EventTarget.prototype = {
1400
1401            constructor: AniJS.EventTarget,
1402
1403            /**
1404             * Registers the specified listener on the EventTarget it's called on
1405             * Similar to the native implementation
1406             * @method addEventListener
1407             * @param {} type
1408             * @param {} listener
1409             * @param {} other
1410             * @return
1411             */
1412            addEventListener: function(type, listener, other) {
1413                var instance = this;
1414                if (typeof instance._listeners[type] == "undefined") {
1415                    instance._listeners[type] = [];
1416                }
1417
1418                instance._listeners[type].push(listener);
1419            },
1420
1421            /**
1422             * Dispatches an Event at the specified EventTarget
1423             * Similar to the native implementation
1424             * @method dispatchEvent
1425             * @param {} event
1426             * @return
1427             */
1428            dispatchEvent: function(event) {
1429                var instance = this;
1430                if (typeof event == "string") {
1431                    event = {
1432                        type: event
1433                    };
1434                }
1435                if (!event.target) {
1436                    event.target = instance;
1437                }
1438
1439                if (!event.type) { //falsy
1440                    throw new Error("Event object missing 'type' property.");
1441                }
1442
1443                if (this._listeners[event.type] instanceof Array) {
1444                    var listeners = instance._listeners[event.type];
1445
1446                    for (var i = 0, len = listeners.length; i < len; i++) {
1447                        listeners[i].call(instance, event);
1448                    }
1449                }
1450            },
1451
1452            /**
1453             * Removes the event listener previously registered with EventTarget.addEventListener.
1454             * Similar to the native implementation
1455             * @method removeEventListener
1456             * @param {} type
1457             * @param {} listener
1458             * @return
1459             */
1460            removeEventListener: function(type, listener) {
1461                var instance = this;
1462                if (instance._listeners[type] instanceof Array) {
1463                    var listeners = instance._listeners[type];
1464                    for (var i = 0, len = listeners.length; i < len; i++) {
1465                        if (listeners[i] === listener) {
1466                            listeners.splice(i, 1);
1467                            break;
1468                        }
1469                    }
1470                }
1471            }
1472        };
1473
1474        return AniJS;
1475
1476    }(AniJS || {}));
1477
1478    AniJS.init();
1479    AniJS.run();
1480
1481    // https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
1482    // AMD Support
1483    if (typeof define === "function" && define.amd) {
1484        define("anijs", [], function() {
1485            return AniJS;
1486        });
1487    }
1488    if (typeof noGlobal == typeof undefined) {
1489        window.AniJS = AniJS;
1490    }
1491
1492    return AniJS;
1493});

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.