Home | History | Annotate | Download | only in neon-animation
      1 <!--
      2 @license
      3 Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
      4 This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
      5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
      6 The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
      7 Code distributed by Google as part of the polymer project is also
      8 subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
      9 -->
     10 
     11 <link rel="import" href="../polymer/polymer.html">
     12 
     13 <script>
     14 
     15   /**
     16    * `Polymer.NeonAnimatableBehavior` is implemented by elements containing animations for use with
     17    * elements implementing `Polymer.NeonAnimationRunnerBehavior`.
     18    * @polymerBehavior
     19    */
     20   Polymer.NeonAnimatableBehavior = {
     21 
     22     properties: {
     23 
     24       /**
     25        * Animation configuration. See README for more info.
     26        */
     27       animationConfig: {
     28         type: Object
     29       },
     30 
     31       /**
     32        * Convenience property for setting an 'entry' animation. Do not set `animationConfig.entry`
     33        * manually if using this. The animated node is set to `this` if using this property.
     34        */
     35       entryAnimation: {
     36         observer: '_entryAnimationChanged',
     37         type: String
     38       },
     39 
     40       /**
     41        * Convenience property for setting an 'exit' animation. Do not set `animationConfig.exit`
     42        * manually if using this. The animated node is set to `this` if using this property.
     43        */
     44       exitAnimation: {
     45         observer: '_exitAnimationChanged',
     46         type: String
     47       }
     48 
     49     },
     50 
     51     _entryAnimationChanged: function() {
     52       this.animationConfig = this.animationConfig || {};
     53       this.animationConfig['entry'] = [{
     54         name: this.entryAnimation,
     55         node: this
     56       }];
     57     },
     58 
     59     _exitAnimationChanged: function() {
     60       this.animationConfig = this.animationConfig || {};
     61       this.animationConfig['exit'] = [{
     62         name: this.exitAnimation,
     63         node: this
     64       }];
     65     },
     66 
     67     _copyProperties: function(config1, config2) {
     68       // shallowly copy properties from config2 to config1
     69       for (var property in config2) {
     70         config1[property] = config2[property];
     71       }
     72     },
     73 
     74     _cloneConfig: function(config) {
     75       var clone = {
     76         isClone: true
     77       };
     78       this._copyProperties(clone, config);
     79       return clone;
     80     },
     81 
     82     _getAnimationConfigRecursive: function(type, map, allConfigs) {
     83       if (!this.animationConfig) {
     84         return;
     85       }
     86 
     87       if(this.animationConfig.value && typeof this.animationConfig.value === 'function') {
     88       	this._warn(this._logf('playAnimation', "Please put 'animationConfig' inside of your components 'properties' object instead of outside of it."));
     89       	return;
     90       }
     91 
     92       // type is optional
     93       var thisConfig;
     94       if (type) {
     95         thisConfig = this.animationConfig[type];
     96       } else {
     97         thisConfig = this.animationConfig;
     98       }
     99 
    100       if (!Array.isArray(thisConfig)) {
    101         thisConfig = [thisConfig];
    102       }
    103 
    104       // iterate animations and recurse to process configurations from child nodes
    105       if (thisConfig) {
    106         for (var config, index = 0; config = thisConfig[index]; index++) {
    107           if (config.animatable) {
    108             config.animatable._getAnimationConfigRecursive(config.type || type, map, allConfigs);
    109           } else {
    110             if (config.id) {
    111               var cachedConfig = map[config.id];
    112               if (cachedConfig) {
    113                 // merge configurations with the same id, making a clone lazily
    114                 if (!cachedConfig.isClone) {
    115                   map[config.id] = this._cloneConfig(cachedConfig)
    116                   cachedConfig = map[config.id];
    117                 }
    118                 this._copyProperties(cachedConfig, config);
    119               } else {
    120                 // put any configs with an id into a map
    121                 map[config.id] = config;
    122               }
    123             } else {
    124               allConfigs.push(config);
    125             }
    126           }
    127         }
    128       }
    129     },
    130 
    131     /**
    132      * An element implementing `Polymer.NeonAnimationRunnerBehavior` calls this method to configure
    133      * an animation with an optional type. Elements implementing `Polymer.NeonAnimatableBehavior`
    134      * should define the property `animationConfig`, which is either a configuration object
    135      * or a map of animation type to array of configuration objects.
    136      */
    137     getAnimationConfig: function(type) {
    138       var map = {};
    139       var allConfigs = [];
    140       this._getAnimationConfigRecursive(type, map, allConfigs);
    141       // append the configurations saved in the map to the array
    142       for (var key in map) {
    143         allConfigs.push(map[key]);
    144       }
    145       return allConfigs;
    146     }
    147 
    148   };
    149 
    150 </script>
    151