Home | History | Annotate | Download | only in paper-shadow
      1 
      2     Polymer('paper-shadow', {
      3 
      4       publish: {
      5         /**
      6          * If set, the shadow is applied to this node.
      7          *
      8          * @attribute target
      9          * @type Element
     10          * @default null
     11          */
     12         target: {value: null, reflect: true},
     13 
     14         /**
     15          * The z-depth of this shadow, from 0-5.
     16          *
     17          * @attribute z
     18          * @type number
     19          * @default 1
     20          */
     21         z: {value: 1, reflect: true},
     22 
     23         /**
     24          * If true, the shadow animates between z-depth changes.
     25          *
     26          * @attribute animated
     27          * @type boolean
     28          * @default false
     29          */
     30         animated: {value: false, reflect: true},
     31 
     32         /**
     33          * Workaround: getComputedStyle is wrong sometimes so `paper-shadow`
     34          * may overwrite the `position` CSS property. Set this property to
     35          * true to prevent this.
     36          *
     37          * @attribute hasPosition
     38          * @type boolean
     39          * @default false
     40          */
     41         hasPosition: {value: false}
     42       },
     43 
     44       // NOTE: include template so that styles are loaded, but remove
     45       // so that we can decide dynamically what part to include
     46       registerCallback: function(polymerElement) {
     47         var template = polymerElement.querySelector('template');
     48         this._style = template.content.querySelector('style');
     49         this._style.removeAttribute('no-shim');
     50       },
     51 
     52       fetchTemplate: function() {
     53         return null;
     54       },
     55 
     56       attached: function() {
     57         this.installScopeStyle(this._style);
     58 
     59         // If no target is bound at attach, default the target to the parent
     60         // element or shadow host.
     61         if (!this.target) {
     62           if (!this.parentElement && this.parentNode.host) {
     63             this.target = this.parentNode.host;
     64           } else if (this.parentElement && (window.ShadowDOMPolyfill ? this.parentElement !== wrap(document.body) : this.parentElement !== document.body)) {
     65             this.target = this.parentElement;
     66           }
     67         }
     68       },
     69 
     70       targetChanged: function(old) {
     71         if (old) {
     72           this.removeShadow(old);
     73         }
     74         if (this.target) {
     75           this.addShadow(this.target);
     76         }
     77       },
     78 
     79       zChanged: function(old) {
     80         if (this.target && this.target._paperShadow) {
     81           var shadow = this.target._paperShadow;
     82           ['top', 'bottom'].forEach(function(s) {
     83             shadow[s].classList.remove('paper-shadow-' + s + '-z-' + old);
     84             shadow[s].classList.add('paper-shadow-' + s + '-z-' + this.z);
     85           }.bind(this));
     86         }
     87       },
     88 
     89       animatedChanged: function() {
     90         if (this.target && this.target._paperShadow) {
     91           var shadow = this.target._paperShadow;
     92           ['top', 'bottom'].forEach(function(s) {
     93             if (this.animated) {
     94               shadow[s].classList.add('paper-shadow-animated');
     95             } else {
     96               shadow[s].classList.remove('paper-shadow-animated');
     97             }
     98           }.bind(this));
     99         }
    100       },
    101 
    102       addShadow: function(node) {
    103         if (node._paperShadow) {
    104           return;
    105         }
    106 
    107         var computed = getComputedStyle(node);
    108         if (!this.hasPosition && computed.position === 'static') {
    109           node.style.position = 'relative';
    110         }
    111         node.style.overflow = 'visible';
    112 
    113         // Both the top and bottom shadows are children of the target, so
    114         // it does not affect the classes and CSS properties of the target.
    115         ['top', 'bottom'].forEach(function(s) {
    116           var inner = (node._paperShadow && node._paperShadow[s]) || document.createElement('div');
    117           inner.classList.add('paper-shadow');
    118           inner.classList.add('paper-shadow-' + s + '-z-' + this.z);
    119           if (this.animated) {
    120             inner.classList.add('paper-shadow-animated');
    121           }
    122 
    123           if (node.shadowRoot) {
    124             node.shadowRoot.insertBefore(inner, node.shadowRoot.firstChild);
    125           } else {
    126             node.insertBefore(inner, node.firstChild);
    127           }
    128 
    129           node._paperShadow = node._paperShadow || {};
    130           node._paperShadow[s] = inner;
    131         }.bind(this));
    132 
    133       },
    134 
    135       removeShadow: function(node) {
    136         if (!node._paperShadow) {
    137           return;
    138         }
    139 
    140         ['top', 'bottom'].forEach(function(s) {
    141           node._paperShadow[s].remove();
    142         });
    143         node._paperShadow = null;
    144 
    145         node.style.position = null;
    146       }
    147 
    148     });
    149