cygprofile: increase timeouts to allow showing web contents
[chromium-blink-merge.git] / chrome / browser / resources / chromeos / first_run / step.js
blob213ea27c02e97919b48249f7274502df1b721ffd
1 // Copyright 2013 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 /**
6 * Prototype for first-run tutorial steps.
7 */
9 cr.define('cr.FirstRun', function() {
10 var Step = cr.ui.define('div');
12 Step.prototype = {
13 __proto__: HTMLDivElement.prototype,
15 // Name of step.
16 name_: null,
18 // Button leading to next tutorial step.
19 nextButton_: null,
21 // Default control for this step.
22 defaultControl_: null,
24 decorate: function() {
25 this.name_ = this.getAttribute('id');
26 var controlsContainer = this.getElementsByClassName('controls')[0];
27 if (!controlsContainer)
28 throw Error('Controls not found.');
29 this.nextButton_ =
30 controlsContainer.getElementsByClassName('next-button')[0];
31 if (!this.nextButton_)
32 throw Error('Next button not found.');
33 this.nextButton_.addEventListener('click', (function(e) {
34 chrome.send('nextButtonClicked', [this.getName()]);
35 e.stopPropagation();
36 }).bind(this));
37 this.defaultControl_ = controlsContainer.children[0];
40 /**
41 * Returns name of the string.
43 getName: function() {
44 return this.name_;
47 /**
48 * Hides the step.
49 * @param {boolean} animated Whether transition should be animated.
50 * @param {function()=} opt_onHidden Called after step has been hidden.
52 hide: function(animated, opt_onHidden) {
53 var transitionDuration =
54 animated ? cr.FirstRun.getDefaultTransitionDuration() : 0;
55 changeVisibility(this,
56 false,
57 transitionDuration,
58 function() {
59 this.classList.add('hidden');
60 if (opt_onHidden)
61 opt_onHidden();
62 }.bind(this));
65 /**
66 * Shows the step.
67 * @param {boolean} animated Whether transition should be animated.
68 * @param {function(Step)=} opt_onShown Called after step has been shown.
70 show: function(animated, opt_onShown) {
71 var transitionDuration =
72 animated ? cr.FirstRun.getDefaultTransitionDuration() : 0;
73 this.classList.remove('hidden');
74 changeVisibility(this,
75 true,
76 transitionDuration,
77 function() {
78 if (opt_onShown)
79 opt_onShown(this);
80 }.bind(this));
83 /**
84 * Sets position of the step.
85 * @param {object} position Parameter with optional fields |top|,
86 * |right|, |bottom|, |left| holding corresponding offsets.
88 setPosition: function(position) {
89 var style = this.style;
90 ['top', 'right', 'bottom', 'left'].forEach(function(property) {
91 if (position.hasOwnProperty(property))
92 style.setProperty(property, position[property] + 'px');
93 });
96 /**
97 * Makes default control focused. Default control is a first control in
98 * current implementation.
100 focusDefaultControl: function() {
101 this.defaultControl_.focus();
105 var Bubble = cr.ui.define('div');
107 // List of rules declaring bubble's arrow position depending on text direction
108 // and shelf alignment. Every rule has required field |position| with list
109 // of classes that should be applied to arrow element if this rule choosen.
110 // The rule is suitable if its |shelf| and |dir| fields are correspond
111 // to current shelf alignment and text direction. Missing fields behaves like
112 // '*' wildcard. The last suitable rule in list is choosen for arrow style.
113 var ARROW_POSITION = {
114 'app-list': [
116 position: ['points-down', 'left']
119 dir: 'rtl',
120 position: ['points-down', 'right']
123 shelf: 'left',
124 position: ['points-left', 'top']
127 shelf: 'right',
128 position: ['points-right', 'top']
131 'tray': [
133 position: ['points-right', 'top']
136 dir: 'rtl',
137 shelf: 'bottom',
138 position: ['points-left', 'top']
141 shelf: 'left',
142 position: ['points-left', 'top']
145 'help': [
147 position: ['points-right', 'bottom']
150 dir: 'rtl',
151 shelf: 'bottom',
152 position: ['points-left', 'bottom']
155 shelf: 'left',
156 position: ['points-left', 'bottom']
161 var DISTANCE_TO_POINTEE = 10;
162 var MINIMAL_SCREEN_OFFSET = 10;
163 var ARROW_LENGTH = 6; // Keep synced with .arrow border-width.
165 Bubble.prototype = {
166 __proto__: Step.prototype,
168 // Element displaying arrow.
169 arrow_: null,
171 // Unit vector directed along the bubble arrow.
172 direction_: null,
175 * In addition to base class 'decorate' this method creates arrow and
176 * sets some properties related to arrow.
178 decorate: function() {
179 Step.prototype.decorate.call(this);
180 this.arrow_ = document.createElement('div');
181 this.arrow_.classList.add('arrow');
182 this.appendChild(this.arrow_);
183 var inputDirection = document.documentElement.getAttribute('dir');
184 var shelfAlignment = document.documentElement.getAttribute('shelf');
185 var isSuitable = function(rule) {
186 var inputDirectionMatch = !rule.hasOwnProperty('dir') ||
187 rule.dir === inputDirection;
188 var shelfAlignmentMatch = !rule.hasOwnProperty('shelf') ||
189 rule.shelf === shelfAlignment;
190 return inputDirectionMatch && shelfAlignmentMatch;
192 var lastSuitableRule = null;
193 var rules = ARROW_POSITION[this.getName()];
194 rules.forEach(function(rule) {
195 if (isSuitable(rule))
196 lastSuitableRule = rule;
198 assert(lastSuitableRule);
199 lastSuitableRule.position.forEach(function(cls) {
200 this.arrow_.classList.add(cls);
201 }.bind(this));
202 var list = this.arrow_.classList;
203 if (list.contains('points-up'))
204 this.direction_ = [0, -1];
205 else if (list.contains('points-right'))
206 this.direction_ = [1, 0];
207 else if (list.contains('points-down'))
208 this.direction_ = [0, 1];
209 else // list.contains('points-left')
210 this.direction_ = [-1, 0];
214 * Sets position of bubble in such a maner that bubble's arrow points to
215 * given point.
216 * @param {Array} point Bubble arrow should point to this point after
217 * positioning. |point| has format [x, y].
218 * @param {offset} number Additional offset from |point|.
220 setPointsTo: function(point, offset) {
221 var shouldShowBefore = this.hidden;
222 // "Showing" bubble in order to make offset* methods work.
223 if (shouldShowBefore) {
224 this.style.setProperty('opacity', '0');
225 this.show(false);
227 var arrow = [this.arrow_.offsetLeft + this.arrow_.offsetWidth / 2,
228 this.arrow_.offsetTop + this.arrow_.offsetHeight / 2];
229 var totalOffset = DISTANCE_TO_POINTEE + offset;
230 var left = point[0] - totalOffset * this.direction_[0] - arrow[0];
231 var top = point[1] - totalOffset * this.direction_[1] - arrow[1];
232 // Force bubble to be inside screen.
233 if (this.arrow_.classList.contains('points-up') ||
234 this.arrow_.classList.contains('points-down')) {
235 left = Math.max(left, MINIMAL_SCREEN_OFFSET);
236 left = Math.min(left, document.body.offsetWidth - this.offsetWidth -
237 MINIMAL_SCREEN_OFFSET);
239 if (this.arrow_.classList.contains('points-left') ||
240 this.arrow_.classList.contains('points-right')) {
241 top = Math.max(top, MINIMAL_SCREEN_OFFSET);
242 top = Math.min(top, document.body.offsetHeight - this.offsetHeight -
243 MINIMAL_SCREEN_OFFSET);
245 this.style.setProperty('left', left + 'px');
246 this.style.setProperty('top', top + 'px');
247 if (shouldShowBefore) {
248 this.hide(false);
249 this.style.removeProperty('opacity');
254 * Sets position of bubble. Overrides Step.setPosition to adjust offsets
255 * in case if its direction is the same as arrow's direction.
256 * @param {object} position Parameter with optional fields |top|,
257 * |right|, |bottom|, |left| holding corresponding offsets.
259 setPosition: function(position) {
260 var arrow = this.arrow_;
261 // Increasing offset if it's from side where bubble points to.
262 [['top', 'points-up'],
263 ['right', 'points-right'],
264 ['bottom', 'points-down'],
265 ['left', 'points-left']].forEach(function(mapping) {
266 if (position.hasOwnProperty(mapping[0]) &&
267 arrow.classList.contains(mapping[1])) {
268 position[mapping[0]] += ARROW_LENGTH + DISTANCE_TO_POINTEE;
271 Step.prototype.setPosition.call(this, position);
275 var HelpStep = cr.ui.define('div');
277 HelpStep.prototype = {
278 __proto__: Bubble.prototype,
280 decorate: function() {
281 Bubble.prototype.decorate.call(this);
282 var helpButton = this.getElementsByClassName('help-button')[0];
283 helpButton.addEventListener('click', function(e) {
284 chrome.send('helpButtonClicked');
285 e.stopPropagation();
290 var DecorateStep = function(el) {
291 if (el.id == 'help')
292 HelpStep.decorate(el);
293 else if (el.classList.contains('bubble'))
294 Bubble.decorate(el);
295 else
296 Step.decorate(el);
299 return {DecorateStep: DecorateStep};