[IMP] Wait for DOM element if necessary
[odoo/odoo.git] / addons / website / static / src / js / website.tour.js
1 (function () {
2     'use strict';
3
4     var website = openerp.website;
5     website.templates.push('/website/static/src/xml/website.tour.xml');
6
7     function render (template, dict)  {
8         return openerp.qweb.render(template, dict);
9     }
10
11     website.EditorTour = openerp.Class.extend({
12         tour: undefined,
13         steps: [],
14         tourStorage: window.localStorage,
15         init: function () {
16             this.tour = new Tour({
17                 name: this.id,
18                 storage: this.tourStorage,
19                 keyboard: false,
20             });
21             this.tour.addSteps(_.map(this.steps, function (step) {
22                step.title = render('website.tour_popover_title', { title: step.title });
23                return step;
24             }));
25             this.monkeyPatchTour();
26         },
27         monkeyPatchTour: function () {
28             var self = this;
29             // showStep should wait for 'element' to appear instead of moving to the next step
30             self.tour.showStep = function (i) {
31               var step = self.tour.getStep(i);
32               return (function proceed () {
33                   if (step.orphan || $(step.element).length > 0) {
34                       return Tour.prototype.showStep.call(self.tour, i);
35                   } else {
36                       setTimeout(proceed, 50);
37                   }
38               }());
39             };
40         },
41         reset: function () {
42             this.tourStorage.removeItem(this.id+'_current_step');
43             this.tourStorage.removeItem(this.id+'_end');
44             this.tour._current = 0;
45             $('.popover.tour').remove();
46         },
47         start: function () {
48             if (this.canResume()) {
49                 this.tour.start();
50             }
51         },
52         canResume: function () {
53             return (this.currentStepIndex() === 0) && !this.tour.ended();
54         },
55         currentStepIndex: function () {
56             var index = this.tourStorage.getItem(this.id+'_current_step') || 0;
57             return parseInt(index, 10);
58         },
59         indexOfStep: function (stepId) {
60             var index = -1;
61             _.each(this.steps, function (step, i) {
62                if (step.stepId === stepId) {
63                    index = i;
64                }
65             });
66             return index;
67         },
68         movetoStep: function (stepId) {
69             $('.popover.tour').remove();
70             var index = this.indexOfStep(stepId);
71             if (index > -1) {
72                 this.tour.goto(index);
73             }
74         },
75         saveStep: function (stepId) {
76             var index = this.indexOfStep(stepId);
77             this.tourStorage.setItem(this.id+'_current_step', index);
78         },
79         stop: function () {
80             this.tour.end();
81         },
82     });
83
84     website.EditorBasicTour = website.EditorTour.extend({
85         id: 'add_banner_tour',
86         name: "How to add a banner",
87         init: function (editor) {
88             var self = this;
89             self.steps = [
90                 {
91                     stepId: 'welcome',
92                     orphan: true,
93                     backdrop: true,
94                     title: "Welcome to your website!",
95                     content: "This tutorial will guide you to build your website.<br>Let's start by the banner!",
96                     template: render('website.tour_popover', { next: "Start", end: "Close" }),
97                 },
98                 {
99                     stepId: 'edit-page',
100                     element: 'button[data-action=edit]',
101                     placement: 'bottom',
102                     reflex: true,
103                     title: "Edit this page",
104                     content: "You are in your website homepage.<br>Click here to edit it.",
105                     template: render('website.tour_popover'),
106                 },
107                 {
108                     stepId: 'add-block',
109                     element: 'button[data-action=snippet]',
110                     placement: 'bottom',
111                     title: "Shows Building Blocks",
112                     content: "Make the home page more attractive with a banner.<br>Click here to see available building blocks.",
113                     template: render('website.tour_popover'),
114                     onShow: function () {
115                         function refreshAddBlockStep () {
116                             self.tour.showStep(self.indexOfStep('add-block'));
117                             editor.off('rte:ready', editor, refreshAddBlockStep);
118                         }
119                         editor.on('rte:ready', editor, refreshAddBlockStep);
120                         $('button[data-action=snippet]').click(function () {
121                             self.movetoStep('drag-banner');
122                         });
123                     }
124                 },
125                 {
126                     stepId: 'drag-banner',
127                     element: '#website-top-navbar [data-snippet-id=carousel]',
128                     placement: 'bottom',
129                     title: "Drag & Drop a Banner",
130                     content: "Drag the <em>Banner</em> block and drop it to the top of your page.",
131                     template: render('website.tour_popover'),
132                     onShow: function () {
133                         function beginDrag () {
134                             $('.popover.tour').remove();
135                             $('body').off('mousedown', beginDrag);
136                             function goToNextStep () {
137                                 $('#oe_snippets').hide();
138                                 self.movetoStep('edit-title');
139                                 $('body').off('mouseup', goToNextStep);
140                             }
141                             $('body').on('mouseup', goToNextStep);
142                         }
143                         $('body').on('mousedown', beginDrag);
144                     },
145                 },
146                 {
147                     stepId: 'edit-title',
148                     element: '#wrap [data-snippet-id=carousel]:first .carousel-caption',
149                     placement: 'left',
150                     title: "Set your Banner text",
151                     content: "Click in the text to edit it.<br>Select the text to change the look thanks to the top menu bar.",
152                     template: render('website.tour_popover', { next: "Continue" }),
153                     onHide: function () {
154                         var $banner = $("#wrap [data-snippet-id=carousel]:first");
155                         if ($banner.length) {
156                             $banner.click();
157                         }
158                     },
159                 },
160                 {
161                     stepId: 'customize-banner',
162                     element: '.oe_overlay_options .oe_options',
163                     placement: 'left',
164                     title: "Customize your new Banner style",
165                     content: "Click on <em>Customize</em> and change the background of your banner.<br>If your are satisfied with the current background, just click <em>Continue</em>.",
166                     template: render('website.tour_popover', { next: "Continue" }),
167                     onShow: function () {
168                         $('.dropdown-menu [name=carousel-background]').click(function () {
169                             self.movetoStep('save-changes');
170                         });
171                     },
172                 },
173                 {
174                     stepId: 'save-changes',
175                     element: 'button[data-action=save]',
176                     placement: 'right',
177                     reflex: true,
178                     title: "Save your modifications",
179                     content: "Click here to save the content of your website.",
180                     template: render('website.tour_popover'),
181                     onHide: function () {
182                         self.saveStep('part-2');
183                     },
184
185                 },
186                 {
187                     stepId: 'part-2',
188                     orphan: true,
189                     backdrop: true,
190                     title: "Congratutaltions!",
191                     content: "Congratulations on your first modifications.",
192                     template: render('website.tour_popover', { next: "OK" }),
193                 },
194                 {
195                     stepId: 'show-tutorials',
196                     element: '#help-menu-button',
197                     placement: 'left',
198                     title: "Help is always available",
199                     content: "You can find more tutorials in the <em>Help</em> menu.",
200                     template: render('website.tour_popover', { end: "Close" }),
201                 },
202             ];
203             return this._super();
204         },
205         startOfPart2: function () {
206             var currentStepIndex = this.currentStepIndex();
207             var secondPartIndex = this.indexOfStep('part-2');
208             var showTutorialsIndex = this.indexOfStep('show-tutorials');
209             return (currentStepIndex === secondPartIndex || currentStepIndex === showTutorialsIndex) && !this.tour.ended();
210         },
211         canResume: function () {
212             return this.startOfPart2() || this._super();
213         },
214     });
215
216     website.UrlParser = openerp.Class.extend({
217         init: function (url) {
218             var a = document.createElement('a');
219             a.href = url;
220             this.href = a.href;
221             this.host = a.host;
222             this.protocol = a.protocol;
223             this.port = a.port;
224             this.hostname = a.hostname;
225             this.pathname = a.pathname;
226             this.origin = a.origin;
227             this.search = a.search;
228         },
229     });
230
231     website.EditorBar.include({
232         start: function () {
233             website.tutorials = {
234                 basic: new website.EditorBasicTour(this),
235             };
236             var menu = $('#help-menu');
237             _.each(website.tutorials, function (tutorial) {
238                 var $menuItem = $($.parseHTML('<li><a href="#">'+tutorial.name+'</a></li>'));
239                 $menuItem.click(function () {
240                     tutorial.reset();
241                     tutorial.start();
242                 })
243                 menu.append($menuItem);
244             });
245             var url = new website.UrlParser(window.location.href);
246             if (url.search.indexOf('?tutorial=true') === 0 || website.tutorials.basic.startOfPart2()) {
247                 website.tutorials.basic.start();
248             }
249             $('.tour-backdrop').click(function (e) {
250                 e.stopImmediatePropagation();
251                 e.preventDefault();
252             });
253             return this._super();
254         },
255     });
256
257 }());