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
3 // found in the LICENSE file.
5 // Counter used to give webkit animations unique names.
6 var animationCounter = 0;
8 var animationEventTracker_ = new EventTracker();
10 function addAnimation(code) {
11 var name = 'anim' + animationCounter;
13 var rules = document.createTextNode(
14 '@-webkit-keyframes ' + name + ' {' + code + '}');
15 var el = document.createElement('style');
17 el.appendChild(rules);
18 el.setAttribute('id', name);
19 document.body.appendChild(el);
25 * Generates css code for fading in an element by animating the height.
26 * @param {number} targetHeight The desired height in pixels after the animation
28 * @return {string} The css code for the fade in animation.
30 function getFadeInAnimationCode(targetHeight) {
31 return '0% { opacity: 0; height: 0; } ' +
32 '80% { opacity: 0.5; height: ' + (targetHeight + 4) + 'px; }' +
33 '100% { opacity: 1; height: ' + targetHeight + 'px; }';
37 * Fades in an element. Used for both printing options and error messages
38 * appearing underneath the textfields.
39 * @param {HTMLElement} el The element to be faded in.
41 function fadeInElement(el) {
42 if (el.classList.contains('visible'))
44 el.classList.remove('closing');
46 el.style.height = 'auto';
47 var height = el.offsetHeight;
48 el.style.height = height + 'px';
49 var animName = addAnimation(getFadeInAnimationCode(height));
50 animationEventTracker_.add(
51 el, 'webkitAnimationEnd', onFadeInAnimationEnd.bind(el), false);
52 el.style.webkitAnimationName = animName;
53 el.classList.add('visible');
57 * Fades out an element. Used for both printing options and error messages
58 * appearing underneath the textfields.
59 * @param {HTMLElement} el The element to be faded out.
61 function fadeOutElement(el) {
62 if (!el.classList.contains('visible'))
64 fadeInAnimationCleanup(el);
65 el.style.height = 'auto';
66 var height = el.offsetHeight;
67 el.style.height = height + 'px';
68 el.offsetHeight; // Should force an update of the computed style.
69 animationEventTracker_.add(
70 el, 'webkitTransitionEnd', onFadeOutTransitionEnd.bind(el), false);
71 el.classList.add('closing');
72 el.classList.remove('visible');
76 * Executes when a fade out animation ends.
77 * @param {WebkitTransitionEvent} event The event that triggered this listener.
78 * @this {HTMLElement} The element where the transition occurred.
80 function onFadeOutTransitionEnd(event) {
81 if (event.propertyName != 'height')
83 animationEventTracker_.remove(this, 'webkitTransitionEnd');
88 * Executes when a fade in animation ends.
89 * @param {WebkitAnimationEvent} event The event that triggered this listener.
90 * @this {HTMLElement} The element where the transition occurred.
92 function onFadeInAnimationEnd(event) {
93 this.style.height = '';
94 fadeInAnimationCleanup(this);
98 * Removes the <style> element corresponding to |animationName| from the DOM.
99 * @param {HTMLElement} element The animated element.
101 function fadeInAnimationCleanup(element) {
102 if (element.style.webkitAnimationName) {
103 var animEl = document.getElementById(element.style.webkitAnimationName);
105 animEl.parentNode.removeChild(animEl);
106 element.style.webkitAnimationName = '';
107 animationEventTracker_.remove(element, 'webkitAnimationEnd');
112 * Fades in a printing option existing under |el|.
113 * @param {HTMLElement} el The element to hide.
115 function fadeInOption(el) {
116 if (el.classList.contains('visible'))
118 // To make the option visible during the first fade in.
121 wrapContentsInDiv(el.querySelector('h1'), ['invisible']);
122 var rightColumn = el.querySelector('.right-column');
123 wrapContentsInDiv(rightColumn, ['invisible']);
125 var toAnimate = el.querySelectorAll('.collapsible');
126 for (var i = 0; i < toAnimate.length; i++)
127 fadeInElement(toAnimate[i]);
128 el.classList.add('visible');
132 * Fades out a printing option existing under |el|.
133 * @param {HTMLElement} el The element to hide.
134 * @param {boolean=} opt_justHide Whether {@code el} should be hidden with no
137 function fadeOutOption(el, opt_justHide) {
138 if (!el.classList.contains('visible'))
141 wrapContentsInDiv(el.querySelector('h1'), ['visible']);
142 var rightColumn = el.querySelector('.right-column');
143 wrapContentsInDiv(rightColumn, ['visible']);
145 var toAnimate = el.querySelectorAll('.collapsible');
146 for (var i = 0; i < toAnimate.length; i++) {
148 toAnimate[i].hidden = true;
149 toAnimate[i].classList.add('closing');
150 toAnimate[i].classList.remove('visible');
152 fadeOutElement(toAnimate[i]);
155 el.classList.remove('visible');
159 * Wraps the contents of |el| in a div element and attaches css classes
160 * |classes| in the new div, only if has not been already done. It is necessary
161 * for animating the height of table cells.
162 * @param {HTMLElement} el The element to be processed.
163 * @param {array} classes The css classes to add.
165 function wrapContentsInDiv(el, classes) {
166 var div = el.querySelector('div');
167 if (!div || !div.classList.contains('collapsible')) {
168 div = document.createElement('div');
169 while (el.childNodes.length > 0)
170 div.appendChild(el.firstChild);
175 div.classList.add('collapsible');
176 for (var i = 0; i < classes.length; i++)
177 div.classList.add(classes[i]);