1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Use of this source code is governed by a BSD-style license that can be
3ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// found in the LICENSE file.
4ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// This file contains functions that control several animations in the print
6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// preview tab (scrollbars, showing hiding options, resizing).
7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Scrollbar will never get smaller than this
9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst TRANSIENT_MIN_SCROLLBAR_SIZE = 40;
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen//  Timeout duration in milliseconds used for showing the scrollbars.
11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenconst HIDE_SCROLLBARS_TIMEOUT = 250;
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Timeout id used to reset the timer when needed.
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvar transientHideScrollbarsTimeoutId = [];
14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen//  Holds all elements that have scrollbars attached to them.
15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvar transientScrollbarEls = [];
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Counter used to give webkit animations unique names.
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvar animationCounter = 0;
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen/**
20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Makes the scrollbars visible. If |el| has already a scrollbar timer, it
21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * resets its value.
22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *
23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {HTMLDivElement} el The element associated with the scrollbars
24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */
25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenfunction showTransientScrollbars(el) {
26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  el.scrollHorEl.classList.remove('invisible');
27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  el.scrollVertEl.classList.remove('invisible');
28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (el.transientHideScrollbarsTimeoutId)
30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    window.clearTimeout(el.transientHideScrollbarsTimeoutId);
31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  el.transientHideScrollbarsTimeoutId =
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      window.setTimeout(function() { hideTransientScrollbars(el) },
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                        HIDE_SCROLLBARS_TIMEOUT);
35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen/**
38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Hides the scrollbars.
39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *
40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {HTMLElement} el The element associated with the scrollbars
41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen*/
42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenfunction hideTransientScrollbars(el) {
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  el.scrollHorEl.classList.add('invisible');
44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  el.scrollVertEl.classList.add('invisible');
45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen/**
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Handles a mouse move event, takes care of updating the scrollbars.
49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *
50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {event} event The event that triggered this handler
51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen*/
52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenfunction handleTransientMouseMove(event) {
53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var el = event.target;
54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  while (!el.classList.contains('scrollbar-inside') && el != document.body)
56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    el = el.parentNode;
57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  showTransientScrollbars(el);
59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen/**
62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Updates the scrollbars associated with the the input element.
63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *
64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {HTMLElement} el
65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */
66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenfunction updateTransientScrollbars(el) {
67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var scrollLeft = el.scrollLeft;
68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var scrollTop = el.scrollTop;
69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var scrollWidth = el.scrollWidth;
71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var scrollHeight = el.scrollHeight;
72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var offsetWidth = el.offsetWidth - el.scrollbarWidth;
74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var offsetHeight = el.offsetHeight - el.scrollbarHeight;
75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var elevatorWidth = offsetWidth / scrollWidth * offsetWidth;
77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var elevatorHeight = offsetHeight / scrollHeight * offsetHeight;
78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Make sure the scrollbars are big enough.
80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (elevatorWidth < TRANSIENT_MIN_SCROLLBAR_SIZE)
81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    elevatorWidth = TRANSIENT_MIN_SCROLLBAR_SIZE;
82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (elevatorHeight < TRANSIENT_MIN_SCROLLBAR_SIZE)
83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    elevatorHeight = TRANSIENT_MIN_SCROLLBAR_SIZE;
84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (offsetWidth >= scrollWidth) {
86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!el.scrollHorEl.classList.contains('hidden'))
87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      el.scrollHorEl.classList.add('hidden');
88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (el.scrollHorEl.classList.contains('hidden'))
90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      el.scrollHorEl.classList.remove('hidden');
91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    var x = scrollLeft / (scrollWidth - offsetWidth);
92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // TODO(mwichary): 6 shouldn’t be hardcoded
94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    el.scrollHorEl.style.left = (x * (offsetWidth - elevatorWidth - 6)) + 'px';
95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    el.scrollHorEl.style.width = elevatorWidth + 'px';
96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (offsetHeight >= scrollHeight) {
99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!el.scrollVertEl.classList.contains('hidden'))
100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      el.scrollVertEl.classList.add('hidden');
101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (el.scrollVertEl.classList.contains('hidden'))
103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      el.scrollVertEl.classList.remove('hidden');
104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    var y = scrollTop / (scrollHeight - offsetHeight);
106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // TODO(mwichary): 6 shouldn’t be hardcoded
108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    el.scrollVertEl.style.top =
109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        (y * (offsetHeight - elevatorHeight - 6)) + 'px';
110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    el.scrollVertEl.style.height = elevatorHeight + 'px';
111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen/**
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Updates all exising scrollbars.
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */
117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenfunction updateAllTransientScrollbars() {
118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  for (var i = 0; i < transientScrollbarEls.length; i++) {
119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    var el = transientScrollbarEls[i];
120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    updateTransientScrollbars(el);
121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen/**
125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Handles a scroll event.
126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */
127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenfunction handleTransientScroll(event) {
128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var el = event.target;
129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (el == document)
131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    el = document.body;
132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  updateTransientScrollbars(el);
134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Make sure to show the scrollbars if they are hidden.
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  showTransientScrollbars(el);
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen/**
140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Adds scrollbars to the input element.
141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {HTMLElement} scrollableEl The scrollable element
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */
144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenfunction addTransientScrollbars(scrollableEl) {
145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var insideEl = scrollableEl.querySelector('.scrollbar-inside');
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!insideEl)
148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    insideEl = scrollableEl;
149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Determine the width/height of native scrollbar elements.
151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  insideEl.scrollbarWidth = insideEl.offsetWidth - insideEl.clientWidth;
152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  insideEl.scrollbarHeight = insideEl.offsetHeight - insideEl.clientHeight;
153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Create scrollbar elements
155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  insideEl.scrollHorEl = document.createElement('div');
156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  insideEl.scrollHorEl.className = 'scrollbar hor';
157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scrollableEl.appendChild(insideEl.scrollHorEl);
158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  insideEl.scrollVertEl = document.createElement('div');
160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  insideEl.scrollVertEl.className = 'scrollbar vert';
161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  scrollableEl.appendChild(insideEl.scrollVertEl);
162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Need to make sure the scrollbars are absolutely positioned vis-a-vis
164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // their parent element. If not, make its position relative.
165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (insideEl.scrollVertEl.offsetParent != scrollableEl)
166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    scrollableEl.style.position = 'relative';
167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (insideEl == document.body)
169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    window.addEventListener('scroll', handleTransientScroll, false);
170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  else
171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    insideEl.addEventListener('scroll', handleTransientScroll, false);
172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  insideEl.addEventListener('mousemove', handleTransientMouseMove, false);
173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  updateTransientScrollbars(insideEl);
175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  showTransientScrollbars(insideEl);
176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  transientScrollbarEls.push(insideEl);
178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen/**
181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Creates webkit animation as specified by |code.
182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *
183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {string} code The code specifying the animation.
184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */
185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenfunction addAnimation(code) {
186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var name = 'anim' + animationCounter;
187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  animationCounter++;
188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var rules = document.createTextNode(
190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      '@-webkit-keyframes ' + name + ' {' + code + '}');
191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var el = document.createElement('style');
193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  el.type = 'text/css';
194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  el.appendChild(rules);
195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  document.body.appendChild(el);
196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return name;
198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen/**
201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Shows/hides elements of class "hidden-section" depending on their
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * current state.
203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *
204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * @param {HTLMElement} el The element to be shown/hidden
205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */
206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenfunction handleZippyClickEl(el) {
207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  while (el.tagName != 'LI' && !el.classList.contains('hidden-section'))
208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    el = el.parentNode;
209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  var extraEl = el.querySelector('.extra');
211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!el.classList.contains('opened')) {
213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    extraEl.style.height = 'auto';
214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    var height = extraEl.offsetHeight;
215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    extraEl.style.height = height + 'px';
217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    el.classList.add('opened');
219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    var animName = addAnimation(
221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      '0% { opacity: 0; height: 0; padding-top: 0; } ' +
222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      '80% { height: ' + (height + 2) + 'px; padding-top: 12px; }' +
223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      '100% { opacity: 1; height: ' + height + 'px; padding-top: 10px; }');
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    extraEl.style.webkitAnimationName = animName;
226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    extraEl.style.webkitAnimationName = '';
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    extraEl.style.height = 'auto';
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    el.classList.remove('opened');
231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    el.classList.add('closing');
232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    // DEBUG
234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    window.setTimeout(
235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      function() { handleZippyClickCleanup(el, extraEl); }, 120);
236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  window.setTimeout(updateAllTransientScrollbars, 100);
239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen/**
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Cleans up the show/hide animation of function handleZippyClickEl().
243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenfunction handleZippyClickCleanup(el, extraEl) {
245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  extraEl.style.height = '';
246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  el.classList.remove('closing');
247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen/**
250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Handler for the load event.
251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */
252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenfunction handleBodyLoad() {
253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  document.body.classList.add('loaded');
254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen/**
257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen * Initializes the scrollbars animation.
258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen */
259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenfunction initializeAnimation() {
260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (document.querySelector('body > .sidebar'))
261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    addTransientScrollbars(document.querySelector('body > .sidebar'));
262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  else
263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    addTransientScrollbars(document.body);
264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  window.addEventListener('resize', updateAllTransientScrollbars, false);
266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  window.addEventListener('load', handleBodyLoad, false);
267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
268