OLD | NEW |
| (Empty) |
1 <!-- | |
2 Copyright (c) 2014 The Polymer Project Authors. All rights reserved. | |
3 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt | |
4 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt | |
5 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt | |
6 Code distributed by Google as part of the polymer project is also | |
7 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt | |
8 --> | |
9 | |
10 <!-- | |
11 The `paper-shadow` element is a helper to add shadows to elements. | |
12 Paper shadows are composed of two shadows on top of each other. We | |
13 mimic this effect by using two elements on top of each other, each with a | |
14 different drop shadow. You can apply the shadow to an element by assigning | |
15 it as the target. If you do not specify a target, the shadow is applied to | |
16 the `paper-shadow` element's parent element or shadow host element if its | |
17 parent is a shadow root. Alternatively, you can use the CSS classes included | |
18 by this element directly. | |
19 | |
20 Example: | |
21 | |
22 <div id="myCard" class="card"></div> | |
23 <paper-shadow id="myShadow" z="1"></div> | |
24 | |
25 // Assign a target explicitly | |
26 myShadow.target = document.getElementById('myCard'); | |
27 | |
28 // Auto-assign the target. | |
29 <div class="card"> | |
30 <paper-shadow z="1"></paper-shadow> | |
31 </div> | |
32 | |
33 // Use the classes directly | |
34 <div class="card paper-shadow-top paper-shadow-top-z-1"> | |
35 <div class="card-inner paper-shadow-bottom paper-shadow-bottom-z-1"></div> | |
36 </div> | |
37 | |
38 If you assign a target to a `paper-shadow` element, it creates two nodes and ins
erts | |
39 them as the first children of the target, or the first children of the target's
shadow | |
40 root if there is one. This implies: | |
41 | |
42 1. If the primary node that drops the shadow has styling that affects its shap
e, | |
43 the same styling must be applied to elements with class `paper-shadow`. | |
44 `border-radius` is a very common property and is inherited automatically. | |
45 | |
46 2. The target's overflow property will be set to `overflow: visible` because t
he | |
47 shadow is rendered beyond the bounds of its container. Position the shadow
as a | |
48 separate layer and use a different child element for clipping if needed. | |
49 | |
50 @group Paper Elements | |
51 @class paper-shadow | |
52 --> | |
53 | |
54 <link href="../polymer/polymer.html" rel="import"> | |
55 | |
56 <polymer-element name="paper-shadow"> | |
57 | |
58 <template> | |
59 | |
60 <link no-shim href="paper-shadow.css" rel="stylesheet"> | |
61 | |
62 </template> | |
63 | |
64 <script> | |
65 Polymer('paper-shadow', { | |
66 | |
67 publish: { | |
68 /** | |
69 * If set, the shadow is applied to this node. | |
70 * | |
71 * @attribute target | |
72 * @type Element | |
73 * @default null | |
74 */ | |
75 target: {value: null, reflect: true}, | |
76 | |
77 /** | |
78 * The z-depth of this shadow, from 0-5. | |
79 * | |
80 * @attribute z | |
81 * @type number | |
82 * @default 1 | |
83 */ | |
84 z: {value: 1, reflect: true}, | |
85 | |
86 /** | |
87 * If true, the shadow animates between z-depth changes. | |
88 * | |
89 * @attribute animated | |
90 * @type boolean | |
91 * @default false | |
92 */ | |
93 animated: {value: false, reflect: true}, | |
94 | |
95 /** | |
96 * Workaround: getComputedStyle is wrong sometimes so `paper-shadow` | |
97 * may overwrite the `position` CSS property. Set this property to | |
98 * true to prevent this. | |
99 * | |
100 * @attribute hasPosition | |
101 * @type boolean | |
102 * @default false | |
103 */ | |
104 hasPosition: false | |
105 }, | |
106 | |
107 // NOTE: include template so that styles are loaded, but remove | |
108 // so that we can decide dynamically what part to include | |
109 registerCallback: function(polymerElement) { | |
110 var template = polymerElement.querySelector('template'); | |
111 this._style = template.content.querySelector('style'); | |
112 this._style.removeAttribute('no-shim'); | |
113 }, | |
114 | |
115 fetchTemplate: function() { | |
116 return null; | |
117 }, | |
118 | |
119 attached: function() { | |
120 // If no target is bound at attach, default the target to the parent | |
121 // element or shadow host. | |
122 if (!this.target) { | |
123 if (!this.parentElement && this.parentNode.host) { | |
124 this.target = this.parentNode.host; | |
125 } else if (this.parentElement && (window.ShadowDOMPolyfill ? this.pare
ntElement !== wrap(document.body) : this.parentElement !== document.body)) { | |
126 this.target = this.parentElement; | |
127 } | |
128 } | |
129 }, | |
130 | |
131 targetChanged: function(old) { | |
132 if (old) { | |
133 this.removeShadow(old); | |
134 } | |
135 if (this.target) { | |
136 this.addShadow(this.target); | |
137 } | |
138 }, | |
139 | |
140 zChanged: function(old) { | |
141 if (this.target && this.target._paperShadow) { | |
142 var shadow = this.target._paperShadow; | |
143 ['top', 'bottom'].forEach(function(s) { | |
144 shadow[s].classList.remove('paper-shadow-' + s + '-z-' + old); | |
145 shadow[s].classList.add('paper-shadow-' + s + '-z-' + this.z); | |
146 }.bind(this)); | |
147 } | |
148 }, | |
149 | |
150 animatedChanged: function() { | |
151 if (this.target && this.target._paperShadow) { | |
152 var shadow = this.target._paperShadow; | |
153 ['top', 'bottom'].forEach(function(s) { | |
154 if (this.animated) { | |
155 shadow[s].classList.add('paper-shadow-animated'); | |
156 } else { | |
157 shadow[s].classList.remove('paper-shadow-animated'); | |
158 } | |
159 }.bind(this)); | |
160 } | |
161 }, | |
162 | |
163 addShadow: function(node) { | |
164 if (node._paperShadow) { | |
165 return; | |
166 } | |
167 | |
168 if (!node._hasShadowStyle) { | |
169 if (!node.shadowRoot) { | |
170 node.createShadowRoot().innerHTML = '<content></content>'; | |
171 } | |
172 this.installScopeStyle(this._style, 'shadow', node.shadowRoot); | |
173 node._hasShadowStyle = true; | |
174 } | |
175 | |
176 var computed = getComputedStyle(node); | |
177 if (!this.hasPosition && computed.position === 'static') { | |
178 node.style.position = 'relative'; | |
179 } | |
180 node.style.overflow = 'visible'; | |
181 | |
182 // Both the top and bottom shadows are children of the target, so | |
183 // it does not affect the classes and CSS properties of the target. | |
184 ['top', 'bottom'].forEach(function(s) { | |
185 var inner = (node._paperShadow && node._paperShadow[s]) || document.cr
eateElement('div'); | |
186 inner.classList.add('paper-shadow'); | |
187 inner.classList.add('paper-shadow-' + s + '-z-' + this.z); | |
188 if (this.animated) { | |
189 inner.classList.add('paper-shadow-animated'); | |
190 } | |
191 | |
192 if (node.shadowRoot) { | |
193 node.shadowRoot.insertBefore(inner, node.shadowRoot.firstChild); | |
194 } else { | |
195 node.insertBefore(inner, node.firstChild); | |
196 } | |
197 | |
198 node._paperShadow = node._paperShadow || {}; | |
199 node._paperShadow[s] = inner; | |
200 }.bind(this)); | |
201 | |
202 }, | |
203 | |
204 removeShadow: function(node) { | |
205 if (!node._paperShadow) { | |
206 return; | |
207 } | |
208 | |
209 ['top', 'bottom'].forEach(function(s) { | |
210 node._paperShadow[s].remove(); | |
211 }); | |
212 node._paperShadow = null; | |
213 | |
214 node.style.position = null; | |
215 } | |
216 | |
217 }); | |
218 </script> | |
219 </polymer-element> | |
OLD | NEW |