OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Counter used to give animations unique names. | 5 // Counter used to give animations unique names. |
6 var animationCounter = 0; | 6 var animationCounter = 0; |
7 | 7 |
8 var animationEventTracker_ = new EventTracker(); | 8 var animationEventTracker = new EventTracker(); |
9 | 9 |
10 function addAnimation(code) { | 10 function addAnimation(code) { |
11 var name = 'anim' + animationCounter; | 11 var name = 'anim' + animationCounter; |
12 animationCounter++; | 12 animationCounter++; |
13 var rules = document.createTextNode( | 13 var rules = document.createTextNode( |
14 '@keyframes ' + name + ' {' + code + '}'); | 14 '@keyframes ' + name + ' {' + code + '}'); |
15 var el = document.createElement('style'); | 15 var el = document.createElement('style'); |
16 el.type = 'text/css'; | 16 el.type = 'text/css'; |
17 el.appendChild(rules); | 17 el.appendChild(rules); |
18 el.setAttribute('id', name); | 18 el.setAttribute('id', name); |
(...skipping 28 matching lines...) Expand all Loading... |
47 el.hidden = false; | 47 el.hidden = false; |
48 el.setAttribute('aria-hidden', 'false'); | 48 el.setAttribute('aria-hidden', 'false'); |
49 el.style.height = 'auto'; | 49 el.style.height = 'auto'; |
50 var height = el.offsetHeight; | 50 var height = el.offsetHeight; |
51 if (opt_justShow) { | 51 if (opt_justShow) { |
52 el.style.height = ''; | 52 el.style.height = ''; |
53 el.style.opacity = ''; | 53 el.style.opacity = ''; |
54 } else { | 54 } else { |
55 el.style.height = height + 'px'; | 55 el.style.height = height + 'px'; |
56 var animName = addAnimation(getFadeInAnimationCode(height)); | 56 var animName = addAnimation(getFadeInAnimationCode(height)); |
57 animationEventTracker_.add( | 57 animationEventTracker.add( |
58 el, 'animationend', onFadeInAnimationEnd.bind(el), false); | 58 el, 'animationend', onFadeInAnimationEnd.bind(el), false); |
59 el.style.animationName = animName; | 59 el.style.animationName = animName; |
60 } | 60 } |
61 el.classList.add('visible'); | 61 el.classList.add('visible'); |
62 } | 62 } |
63 | 63 |
64 /** | 64 /** |
65 * Fades out an element. Used for both printing options and error messages | 65 * Fades out an element. Used for both printing options and error messages |
66 * appearing underneath the textfields. | 66 * appearing underneath the textfields. |
67 * @param {HTMLElement} el The element to be faded out. | 67 * @param {HTMLElement} el The element to be faded out. |
68 */ | 68 */ |
69 function fadeOutElement(el) { | 69 function fadeOutElement(el) { |
70 if (!el.classList.contains('visible')) | 70 if (!el.classList.contains('visible')) |
71 return; | 71 return; |
72 fadeInAnimationCleanup(el); | 72 fadeInAnimationCleanup(el); |
73 el.style.height = 'auto'; | 73 el.style.height = 'auto'; |
74 var height = el.offsetHeight; | 74 var height = el.offsetHeight; |
75 el.style.height = height + 'px'; | 75 el.style.height = height + 'px'; |
| 76 /** @suppress {suspiciousCode} */ |
76 el.offsetHeight; // Should force an update of the computed style. | 77 el.offsetHeight; // Should force an update of the computed style. |
77 animationEventTracker_.add( | 78 animationEventTracker.add( |
78 el, 'transitionend', onFadeOutTransitionEnd.bind(el), false); | 79 el, 'transitionend', onFadeOutTransitionEnd.bind(el), false); |
79 el.classList.add('closing'); | 80 el.classList.add('closing'); |
80 el.classList.remove('visible'); | 81 el.classList.remove('visible'); |
81 el.setAttribute('aria-hidden', 'true'); | 82 el.setAttribute('aria-hidden', 'true'); |
82 } | 83 } |
83 | 84 |
84 /** | 85 /** |
85 * Executes when a fade out animation ends. | 86 * Executes when a fade out animation ends. |
86 * @param {Event} event The event that triggered this listener. | 87 * @param {Event} event The event that triggered this listener. |
87 * @this {HTMLElement} The element where the transition occurred. | 88 * @this {HTMLElement} The element where the transition occurred. |
88 */ | 89 */ |
89 function onFadeOutTransitionEnd(event) { | 90 function onFadeOutTransitionEnd(event) { |
90 if (event.propertyName != 'height') | 91 if (event.propertyName != 'height') |
91 return; | 92 return; |
92 animationEventTracker_.remove(this, 'transitionend'); | 93 animationEventTracker.remove(this, 'transitionend'); |
93 this.hidden = true; | 94 this.hidden = true; |
94 } | 95 } |
95 | 96 |
96 /** | 97 /** |
97 * Executes when a fade in animation ends. | 98 * Executes when a fade in animation ends. |
98 * @param {Event} event The event that triggered this listener. | 99 * @param {Event} event The event that triggered this listener. |
99 * @this {HTMLElement} The element where the transition occurred. | 100 * @this {HTMLElement} The element where the transition occurred. |
100 */ | 101 */ |
101 function onFadeInAnimationEnd(event) { | 102 function onFadeInAnimationEnd(event) { |
102 this.style.height = ''; | 103 this.style.height = ''; |
103 fadeInAnimationCleanup(this); | 104 fadeInAnimationCleanup(this); |
104 } | 105 } |
105 | 106 |
106 /** | 107 /** |
107 * Removes the <style> element corresponding to |animationName| from the DOM. | 108 * Removes the <style> element corresponding to |animationName| from the DOM. |
108 * @param {HTMLElement} element The animated element. | 109 * @param {HTMLElement} element The animated element. |
109 */ | 110 */ |
110 function fadeInAnimationCleanup(element) { | 111 function fadeInAnimationCleanup(element) { |
111 if (element.style.animationName) { | 112 if (element.style.animationName) { |
112 var animEl = document.getElementById(element.style.animationName); | 113 var animEl = document.getElementById(element.style.animationName); |
113 if (animEl) | 114 if (animEl) |
114 animEl.parentNode.removeChild(animEl); | 115 animEl.parentNode.removeChild(animEl); |
115 element.style.animationName = ''; | 116 element.style.animationName = ''; |
116 animationEventTracker_.remove(element, 'animationend'); | 117 animationEventTracker.remove(element, 'animationend'); |
117 } | 118 } |
118 } | 119 } |
119 | 120 |
120 /** | 121 /** |
121 * Fades in a printing option existing under |el|. | 122 * Fades in a printing option existing under |el|. |
122 * @param {HTMLElement} el The element to hide. | 123 * @param {HTMLElement} el The element to hide. |
123 * @param {boolean=} opt_justShow Whether {@code el} should be hidden with no | 124 * @param {boolean=} opt_justShow Whether {@code el} should be hidden with no |
124 * animation. | 125 * animation. |
125 */ | 126 */ |
126 function fadeInOption(el, opt_justShow) { | 127 function fadeInOption(el, opt_justShow) { |
127 if (el.classList.contains('visible')) | 128 if (el.classList.contains('visible')) |
128 return; | 129 return; |
129 // To make the option visible during the first fade in. | 130 // To make the option visible during the first fade in. |
130 el.hidden = false; | 131 el.hidden = false; |
131 | 132 |
132 var leftColumn = el.querySelector('.left-column'); | 133 var leftColumn = assertInstanceof(el.querySelector('.left-column'), |
| 134 HTMLElement); |
133 wrapContentsInDiv(leftColumn, ['invisible']); | 135 wrapContentsInDiv(leftColumn, ['invisible']); |
134 var rightColumn = el.querySelector('.right-column'); | 136 var rightColumn = assertInstanceof(el.querySelector('.right-column'), |
| 137 HTMLElement); |
135 wrapContentsInDiv(rightColumn, ['invisible']); | 138 wrapContentsInDiv(rightColumn, ['invisible']); |
136 | 139 |
137 var toAnimate = el.querySelectorAll('.collapsible'); | 140 var toAnimate = el.querySelectorAll('.collapsible'); |
138 for (var i = 0; i < toAnimate.length; i++) | 141 for (var i = 0; i < toAnimate.length; i++) |
139 fadeInElement(toAnimate[i], opt_justShow); | 142 fadeInElement(assertInstanceof(toAnimate[i], HTMLElement), opt_justShow); |
140 el.classList.add('visible'); | 143 el.classList.add('visible'); |
141 } | 144 } |
142 | 145 |
143 /** | 146 /** |
144 * Fades out a printing option existing under |el|. | 147 * Fades out a printing option existing under |el|. |
145 * @param {HTMLElement} el The element to hide. | 148 * @param {HTMLElement} el The element to hide. |
146 * @param {boolean=} opt_justHide Whether {@code el} should be hidden with no | 149 * @param {boolean=} opt_justHide Whether {@code el} should be hidden with no |
147 * animation. | 150 * animation. |
148 */ | 151 */ |
149 function fadeOutOption(el, opt_justHide) { | 152 function fadeOutOption(el, opt_justHide) { |
150 if (!el.classList.contains('visible')) | 153 if (!el.classList.contains('visible')) |
151 return; | 154 return; |
152 | 155 |
153 var leftColumn = el.querySelector('.left-column'); | 156 var leftColumn = assertInstanceof(el.querySelector('.left-column'), |
| 157 HTMLElement); |
154 wrapContentsInDiv(leftColumn, ['visible']); | 158 wrapContentsInDiv(leftColumn, ['visible']); |
155 var rightColumn = el.querySelector('.right-column'); | 159 var rightColumn = assertInstanceof(el.querySelector('.right-column'), |
156 wrapContentsInDiv(rightColumn, ['visible']); | 160 HTMLElement); |
| 161 if (rightColumn) |
| 162 wrapContentsInDiv(rightColumn, ['visible']); |
157 | 163 |
158 var toAnimate = el.querySelectorAll('.collapsible'); | 164 var toAnimate = el.querySelectorAll('.collapsible'); |
159 for (var i = 0; i < toAnimate.length; i++) { | 165 for (var i = 0; i < toAnimate.length; i++) { |
160 if (opt_justHide) { | 166 if (opt_justHide) { |
161 toAnimate[i].hidden = true; | 167 toAnimate[i].hidden = true; |
162 toAnimate[i].classList.add('closing'); | 168 toAnimate[i].classList.add('closing'); |
163 toAnimate[i].classList.remove('visible'); | 169 toAnimate[i].classList.remove('visible'); |
164 } else { | 170 } else { |
165 fadeOutElement(toAnimate[i]); | 171 fadeOutElement(assertInstanceof(toAnimate[i], HTMLElement)); |
166 } | 172 } |
167 } | 173 } |
168 el.classList.remove('visible'); | 174 el.classList.remove('visible'); |
169 } | 175 } |
170 | 176 |
171 /** | 177 /** |
172 * Wraps the contents of |el| in a div element and attaches css classes | 178 * Wraps the contents of |el| in a div element and attaches css classes |
173 * |classes| in the new div, only if has not been already done. It is necessary | 179 * |classes| in the new div, only if has not been already done. It is necessary |
174 * for animating the height of table cells. | 180 * for animating the height of table cells. |
175 * @param {HTMLElement} el The element to be processed. | 181 * @param {!HTMLElement} el The element to be processed. |
176 * @param {array} classes The css classes to add. | 182 * @param {!Array} classes The css classes to add. |
177 */ | 183 */ |
178 function wrapContentsInDiv(el, classes) { | 184 function wrapContentsInDiv(el, classes) { |
179 var div = el.querySelector('div'); | 185 var div = el.querySelector('div'); |
180 if (!div || !div.classList.contains('collapsible')) { | 186 if (!div || !div.classList.contains('collapsible')) { |
181 div = document.createElement('div'); | 187 div = document.createElement('div'); |
182 while (el.childNodes.length > 0) | 188 while (el.childNodes.length > 0) |
183 div.appendChild(el.firstChild); | 189 div.appendChild(el.firstChild); |
184 el.appendChild(div); | 190 el.appendChild(div); |
185 } | 191 } |
186 | 192 |
187 div.className = ''; | 193 div.className = ''; |
188 div.classList.add('collapsible'); | 194 div.classList.add('collapsible'); |
189 for (var i = 0; i < classes.length; i++) | 195 for (var i = 0; i < classes.length; i++) |
190 div.classList.add(classes[i]); | 196 div.classList.add(classes[i]); |
191 } | 197 } |
OLD | NEW |