cros: Remove default pinned apps trial.
[chromium-blink-merge.git] / chrome / browser / resources / chromeos / first_run / first_run.js
blob81fd973d6217bed9af2a736152ec7760287514f6
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  * @fileoverview First run UI.
7  */
9 <include src="step.js">
11 // Transitions durations.
12 /** @const  */ var DEFAULT_TRANSITION_DURATION_MS = 400;
13 /** @const  */ var BG_TRANSITION_DURATION_MS = 800;
15 /**
16  * Changes visibility of element with animated transition.
17  * @param {Element} element Element which visibility should be changed.
18  * @param {boolean} visible Whether element should be visible after transition.
19  * @param {number=} opt_transitionDuration Time length of transition in
20  *     milliseconds. Default value is DEFAULT_TRANSITION_DURATION_MS.
21  * @param {function()=} opt_onFinished Called after transition has finished.
22  */
23 function changeVisibility(
24     element, visible, opt_transitionDuration, opt_onFinished) {
25   var classes = element.classList;
26   // If target visibility is the same as current element visibility.
27   if (classes.contains('transparent') === !visible) {
28     if (opt_onFinished)
29       opt_onFinished();
30     return;
31   }
32   var transitionDuration = (opt_transitionDuration === undefined) ?
33     cr.FirstRun.getDefaultTransitionDuration() : opt_transitionDuration;
34   var style = element.style;
35   var oldDurationValue = style.getPropertyValue('transition-duration');
36   style.setProperty('transition-duration', transitionDuration + 'ms');
37   var transition = visible ? 'show-animated' : 'hide-animated';
38   classes.add(transition);
39   classes.toggle('transparent');
40   element.addEventListener('webkitTransitionEnd', function f() {
41     element.removeEventListener('webkitTransitionEnd', f);
42     classes.remove(transition);
43     if (oldDurationValue)
44       style.setProperty('transition-duration', oldDurationValue);
45     else
46       style.removeProperty('transition-duration');
47     if (opt_onFinished)
48       opt_onFinished();
49   });
50   ensureTransitionEndEvent(element, transitionDuration);
53 cr.define('cr.FirstRun', function() {
54   return {
55     // Whether animated transitions are enabled.
56     transitionsEnabled_: false,
58     // SVG element representing UI background.
59     background_: null,
61     // Container for background.
62     backgroundContainer_: null,
64     // Mask element describing transparent "holes" in background.
65     mask_: null,
67     // Pattern used for creating rectangular holes.
68     rectangularHolePattern_: null,
70     // Pattern used for creating round holes.
71     roundHolePattern_: null,
73     // Dictionary keeping all available tutorial steps by their names.
74     steps_: {},
76     // Element representing step currently shown for user.
77     currentStep_: null,
79     /**
80      * Initializes internal structures and preparing steps.
81      */
82     initialize: function() {
83       disableTextSelectAndDrag();
84       this.transitionsEnabled_ = loadTimeData.getBoolean('transitionsEnabled');
85       this.background_ = $('background');
86       this.backgroundContainer_ = $('background-container');
87       this.mask_ = $('mask');
88       this.rectangularHolePattern_ = $('rectangular-hole-pattern');
89       this.rectangularHolePattern_.removeAttribute('id');
90       this.roundHolePattern_ = $('round-hole-pattern');
91       this.roundHolePattern_.removeAttribute('id');
92       var stepElements = document.getElementsByClassName('step');
93       for (var i = 0; i < stepElements.length; ++i) {
94         var step = stepElements[i];
95         cr.FirstRun.DecorateStep(step);
96         this.steps_[step.getName()] = step;
97       }
98       this.setBackgroundVisible(true, function() {
99         chrome.send('initialized');
100       });
101     },
103     /**
104      * Hides all elements and background.
105      */
106     finalize: function() {
107       // At first we hide holes (job 1) and current step (job 2) simultaneously,
108       // then background.
109       var jobsLeft = 2;
110       var onJobDone = function() {
111         --jobsLeft;
112         if (jobsLeft)
113           return;
114         this.setBackgroundVisible(false, function() {
115           chrome.send('finalized');
116         });
117       }.bind(this);
118       this.doHideCurrentStep_(function(name) {
119         if (name)
120           chrome.send('stepHidden', [name]);
121         onJobDone();
122       });
123       this.removeHoles(onJobDone);
124     },
126     /**
127      * Adds transparent rectangular hole to background.
128      * @param {number} x X coordinate of top-left corner of hole.
129      * @param {number} y Y coordinate of top-left corner of hole.
130      * @param {number} widht Width of hole.
131      * @param {number} height Height of hole.
132      */
133     addRectangularHole: function(x, y, width, height) {
134       var hole = this.rectangularHolePattern_.cloneNode();
135       hole.setAttribute('x', x);
136       hole.setAttribute('y', y);
137       hole.setAttribute('width', width);
138       hole.setAttribute('height', height);
139       this.mask_.appendChild(hole);
140       setTimeout(function() {
141         changeVisibility(hole, true);
142       }, 0);
143     },
145     /**
146      * Adds transparent round hole to background.
147      * @param {number} x X coordinate of circle center.
148      * @param {number} y Y coordinate of circle center.
149      * @param {number} radius Radius of circle.
150      */
151     addRoundHole: function(x, y, radius) {
152       var hole = this.roundHolePattern_.cloneNode();
153       hole.setAttribute('cx', x);
154       hole.setAttribute('cy', y);
155       hole.setAttribute('r', radius);
156       this.mask_.appendChild(hole);
157       setTimeout(function() {
158         changeVisibility(hole, true);
159       }, 0);
160     },
162     /**
163      * Removes all holes previously added by |addHole|.
164      * @param {function=} opt_onHolesRemoved Called after all holes have been
165      *     hidden.
166      */
167     removeHoles: function(opt_onHolesRemoved) {
168       var mask = this.mask_;
169       var holes = Array.prototype.slice.call(
170           mask.getElementsByClassName('hole'));
171       var holesLeft = holes.length;
172       if (!holesLeft) {
173         if (opt_onHolesRemoved)
174           opt_onHolesRemoved();
175         return;
176       }
177       holes.forEach(function(hole) {
178         changeVisibility(hole, false, this.getDefaultTransitionDuration(),
179             function() {
180               mask.removeChild(hole);
181               --holesLeft;
182               if (!holesLeft && opt_onHolesRemoved)
183                 opt_onHolesRemoved();
184             });
185       }.bind(this));
186     },
188     /**
189      * Hides currently active step and notifies chrome after step has been
190      * hidden.
191      */
192     hideCurrentStep: function() {
193       assert(this.currentStep_);
194       this.doHideCurrentStep_(function(name) {
195         chrome.send('stepHidden', [name]);
196       });
197     },
199     /**
200      * Hides currently active step.
201      * @param {function(string)=} opt_onStepHidden Called after step has been
202      *     hidden.
203      */
204     doHideCurrentStep_: function(opt_onStepHidden) {
205       if (!this.currentStep_) {
206         if (opt_onStepHidden)
207           opt_onStepHidden();
208         return;
209       }
210       var name = this.currentStep_.getName();
211       this.currentStep_.hide(true, function() {
212         this.currentStep_ = null;
213         if (opt_onStepHidden)
214           opt_onStepHidden(name);
215       }.bind(this));
216     },
218     /**
219      * Shows step with given name in given position.
220      * @param {string} name Name of step.
221      * @param {object} position Optional parameter with optional fields |top|,
222      *     |right|, |bottom|, |left| used for step positioning.
223      * @param {Array} pointWithOffset Optional parameter for positioning
224      *     bubble. Contains [x, y, offset], where (x, y) - point to which bubble
225      *     points, offset - distance between arrow and point.
226      */
227     showStep: function(name, position, pointWithOffset) {
228       assert(!this.currentStep_);
229       if (!this.steps_.hasOwnProperty(name))
230         throw Error('Step "' + name + '" not found.');
231       var step = this.steps_[name];
232       if (position)
233         step.setPosition(position);
234       if (pointWithOffset)
235         step.setPointsTo(pointWithOffset.slice(0, 2), pointWithOffset[2]);
236       step.show(true);
237       this.currentStep_ = step;
238     },
240     /**
241      * Sets visibility of the background.
242      * @param {boolean} visibility Whether background should be visible.
243      * @param {function()=} opt_onCompletion Called after visibility has
244      *     changed.
245      */
246     setBackgroundVisible: function(visible, opt_onCompletion) {
247       changeVisibility(this.backgroundContainer_, visible,
248           this.getBackgroundTransitionDuration(), opt_onCompletion);
249     },
251     /**
252      * Returns default duration of animated transitions, in ms.
253      */
254     getDefaultTransitionDuration: function() {
255       return this.transitionsEnabled_ ? DEFAULT_TRANSITION_DURATION_MS : 0;
256     },
258     /**
259      * Returns duration of transitions of background shield, in ms.
260      */
261     getBackgroundTransitionDuration: function() {
262       return this.transitionsEnabled_ ? BG_TRANSITION_DURATION_MS : 0;
263     }
264   };
268  * Initializes UI.
269  */
270 window.onload = function() {
271   cr.FirstRun.initialize();