• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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