Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / resources / print_preview / print_preview_animations.js
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.
4
5 // Counter used to give webkit animations unique names.
6 var animationCounter = 0;
7
8 var animationEventTracker_ = new EventTracker();
9
10 function addAnimation(code) {
11   var name = 'anim' + animationCounter;
12   animationCounter++;
13   var rules = document.createTextNode(
14       '@-webkit-keyframes ' + name + ' {' + code + '}');
15   var el = document.createElement('style');
16   el.type = 'text/css';
17   el.appendChild(rules);
18   el.setAttribute('id', name);
19   document.body.appendChild(el);
20
21   return name;
22 }
23
24 /**
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
27  *     ends.
28  * @return {string} The css code for the fade in animation.
29  */
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; }';
34 }
35
36 /**
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.
40  * @param {boolean=} opt_justShow Whether {@code el} should be shown with no
41  *     animation.
42  */
43 function fadeInElement(el, opt_justShow) {
44   if (el.classList.contains('visible'))
45     return;
46   el.classList.remove('closing');
47   el.hidden = false;
48   el.setAttribute('aria-hidden', 'false');
49   el.style.height = 'auto';
50   var height = el.offsetHeight;
51   if (opt_justShow) {
52     el.style.height = '';
53     el.style.opacity = '';
54   } else {
55     el.style.height = height + 'px';
56     var animName = addAnimation(getFadeInAnimationCode(height));
57     animationEventTracker_.add(
58         el, 'webkitAnimationEnd', onFadeInAnimationEnd.bind(el), false);
59     el.style.webkitAnimationName = animName;
60   }
61   el.classList.add('visible');
62 }
63
64 /**
65  * Fades out an element. Used for both printing options and error messages
66  * appearing underneath the textfields.
67  * @param {HTMLElement} el The element to be faded out.
68  */
69 function fadeOutElement(el) {
70   if (!el.classList.contains('visible'))
71     return;
72   fadeInAnimationCleanup(el);
73   el.style.height = 'auto';
74   var height = el.offsetHeight;
75   el.style.height = height + 'px';
76   el.offsetHeight;  // Should force an update of the computed style.
77   animationEventTracker_.add(
78       el, 'webkitTransitionEnd', onFadeOutTransitionEnd.bind(el), false);
79   el.classList.add('closing');
80   el.classList.remove('visible');
81   el.setAttribute('aria-hidden', 'true');
82 }
83
84 /**
85  * Executes when a fade out animation ends.
86  * @param {WebkitTransitionEvent} event The event that triggered this listener.
87  * @this {HTMLElement} The element where the transition occurred.
88  */
89 function onFadeOutTransitionEnd(event) {
90   if (event.propertyName != 'height')
91     return;
92   animationEventTracker_.remove(this, 'webkitTransitionEnd');
93   this.hidden = true;
94 }
95
96 /**
97  * Executes when a fade in animation ends.
98  * @param {WebkitAnimationEvent} event The event that triggered this listener.
99  * @this {HTMLElement} The element where the transition occurred.
100  */
101 function onFadeInAnimationEnd(event) {
102   this.style.height = '';
103   fadeInAnimationCleanup(this);
104 }
105
106 /**
107  * Removes the <style> element corresponding to |animationName| from the DOM.
108  * @param {HTMLElement} element The animated element.
109  */
110 function fadeInAnimationCleanup(element) {
111   if (element.style.webkitAnimationName) {
112     var animEl = document.getElementById(element.style.webkitAnimationName);
113     if (animEl)
114       animEl.parentNode.removeChild(animEl);
115     element.style.webkitAnimationName = '';
116     animationEventTracker_.remove(element, 'webkitAnimationEnd');
117   }
118 }
119
120 /**
121  * Fades in a printing option existing under |el|.
122  * @param {HTMLElement} el The element to hide.
123  * @param {boolean=} opt_justShow Whether {@code el} should be hidden with no
124  *     animation.
125  */
126 function fadeInOption(el, opt_justShow) {
127   if (el.classList.contains('visible'))
128     return;
129   // To make the option visible during the first fade in.
130   el.hidden = false;
131
132   var leftColumn = el.querySelector('.left-column');
133   wrapContentsInDiv(leftColumn, ['invisible']);
134   var rightColumn = el.querySelector('.right-column');
135   wrapContentsInDiv(rightColumn, ['invisible']);
136
137   var toAnimate = el.querySelectorAll('.collapsible');
138   for (var i = 0; i < toAnimate.length; i++)
139     fadeInElement(toAnimate[i], opt_justShow);
140   el.classList.add('visible');
141 }
142
143 /**
144  * Fades out a printing option existing under |el|.
145  * @param {HTMLElement} el The element to hide.
146  * @param {boolean=} opt_justHide Whether {@code el} should be hidden with no
147  *     animation.
148  */
149 function fadeOutOption(el, opt_justHide) {
150   if (!el.classList.contains('visible'))
151     return;
152
153   var leftColumn = el.querySelector('.left-column');
154   wrapContentsInDiv(leftColumn, ['visible']);
155   var rightColumn = el.querySelector('.right-column');
156   wrapContentsInDiv(rightColumn, ['visible']);
157
158   var toAnimate = el.querySelectorAll('.collapsible');
159   for (var i = 0; i < toAnimate.length; i++) {
160     if (opt_justHide) {
161       toAnimate[i].hidden = true;
162       toAnimate[i].classList.add('closing');
163       toAnimate[i].classList.remove('visible');
164     } else {
165       fadeOutElement(toAnimate[i]);
166     }
167   }
168   el.classList.remove('visible');
169 }
170
171 /**
172  * 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
174  * for animating the height of table cells.
175  * @param {HTMLElement} el The element to be processed.
176  * @param {array} classes The css classes to add.
177  */
178 function wrapContentsInDiv(el, classes) {
179   var div = el.querySelector('div');
180   if (!div || !div.classList.contains('collapsible')) {
181     div = document.createElement('div');
182     while (el.childNodes.length > 0)
183       div.appendChild(el.firstChild);
184     el.appendChild(div);
185   }
186
187   div.className = '';
188   div.classList.add('collapsible');
189   for (var i = 0; i < classes.length; i++)
190     div.classList.add(classes[i]);
191 }