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: {value: 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 this.installScopeStyle(this._style); | |
121 | |
122 // If no target is bound at attach, default the target to the parent | |
123 // element or shadow host. | |
124 if (!this.target) { | |
125 if (!this.parentElement && this.parentNode.host) { | |
126 this.target = this.parentNode.host; | |
127 } else if (this.parentElement && (window.ShadowDOMPolyfill ? this.pare
ntElement !== wrap(document.body) : this.parentElement !== document.body)) { | |
128 this.target = this.parentElement; | |
129 } | |
130 } | |
131 }, | |
132 | |
133 targetChanged: function(old) { | |
134 if (old) { | |
135 this.removeShadow(old); | |
136 } | |
137 if (this.target) { | |
138 this.addShadow(this.target); | |
139 } | |
140 }, | |
141 | |
142 zChanged: function(old) { | |
143 if (this.target && this.target._paperShadow) { | |
144 var shadow = this.target._paperShadow; | |
145 ['top', 'bottom'].forEach(function(s) { | |
146 shadow[s].classList.remove('paper-shadow-' + s + '-z-' + old); | |
147 shadow[s].classList.add('paper-shadow-' + s + '-z-' + this.z); | |
148 }.bind(this)); | |
149 } | |
150 }, | |
151 | |
152 animatedChanged: function() { | |
153 if (this.target && this.target._paperShadow) { | |
154 var shadow = this.target._paperShadow; | |
155 ['top', 'bottom'].forEach(function(s) { | |
156 if (this.animated) { | |
157 shadow[s].classList.add('paper-shadow-animated'); | |
158 } else { | |
159 shadow[s].classList.remove('paper-shadow-animated'); | |
160 } | |
161 }.bind(this)); | |
162 } | |
163 }, | |
164 | |
165 addShadow: function(node) { | |
166 if (node._paperShadow) { | |
167 return; | |
168 } | |
169 | |
170 var computed = getComputedStyle(node); | |
171 if (!this.hasPosition && computed.position === 'static') { | |
172 node.style.position = 'relative'; | |
173 } | |
174 node.style.overflow = 'visible'; | |
175 | |
176 // Both the top and bottom shadows are children of the target, so | |
177 // it does not affect the classes and CSS properties of the target. | |
178 ['top', 'bottom'].forEach(function(s) { | |
179 var inner = (node._paperShadow && node._paperShadow[s]) || document.cr
eateElement('div'); | |
180 inner.classList.add('paper-shadow'); | |
181 inner.classList.add('paper-shadow-' + s + '-z-' + this.z); | |
182 if (this.animated) { | |
183 inner.classList.add('paper-shadow-animated'); | |
184 } | |
185 | |
186 if (node.shadowRoot) { | |
187 node.shadowRoot.insertBefore(inner, node.shadowRoot.firstChild); | |
188 } else { | |
189 node.insertBefore(inner, node.firstChild); | |
190 } | |
191 | |
192 node._paperShadow = node._paperShadow || {}; | |
193 node._paperShadow[s] = inner; | |
194 }.bind(this)); | |
195 | |
196 }, | |
197 | |
198 removeShadow: function(node) { | |
199 if (!node._paperShadow) { | |
200 return; | |
201 } | |
202 | |
203 ['top', 'bottom'].forEach(function(s) { | |
204 node._paperShadow[s].remove(); | |
205 }); | |
206 node._paperShadow = null; | |
207 | |
208 node.style.position = null; | |
209 } | |
210 | |
211 }); | |
212 </script> | |
213 </polymer-element> | |
OLD | NEW |