From 60bdd78706336fa0221264f1675a8645bc2a99e9 Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Thu, 20 Mar 2014 09:30:55 +0100
Subject: [PATCH 01/26] [IMP] website tour: refactoring and change api for
create tour and test
bzr revid: chm@openerp.com-20140320083055-z5ys4oey5brd439v
---
.../static/src/js/website.tour.banner.js | 207 +++---
addons/website/static/src/js/website.tour.js | 689 +++++++-----------
.../static/src/js/website.tour.blog.js | 210 +++---
.../static/src/js/website.tour.event.js | 206 +++---
.../static/src/js/website.tour.event_sale.js | 129 ++--
.../static/src/js/website.tour.sale.js | 159 ++--
.../static/src/js/website.tour.shop.js | 254 +++----
7 files changed, 836 insertions(+), 1018 deletions(-)
diff --git a/addons/website/static/src/js/website.tour.banner.js b/addons/website/static/src/js/website.tour.banner.js
index 9c8afcd61e5..65099d03986 100644
--- a/addons/website/static/src/js/website.tour.banner.js
+++ b/addons/website/static/src/js/website.tour.banner.js
@@ -4,117 +4,106 @@
var website = openerp.website;
var _t = openerp._t;
- website.EditorBar.include({
- start: function () {
- this.registerTour(new website.Tour.Banner(this));
- return this._super();
- },
- });
-
- website.Tour.Banner = website.Tour.extend({
+ website.Tour.register({
id: 'banner',
- name: "Build a page",
+ name: _t("Build a page"),
path: '/page/website.homepage',
- init: function () {
- var self = this;
- self.steps = [
- {
- title: _t("Welcome to your website!"),
- content: _t("This tutorial will guide you to build your home page. We will start by adding a banner."),
- popover: { next: _t("Start Tutorial"), end: _t("Skip It") },
- },
- {
- waitNot: '.popover.tour',
- element: 'button[data-action=edit]',
- placement: 'bottom',
- title: _t("Edit this page"),
- content: _t("Every page of your website can be modified through the Edit button."),
- popover: { fixed: true },
- },
- {
- element: 'button[data-action=snippet]',
- placement: 'bottom',
- title: _t("Insert building blocks"),
- content: _t("Click here to insert blocks of centent in the page."),
- popover: { fixed: true },
- },
- {
- snippet: '#snippet_structure .oe_snippet:first',
- placement: 'bottom',
- title: _t("Drag & Drop a Banner"),
- content: _t("Drag the Banner block and drop it in your page."),
- popover: { fixed: true },
- },
- {
- waitFor: '.oe_overlay_options .oe_options:visible',
- element: '#wrap .carousel:first .carousel-caption > div',
- placement: 'top',
- title: _t("Customize banner's text"),
- content: _t("Click in the text and start editing it."),
- popover: { next: _t("Continue") },
- },
- {
- element: '.oe_overlay_options .oe_options:visible',
- placement: 'left',
- title: _t("Customize the banner"),
- content: _t("Customize any block through this menu. Try to change the background of the banner."),
- popover: { next: _t("Continue") },
- },
- {
- waitNot: '.popover.tour',
- element: 'button[data-action=snippet]',
- placement: 'bottom',
- title: _t("Add Another Block"),
- content: _t("Let's add another building block to your page."),
- popover: { fixed: true },
- },
- {
- snippet: '#snippet_structure .oe_snippet:eq(6)',
- placement: 'bottom',
- title: _t("Drag & Drop This Block"),
- content: _t("Drag the 'Features' block and drop it below the banner."),
- popover: { fixed: true },
- },
- {
- waitFor: '.oe_overlay_options .oe_options:visible',
- element: 'button[data-action=save]',
- placement: 'right',
- title: _t("Save your modifications"),
- content: _t("Publish your page by clicking on the 'Save' button."),
- popover: { fixed: true },
- },
- {
- waitFor: 'button[data-action=edit]:visible',
- title: _t("Good Job!"),
- content: _t("Well done, you created your homepage."),
- popover: { next: _t("Continue") },
- },
- {
- waitNot: '.popover.tour',
- element: 'a[data-action=show-mobile-preview]',
- placement: 'bottom',
- title: _t("Test Your Mobile Version"),
- content: _t("Let's check how your homepage looks like on mobile devices."),
- popover: { fixed: true },
- },
- {
- element: '.modal:has(#mobile-viewport) button[data-dismiss=modal]',
- placement: 'right',
- title: _t("Check Mobile Preview"),
- content: _t("Scroll to check rendering and then close the mobile preview."),
- popover: { next: _t("Continue") },
- },
- {
- waitNot: '.modal',
- element: '#content-menu-button',
- placement: 'left',
- title: _t("Add new pages and menus"),
- content: _t("The 'Content' menu allows you to add pages or add the top menu."),
- popover: { next: _t("Close Tutorial") },
- },
- ];
- return this._super();
- },
+ steps: [
+ {
+ title: _t("Welcome to your website!"),
+ content: _t("This tutorial will guide you to build your home page. We will start by adding a banner."),
+ popover: { next: _t("Start Tutorial"), end: _t("Skip It") },
+ },
+ {
+ waitNot: '.popover.tour',
+ element: 'button[data-action=edit]',
+ placement: 'bottom',
+ title: _t("Edit this page"),
+ content: _t("Every page of your website can be modified through the Edit button."),
+ popover: { fixed: true },
+ },
+ {
+ element: 'button[data-action=snippet]',
+ placement: 'bottom',
+ title: _t("Insert building blocks"),
+ content: _t("Click here to insert blocks of centent in the page."),
+ popover: { fixed: true },
+ },
+ {
+ snippet: '#snippet_structure .oe_snippet:first',
+ placement: 'bottom',
+ title: _t("Drag & Drop a Banner"),
+ content: _t("Drag the Banner block and drop it in your page."),
+ popover: { fixed: true },
+ },
+ {
+ waitFor: '.oe_overlay_options .oe_options:visible',
+ element: '#wrap .carousel:first .carousel-caption > div',
+ placement: 'top',
+ title: _t("Customize banner's text"),
+ content: _t("Click in the text and start editing it."),
+ popover: { next: _t("Continue") },
+ },
+ {
+ element: '.oe_overlay_options .oe_options:visible',
+ placement: 'left',
+ title: _t("Customize the banner"),
+ content: _t("Customize any block through this menu. Try to change the background of the banner."),
+ popover: { next: _t("Continue") },
+ },
+ {
+ waitNot: '.popover.tour',
+ element: 'button[data-action=snippet]',
+ placement: 'bottom',
+ title: _t("Add Another Block"),
+ content: _t("Let's add another building block to your page."),
+ popover: { fixed: true },
+ },
+ {
+ snippet: '#snippet_structure .oe_snippet:eq(6)',
+ placement: 'bottom',
+ title: _t("Drag & Drop This Block"),
+ content: _t("Drag the 'Features' block and drop it below the banner."),
+ popover: { fixed: true },
+ },
+ {
+ waitFor: '.oe_overlay_options .oe_options:visible',
+ element: 'button[data-action=save]',
+ placement: 'right',
+ title: _t("Save your modifications"),
+ content: _t("Publish your page by clicking on the 'Save' button."),
+ popover: { fixed: true },
+ },
+ {
+ waitFor: 'button[data-action=edit]:visible',
+ title: _t("Good Job!"),
+ content: _t("Well done, you created your homepage."),
+ popover: { next: _t("Continue") },
+ },
+ {
+ waitNot: '.popover.tour',
+ element: 'a[data-action=show-mobile-preview]',
+ placement: 'bottom',
+ title: _t("Test Your Mobile Version"),
+ content: _t("Let's check how your homepage looks like on mobile devices."),
+ popover: { fixed: true },
+ },
+ {
+ element: '.modal:has(#mobile-viewport) button[data-dismiss=modal]',
+ placement: 'right',
+ title: _t("Check Mobile Preview"),
+ content: _t("Scroll to check rendering and then close the mobile preview."),
+ popover: { next: _t("Continue") },
+ },
+ {
+ waitNot: '.modal',
+ element: '#content-menu-button',
+ placement: 'left',
+ title: _t("Add new pages and menus"),
+ content: _t("The 'Content' menu allows you to add pages or add the top menu."),
+ popover: { next: _t("Close Tutorial") },
+ },
+ ]
});
}());
diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js
index b7e55fe166b..c5ccd1f42c9 100644
--- a/addons/website/static/src/js/website.tour.js
+++ b/addons/website/static/src/js/website.tour.js
@@ -6,7 +6,7 @@ if (typeof openerp === "undefined") {
var error = "openerp is undefined"
+ "\nhref: " + window.location.href
+ "\nreferrer: " + document.referrer
- + "\nlocalStorage: " + JSON.stringify(window.localStorage);
+ + "\nlocalStorage: " + window.localStorage.getItem("tour");
if (typeof $ !== "undefined") {
error += '\n\n' + $("body").html();
}
@@ -36,27 +36,24 @@ function bootstrap_tour_stub () {
}
}
-
-
if (website.EditorBar) {
website.EditorBar.include({
tours: [],
start: function () {
var self = this;
var menu = $('#help-menu');
- _.each(this.tours, function (tour) {
+ _.each(website.Tour.tours, function (tour) {
+ if (tour.mode != "tutorial") {
+ return;
+ }
var $menuItem = $($.parseHTML('
'+tour.name+''));
$menuItem.click(function () {
- tour.reset();
- tour.run();
+ website.Tour.reset();
+ website.Tour.run(tour.id);
});
menu.append($menuItem);
});
return this._super();
- },
- registerTour: function (tour) {
- website.Tour.add(tour);
- this.tours.push(tour);
}
});
}
@@ -94,434 +91,312 @@ $.ajaxSetup({
}
});
-website.Tour = openerp.Class.extend({
- steps: [],
- defaultDelay: 50, //ms
- defaultOverLaps: 5000, //ms
- localStorage: window.localStorage,
- init: function () {},
- run: function (automatic) {
- this.reset();
+/////////////////////////////////////////////////
- for (var k in this.localStorage) {
- if (!k.indexOf("tour-") && k.indexOf("-test") > -1) return;
+
+var localStorage = window.localStorage;
+
+website.Tour = {};
+website.Tour.tours = {};
+website.Tour.state = null;
+website.Tour.register = function (tour) {
+ website.Tour.tours[tour.id] = tour;
+};
+website.Tour.run = function (tour_id, mode) {
+ if (localStorage.getItem("tour")) { // only one test running
+ return;
+ }
+ var tour = website.Tour.tours[tour_id];
+ website.Tour.save_state(tour.id, mode || tour.mode, 0);
+ if (tour.path) {
+ window.location.href = "/"+website.Tour.getLang()+tour.path;
+ }
+};
+website.Tour.registerSteps = function (tour) {
+ if (tour.register) {
+ return;
+ }
+ tour.register = true;
+
+ for (var index=0, len=tour.steps.length; index 0 && tour.steps[index-1] &&
+ tour.steps[index-1].popover && tour.steps[index-1].popover.next) {
+ step.waitNot = '.popover.tour:visible';
+ }
+ if (!step.waitFor && index > 0 && tour.steps[index-1].snippet) {
+ step.waitFor = '.oe_overlay_options .oe_options:visible';
}
- website.Tour.busy = true;
+ if (!step.element) step.orphan = true;
- if (automatic) {
- this.localStorage.setItem("tour-"+this.id+"-test-automatic", true);
- } else {
- this.localStorage.removeItem("tour-"+this.id+"-test-automatic");
+ var snippet = step.element.match(/#oe_snippets (.*) \.oe_snippet_thumbnail/);
+ if (snippet) {
+ step.snippet = snippet[1];
+ } else if (step.snippet) {
+ step.element = '#oe_snippets '+step.snippet+' .oe_snippet_thumbnail';
}
- this.automatic = automatic;
+ }
+ if (tour.steps[index-1] &&
+ tour.steps[index-1].popover && tour.steps[index-1].popover.next) {
+ var step = {
+ step_id: index,
+ waitNot: '.popover.tour:visible'
+ };
+ tour.steps.push(step);
+ }
- if (this.path) {
- // redirect to begin of the tour in function of the language
- if (!this.testUrl(this.path+"(#.*)?$")) {
- var path = this.path.split('#');
- window.location.href = "/"+this.getLang()+path[0] + "#tutorial."+this.id+"=true&" + path.slice(1, path.length).join("#");
- return;
- }
- }
-
- var self = this;
- this.localStorage.setItem("tour-"+this.id+"-test", 0);
- website.Tour.waitReady.call(this, function () {self._running();});
- },
- running: function () {
- var self = this;
- if (+this.localStorage.getItem("tour-"+this.id+"-test") >= this.steps.length-1) {
- this.endTour();
- return;
- }
-
- if (website.Tour.is_busy()) return;
-
- // launch tour with url
- this.checkRunningUrl();
-
- // mark tour as busy (only one test running)
- if (this.localStorage.getItem("tour-"+this.id+"-test") != null) {
- website.Tour.busy = true;
- this.automatic = !!this.localStorage.getItem("tour-"+this.id+"-test-automatic");
- }
-
- if (!this.testPathUrl()) {
- if (this.automatic) {
- this.timer = setTimeout(function () {
- self.reset();
- throw new Error("Wrong url for running " + self.id
- + '\ntestPath: ' + self.testPath
- + '\nhref: ' + window.location.href
- + "\nreferrer: " + document.referrer
- );
- },this.defaultOverLaps);
- }
- return;
- }
-
- var self = this;
- website.Tour.waitReady.call(this, function () {self._running();});
- },
- _running: function () {
- var stepId = this.localStorage.getItem("tour-"+this.id+"-test");
-
- if (stepId != null) {
- this.registerTour();
- this.nextStep(stepId, this.automatic ? this.autoNextStep : null, this.automatic ? this.defaultOverLaps : null);
- }
- },
-
- reset: function () {
- website.Tour.busy = false;
- for (var k in this.steps) {
- this.steps[k].busy = false;
- }
- clearTimeout(self.timer);
- clearTimeout(self.testtimer);
-
- for (var k in this.localStorage) {
- if (!k.indexOf("tour-") || !k.indexOf(this.id)) {
- this.localStorage.removeItem(k);
- }
- }
-
- $('.popover.tour').remove();
- },
-
- getLang: function () {
- return $("html").attr("lang").replace(/-/, '_');
- },
- testUrl: function (url) {
- return new RegExp("(/"+this.getLang()+")?"+url, "i").test(window.location.href);
- },
- testPathUrl: function () {
- if (!this.testPath || this.testUrl(this.testPath)) return true;
- },
- checkRunningUrl: function () {
- if (window.location.hash.indexOf("tutorial."+this.id+"=true") > -1) {
- this.localStorage.setItem("tour-"+this.id+"-test", 0);
- window.location.hash = window.location.hash.replace(/tutorial.+=true&?/, '');
- }
- },
-
- registerTour: function () {
- if (this.automatic) {
- bootstrap_tour_stub();
- }
- this.tour = new Tour({
+ // rendering bootstrap tour and popover
+ if (tour.mode != "test") {
+ tour.tour = new Tour({
name: this.id,
- storage: this.tourStorage,
+ storage: localStorage,
keyboard: false,
template: this.popover(),
onHide: function () {
window.scrollTo(0, 0);
}
});
- this.registerSteps();
- },
- registerSteps: function () {
- for (var index=0, len=this.steps.length; index 0 && this.steps[index-1] &&
- this.steps[index-1].popover && this.steps[index-1].popover.next) {
- step.waitNot = '.popover.tour:visible';
- }
- if (!step.waitFor && index > 0 && this.steps[index-1].snippet) {
- step.waitFor = '.oe_overlay_options .oe_options:visible';
- }
-
+ for (var index=0, len=tour.steps.length; index -1) {
+ tour_id = window.location.href.match(/#tutorial\.(.*)=true/)[1];
+ mode = "tutorial";
+ step_id = 0;
+ }
+ if (!tour_id) {
+ return;
+ }
+ var tour = website.Tour.tours[tour_id];
+ return {'tour': tour, 'tour_id': tour_id, 'mode': mode, 'step_id': step_id};
+};
+website.Tour.error = function (tour, step, message) {
+ website.Tour.reset();
+ throw new Error(message +
+ + "\ntour:" + tour.id +
+ + "\nstep:" + step.id + ": '" + (step._title || step.title) + "'"
+ + '\nhref: ' + window.location.href
+ + '\nreferrer: ' + document.referrer
+ + '\nelement: ' + Boolean(!step.element || ($(step.element).size() && $(step.element).is(":visible") && !$(step.element).is(":hidden")))
+ + '\nwaitNot: ' + Boolean(!step.waitNot || !$(step.waitNot).size())
+ + '\nwaitFor: ' + Boolean(!step.waitFor || $(step.waitFor).size())
+ + '\n\n' + $("body").html()
+ );
+};
+website.Tour.lists = function () {
+ var tour_ids = [];
+ for (var k in website.Tour.tours) {
+ tour_ids.push(k);
+ }
+ return tour_ids;
+};
+website.Tour.save_state = function (tour_id, mode, step_id) {
+ localStorage.setItem("tour", '{tour_id:'+tour_id+', mode:'+mode+', step_id:'+step_id+'}');
+};
+website.Tour.reset = function () {
+ var running = website.Tour.get_state();
+ for (var k in running.tour.steps) {
+ running.tour.steps[k].busy = false;
+ }
+ localStorage.removeItem("tour");
+ clearTimeout(website.Tour.timer);
+ clearTimeout(website.Tour.testtimer);
- if (this.steps[index-1] &&
- this.steps[index-1].popover && this.steps[index-1].popover.next) {
- var step = {
- stepId: ""+index,
- waitNot: '.popover.tour:visible'
- };
- this.steps.push(step);
- }
+ $('.popover.tour').remove();
+};
+website.Tour.running = function () {
+ var running = website.Tour.get_state();
+ website.Tour.registerSteps(running.tour);
+ website.Tour.nextStep( running.tour, running.step_id );
+};
- this.tour.addSteps(this.steps);
- },
+website.Tour.timer = null;
+website.Tour.testtimer = null;
+website.Tour.defaultDelay = 50;
+website.Tour.check = function (step) {
+ return (step &&
+ (!step.element || ($(step.element).size() && $(step.element).is(":visible") && !$(step.element).is(":hidden"))) &&
+ (!step.waitNot || !$(step.waitNot).size()) &&
+ (!step.waitFor || $(step.waitFor).size()));
+};
+website.Tour.waitNextStep = function (tour, step, overlaps) {
+ var time = new Date().getTime();
+ var timer;
- popoverTitle: function (options) {
- try {
- return openerp.qweb.render('website.tour_popover_title', options);
- } catch (e) {
- if (!this.automatic) throw e;
- return options.title;
- }
- },
- popover: function (options) {
- try {
- return openerp.qweb.render('website.tour_popover', options);
- } catch (e) {
- if (!this.automatic) throw e;
- return "";
- }
- },
+ window.onbeforeunload = function () {
+ clearTimeout(website.Tour.timer);
+ clearTimeout(website.Tour.testtimer);
+ };
- timer: null,
- testtimer: null,
- check: function (step) {
- return (step &&
- (!step.element || ($(step.element).size() && $(step.element).is(":visible") && !$(step.element).is(":hidden"))) &&
- (!step.waitNot || !$(step.waitNot).size()) &&
- (!step.waitFor || $(step.waitFor).size()));
- },
- waitNextStep: function (step, callback, overlaps) {
- var self = this;
- var time = new Date().getTime();
- var timer;
-
- window.onbeforeunload = function () {
- clearTimeout(self.timer);
- clearTimeout(self.testtimer);
- };
-
- // check popover activity
- $(".popover.tour button")
- .off()
- .on("click", function () {
- $(".popover.tour").remove();
- if (step.busy) return;
- if (!$(this).is("[data-role='next']")) {
- clearTimeout(self.timer);
- step.busy = true;
- self.tour.end();
- self.endTour(callback);
- }
- });
-
- function checkNext () {
- clearTimeout(self.timer);
+ // check popover activity
+ $(".popover.tour button")
+ .off()
+ .on("click", function () {
+ $(".popover.tour").remove();
if (step.busy) return;
- if (self.check(step)) {
+ if (!$(this).is("[data-role='next']")) {
+ clearTimeout(website.Tour.timer);
step.busy = true;
- // use an other timeout for cke dom loading
- setTimeout(function () {
- self.nextStep(step.stepId, callback, overlaps);
- }, self.defaultDelay);
- } else if (!overlaps || new Date().getTime() - time < overlaps) {
- if (self.current.element) {
- var $popover = $(".popover.tour");
- if(!$(self.current.element).is(":visible")) {
- $popover.data("hide", true).fadeOut(300);
- } else if($popover.data("hide")) {
- $popover.data("hide", false).fadeIn(150);
- }
+ if (tour.tour) {
+ tour.tour.end();
}
- self.timer = setTimeout(checkNext, self.defaultDelay);
- } else {
- self.reset();
- throw new Error("Can't arrive to step " + step.stepId + ": '" + step._title + "'"
- + '\nhref: ' + window.location.href
- + '\nelement: ' + Boolean(!step.element || ($(step.element).size() && $(step.element).is(":visible") && !$(step.element).is(":hidden")))
- + '\nwaitNot: ' + Boolean(!step.waitNot || !$(step.waitNot).size())
- + '\nwaitFor: ' + Boolean(!step.waitFor || $(step.waitFor).size())
- + '\n\n' + $("body").html()
- );
+ tour.endTour(tour);
}
- }
- checkNext();
- },
- step: function (stepId) {
- var steps = this.steps.slice(0,this.steps.length),
- step;
- while (step = steps.shift()) {
- if (!stepId || step.stepId === stepId)
- return step;
- }
- return null;
- },
- next: function (stepId) {
- var steps = this.steps.slice(0,this.steps.length),
- step, next, index=0;
- while (step = steps.shift()) {
- if (!stepId || step.stepId === stepId) {
- // clear popover (fix for boostrap tour if the element is removed before destroy popover)
- $(".popover.tour").remove();
- // go to step in bootstrap tour
- this.tour.goto(index);
- if (step.onload) step.onload();
- next = steps.shift();
- break;
- }
- index++;
- }
- return next;
- },
- nextStep: function (stepId, callback, overlaps) {
- var self = this;
- if (!this.localStorage.getItem("tour-"+this.id+"-test")) return;
+ });
- this.localStorage.setItem("tour-"+this.id+"-test", stepId || 0);
-
- this.current = this.step(stepId);
- var next = this.next(stepId);
-
- if (next) {
+ function checkNext () {
+ clearTimeout(website.Tour.timer);
+ if (step.busy) return;
+ if (website.Tour.check(step)) {
+ step.busy = true;
+ // use an other timeout for cke dom loading
setTimeout(function () {
- self.waitNextStep(next, callback, overlaps);
- if (callback) setTimeout(function(){callback.call(self, next);}, self.defaultDelay);
- }, next && next.wait || 0);
- } else {
- this.endTour();
- }
- },
- endTour: function () {
- var test = parseInt(this.localStorage.getItem("tour-"+this.id+"-test"),10) >= this.steps.length-1;
- this.reset();
- if (test) {
- console.log('ok');
- } else {
- console.log('error');
- }
- },
- autoNextStep: function () {
- var self = this;
- clearTimeout(self.testtimer);
-
- function autoStep () {
- var step = self.current;
- if (!step) return;
-
- if (step.autoComplete) {
- step.autoComplete(tour);
- }
-
- var $popover = $(".popover.tour");
- if ($popover.find("button[data-role='next']:visible").size()) {
- $popover.find("button[data-role='next']:visible").click();
- $popover.remove();
- }
-
- var $element = $(step.element);
- if (!$element.size()) return;
-
- if (step.snippet) {
-
- var selector = '#oe_snippets '+step.snippet+' .oe_snippet_thumbnail';
- self.autoDragAndDropSnippet(selector);
-
- } else if (step.element.match(/#oe_snippets .* \.oe_snippet_thumbnail/)) {
-
- self.autoDragAndDropSnippet($element);
-
- } else if (step.sampleText) {
-
- $element.trigger($.Event("keydown", { srcElement: $element }));
- if ($element.is("input") ) {
- $element.val(step.sampleText);
- } if ($element.is("select")) {
- $element.find("[value='"+step.sampleText+"'], option:contains('"+step.sampleText+"')").attr("selected", true);
- $element.val(step.sampleText);
- } else {
- $element.html(step.sampleText);
+ website.Tour.nextStep(tour, step, overlaps);
+ }, website.Tour.defaultDelay);
+ } else if (!overlaps || new Date().getTime() - time < overlaps) {
+ if (self.current.element) {
+ var $popover = $(".popover.tour");
+ if(!$(self.current.element).is(":visible")) {
+ $popover.data("hide", true).fadeOut(300);
+ } else if($popover.data("hide")) {
+ $popover.data("hide", false).fadeIn(150);
}
- setTimeout(function () {
- $element.trigger($.Event("keyup", { srcElement: $element }));
- $element.trigger($.Event("change", { srcElement: $element }));
- }, self.defaultDelay<<1);
-
- } else if ($element.is(":visible")) {
-
- $element.trigger($.Event("mouseenter", { srcElement: $element[0] }));
- $element.trigger($.Event("mousedown", { srcElement: $element[0] }));
-
- var evt = document.createEvent("MouseEvents");
- evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
- $element[0].dispatchEvent(evt);
-
- // trigger after for step like: mouseenter, next step click on button display with mouseenter
- setTimeout(function () {
- $element.trigger($.Event("mouseup", { srcElement: $element[0] }));
- $element.trigger($.Event("mouseleave", { srcElement: $element[0] }));
- }, 1000);
}
- }
- self.testtimer = setTimeout(autoStep, 100);
- },
- autoDragAndDropSnippet: function (selector) {
- var $thumbnail = $(selector).first();
- var thumbnailPosition = $thumbnail.position();
- $thumbnail.trigger($.Event("mousedown", { which: 1, pageX: thumbnailPosition.left, pageY: thumbnailPosition.top }));
- $thumbnail.trigger($.Event("mousemove", { which: 1, pageX: document.body.scrollWidth/2, pageY: document.body.scrollHeight/2 }));
- var $dropZone = $(".oe_drop_zone").first();
- var dropPosition = $dropZone.position();
- $dropZone.trigger($.Event("mouseup", { which: 1, pageX: dropPosition.left, pageY: dropPosition.top }));
- },
-
-});
-
-
-website.Tour.tours = {};
-website.Tour.busy = false;
-website.Tour.add = function (tour) {
- website.Tour.waitReady(function () {
- tour = tour.id ? tour : new tour();
- if (!website.Tour.tours[tour.id]) {
- website.Tour.tours[tour.id] = tour;
- tour.running();
- }
- });
-};
-website.Tour.get = function (id) {
- return website.Tour.tours[id];
-};
-website.Tour.each = function (callback) {
- website.Tour.waitReady(function () {
- for (var k in website.Tour.tours) {
- callback.call(website.Tour.tours[k]);
- }
- });
-};
-website.Tour.waitReady = function (callback) {
- var self = this;
- $(document).ready(function () {
- if ($.ajaxBusy) {
- $(document).ajaxStop(function() {
- setTimeout(function () {
- callback.call(self);
- },0);
- });
- }
- else {
- setTimeout(function () {
- callback.call(self);
- },0);
- }
- });
-};
-website.Tour.run_test = function (id) {
- website.Tour.waitReady(function () {
- if (!website.Tour.is_busy()) {
- website.Tour.tours[id].run(true);
- }
- });
-};
-website.Tour.is_busy = function () {
- for (var k in this.localStorage) {
- if (!k.indexOf("tour-")) {
- return k;
+ website.Tour.timer = setTimeout(checkNext, website.Tour.defaultDelay);
+ } else {
+ website.Tour.error(tour, step, "Can't arrive to the next step");
}
}
- return website.Tour.busy;
+ checkNext();
};
+website.Tour.nextStep = function (tour, step, overlaps) {
+ var state = website.Tour.get_state();
+ website.Tour.save_state(tour.id, state.mode, step.id);
+
+ // clear popover (fix for boostrap tour if the element is removed before destroy popover)
+ $(".popover.tour").remove();
+ // go to step in bootstrap tour
+ tour.tour.goto(step.id);
+ step.onload();
+ var next = tour.steps[step.id+1];
+
+ if (next) {
+ setTimeout(function () {
+ website.Tour.waitNextStep(tour, next, overlaps);
+ if (state.mode === "test") {
+ setTimeout(function(){
+ website.Tour.autoNextStep(tour, step);
+ }, website.Tour.defaultDelay);
+ }
+ }, next && next.wait || 0);
+ } else {
+ website.Tour.endTour(tour);
+ }
+};
+website.Tour.endTour = function (tour) {
+ var state = website.Tour.get_state();
+ var test = state.step_id >= tour.steps.length-1;
+ this.reset();
+ if (test) {
+ console.log('ok');
+ } else {
+ console.log('error');
+ }
+};
+website.Tour.autoNextStep = function (tour, step) {
+ clearTimeout(website.Tour.testtimer);
+
+ function autoStep () {
+ if (!step) return;
+
+ if (step.autoComplete) {
+ step.autoComplete(tour);
+ }
+
+ var $popover = $(".popover.tour");
+ if ($popover.find("button[data-role='next']:visible").size()) {
+ $popover.find("button[data-role='next']:visible").click();
+ $popover.remove();
+ }
+
+ var $element = $(step.element);
+ if (!$element.size()) return;
+
+ if (step.snippet) {
+
+ website.Tour.autoDragAndDropSnippet($element);
+
+ } else if (step.sampleText) {
+
+ $element.trigger($.Event("keydown", { srcElement: $element }));
+ if ($element.is("input") ) {
+ $element.val(step.sampleText);
+ } if ($element.is("select")) {
+ $element.find("[value='"+step.sampleText+"'], option:contains('"+step.sampleText+"')").attr("selected", true);
+ $element.val(step.sampleText);
+ } else {
+ $element.html(step.sampleText);
+ }
+ setTimeout(function () {
+ $element.trigger($.Event("keyup", { srcElement: $element }));
+ $element.trigger($.Event("change", { srcElement: $element }));
+ }, website.Tour.defaultDelay<<1);
+
+ } else if ($element.is(":visible")) {
+
+ $element.trigger($.Event("mouseenter", { srcElement: $element[0] }));
+ $element.trigger($.Event("mousedown", { srcElement: $element[0] }));
+
+ var evt = document.createEvent("MouseEvents");
+ evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ $element[0].dispatchEvent(evt);
+
+ // trigger after for step like: mouseenter, next step click on button display with mouseenter
+ setTimeout(function () {
+ $element.trigger($.Event("mouseup", { srcElement: $element[0] }));
+ $element.trigger($.Event("mouseleave", { srcElement: $element[0] }));
+ }, 1000);
+ }
+ }
+ website.Tour.testtimer = setTimeout(autoStep, 100);
+};
+website.Tour.autoDragAndDropSnippet = function (selector) {
+ var $thumbnail = $(selector).first();
+ var thumbnailPosition = $thumbnail.position();
+ $thumbnail.trigger($.Event("mousedown", { which: 1, pageX: thumbnailPosition.left, pageY: thumbnailPosition.top }));
+ $thumbnail.trigger($.Event("mousemove", { which: 1, pageX: document.body.scrollWidth/2, pageY: document.body.scrollHeight/2 }));
+ var $dropZone = $(".oe_drop_zone").first();
+ var dropPosition = $dropZone.position();
+ $dropZone.trigger($.Event("mouseup", { which: 1, pageX: dropPosition.left, pageY: dropPosition.top }));
+};
+
+website.ready(website.Tour.running);
}());
diff --git a/addons/website_blog/static/src/js/website.tour.blog.js b/addons/website_blog/static/src/js/website.tour.blog.js
index 3470e2e383b..050bf549225 100644
--- a/addons/website_blog/static/src/js/website.tour.blog.js
+++ b/addons/website_blog/static/src/js/website.tour.blog.js
@@ -4,117 +4,105 @@
var website = openerp.website;
var _t = openerp._t;
- website.EditorBar.include({
- start: function () {
- this.registerTour(new website.Tour.Blog(this));
- return this._super();
- },
- });
-
- website.Tour.Blog = website.Tour.extend({
- id: 'blog',
- name: "Create a blog post",
- testPath: '/(blog|blogpost)',
- init: function () {
- var self = this;
- self.steps = [
- {
- title: _t("New Blog Post"),
- content: _t("Let's go through the first steps to write beautiful blog posts."),
- popover: { next: _t("Start Tutorial"), end: _t("Skip") },
- },
- {
- element: '#content-menu-button',
- placement: 'left',
- title: _t("Add Content"),
- content: _t("Use this 'Content' menu to create a new blog post like any other document (page, menu, products, event, ...)."),
- popover: { fixed: true },
- },
- {
- element: 'a[data-action=new_blog_post]',
- placement: 'left',
- title: _t("New Blog Post"),
- content: _t("Select this menu item to create a new blog post."),
- popover: { fixed: true },
- },
- {
- element: '.modal:has(#editor_new_blog) button.btn-primary',
- placement: 'right',
- title: _t("Create Blog Post"),
- content: _t("Click Continue to create the blog post."),
- },
- {
- waitFor: 'body:has(button[data-action=save]:visible):has(.js_blog)',
- title: _t("Blog Post Created"),
- content: _t("This is your new blog post. Let's edit it."),
- popover: { next: _t("Continue") },
- },
- {
- element: 'h1[data-oe-expression="blog_post.name"]',
- placement: 'bottom',
- sampleText: 'New Blog',
- title: _t("Set a Title"),
- content: _t("Click on this area and set a catchy title for your blog post."),
- },
- {
- waitNot: '#wrap h1[data-oe-model="blog.post"]:contains("Blog Post Title")',
- element: 'button[data-action=snippet]',
- placement: 'left',
- title: _t("Layout Your Blog Post"),
- content: _t("Use well designed building blocks to structure the content of your blog. Click 'Insert Blocks' to add new content."),
- popover: { fixed: true },
- },
- {
- snippet: '#snippet_structure .oe_snippet:eq(2)',
- placement: 'bottom',
- title: _t("Drag & Drop a Block"),
- content: _t("Drag this block and drop it in your page."),
- popover: { fixed: true },
- },
- {
- element: 'button[data-action=snippet]',
- placement: 'bottom',
- title: _t("Add Another Block"),
- content: _t("Let's add another block to your post."),
- popover: { fixed: true },
- },
- {
- snippet: '#snippet_structure .oe_snippet:eq(4)',
- placement: 'bottom',
- title: _t("Drag & Drop a block"),
- content: _t("Drag this block and drop it below the image block."),
- popover: { fixed: true },
- },
- {
- element: '.oe_active .oe_snippet_remove',
- placement: 'top',
- title: _t("Delete the block"),
- content: _t("From this toolbar you can move, duplicate or delete the selected zone. Click on the garbage can image to delete the block. Or click on the Title and delete it."),
- },
- {
- waitNot: '.oe_active .oe_snippet_remove:visible',
- element: 'button[data-action=save]',
- placement: 'right',
- title: _t("Save Your Blog"),
- content: _t("Click the Save button to record changes on the page."),
- popover: { fixed: true },
- },
- {
- waitFor: 'button[data-action=edit]:visible',
- element: 'button.btn-danger.js_publish_btn',
- placement: 'top',
- title: _t("Publish Your Post"),
- content: _t("Your blog post is not yet published. You can update this draft version and publish it once you are ready."),
- },
- {
- waitFor: '.js_publish_management button.js_publish_btn.btn-success:visible',
- title: "Thanks!",
- content: _t("This tutorial is finished. To discover more features, improve the content of this page and try the Promote button in the top right menu."),
- popover: { next: _t("Close Tutorial") },
- },
- ];
- return this._super();
- },
+ website.Tour.register({
+ id: 'blog',
+ name: _t("Create a blog post"),
+ steps: [
+ {
+ title: _t("New Blog Post"),
+ content: _t("Let's go through the first steps to write beautiful blog posts."),
+ popover: { next: _t("Start Tutorial"), end: _t("Skip") },
+ },
+ {
+ element: '#content-menu-button',
+ placement: 'left',
+ title: _t("Add Content"),
+ content: _t("Use this 'Content' menu to create a new blog post like any other document (page, menu, products, event, ...)."),
+ popover: { fixed: true },
+ },
+ {
+ element: 'a[data-action=new_blog_post]',
+ placement: 'left',
+ title: _t("New Blog Post"),
+ content: _t("Select this menu item to create a new blog post."),
+ popover: { fixed: true },
+ },
+ {
+ element: '.modal:has(#editor_new_blog) button.btn-primary',
+ placement: 'right',
+ title: _t("Create Blog Post"),
+ content: _t("Click Continue to create the blog post."),
+ },
+ {
+ waitFor: 'body:has(button[data-action=save]:visible):has(.js_blog)',
+ title: _t("Blog Post Created"),
+ content: _t("This is your new blog post. Let's edit it."),
+ popover: { next: _t("Continue") },
+ },
+ {
+ element: 'h1[data-oe-expression="blog_post.name"]',
+ placement: 'bottom',
+ sampleText: 'New Blog',
+ title: _t("Set a Title"),
+ content: _t("Click on this area and set a catchy title for your blog post."),
+ },
+ {
+ waitNot: '#wrap h1[data-oe-model="blog.post"]:contains("Blog Post Title")',
+ element: 'button[data-action=snippet]',
+ placement: 'left',
+ title: _t("Layout Your Blog Post"),
+ content: _t("Use well designed building blocks to structure the content of your blog. Click 'Insert Blocks' to add new content."),
+ popover: { fixed: true },
+ },
+ {
+ snippet: '#snippet_structure .oe_snippet:eq(2)',
+ placement: 'bottom',
+ title: _t("Drag & Drop a Block"),
+ content: _t("Drag this block and drop it in your page."),
+ popover: { fixed: true },
+ },
+ {
+ element: 'button[data-action=snippet]',
+ placement: 'bottom',
+ title: _t("Add Another Block"),
+ content: _t("Let's add another block to your post."),
+ popover: { fixed: true },
+ },
+ {
+ snippet: '#snippet_structure .oe_snippet:eq(4)',
+ placement: 'bottom',
+ title: _t("Drag & Drop a block"),
+ content: _t("Drag this block and drop it below the image block."),
+ popover: { fixed: true },
+ },
+ {
+ element: '.oe_active .oe_snippet_remove',
+ placement: 'top',
+ title: _t("Delete the block"),
+ content: _t("From this toolbar you can move, duplicate or delete the selected zone. Click on the garbage can image to delete the block. Or click on the Title and delete it."),
+ },
+ {
+ waitNot: '.oe_active .oe_snippet_remove:visible',
+ element: 'button[data-action=save]',
+ placement: 'right',
+ title: _t("Save Your Blog"),
+ content: _t("Click the Save button to record changes on the page."),
+ popover: { fixed: true },
+ },
+ {
+ waitFor: 'button[data-action=edit]:visible',
+ element: 'button.btn-danger.js_publish_btn',
+ placement: 'top',
+ title: _t("Publish Your Post"),
+ content: _t("Your blog post is not yet published. You can update this draft version and publish it once you are ready."),
+ },
+ {
+ waitFor: '.js_publish_management button.js_publish_btn.btn-success:visible',
+ title: "Thanks!",
+ content: _t("This tutorial is finished. To discover more features, improve the content of this page and try the Promote button in the top right menu."),
+ popover: { next: _t("Close Tutorial") },
+ },
+ ]
});
}());
diff --git a/addons/website_event/static/src/js/website.tour.event.js b/addons/website_event/static/src/js/website.tour.event.js
index ef013398acb..07a12d81f34 100644
--- a/addons/website_event/static/src/js/website.tour.event.js
+++ b/addons/website_event/static/src/js/website.tour.event.js
@@ -4,115 +4,103 @@
var website = openerp.website;
var _t = openerp._t;
- website.EditorBar.include({
- start: function () {
- this.registerTour(new website.EventTour(this));
- return this._super();
- },
- });
-
- website.EventTour = website.Tour.extend({
- id: 'event',
- name: "Create an event",
- testPath: '/event(/[0-9]+/register)?',
- init: function (editor) {
- var self = this;
- self.steps = [
- {
- title: _t("Create an Event"),
- content: _t("Let's go through the first steps to publish a new event."),
- popover: { next: _t("Start Tutorial"), end: _t("Skip It") },
- },
- {
- element: '#content-menu-button',
- placement: 'left',
- title: _t("Add Content"),
- content: _t("The Content menu allows you to create new pages, events, menus, etc."),
- popover: { fixed: true },
- },
- {
- element: 'a[data-action=new_event]',
- placement: 'left',
- title: _t("New Event"),
- content: _t("Click here to create a new event."),
- popover: { fixed: true },
- },
- {
- element: '.modal #editor_new_event input[type=text]',
- sampleText: 'Advanced Technical Training',
- placement: 'right',
- title: _t("Create an Event Name"),
- content: _t("Create a name for your new event and click 'Continue'. e.g: Technical Training"),
- },
- {
- waitNot: '.modal input[type=text]:not([value!=""])',
- element: '.modal button.btn-primary',
- placement: 'right',
- title: _t("Create Event"),
- content: _t("Click Continue to create the event."),
- },
- {
- waitFor: 'body:has(button[data-action=save]:visible):has(.js_event)',
- title: _t("New Event Created"),
- content: _t("This is your new event page. We will edit the event presentation page."),
- popover: { next: _t("Continue") },
- },
- {
- element: 'button[data-action=snippet]',
- placement: 'bottom',
- title: _t("Layout your event"),
- content: _t("Insert blocks to layout the body of your event."),
- popover: { fixed: true },
- },
- {
- snippet: '#snippet_structure .oe_snippet:eq(2)',
- placement: 'bottom',
- title: _t("Drag & Drop a block"),
- content: _t("Drag the 'Image-Text' block and drop it in your page."),
- popover: { fixed: true },
- },
- {
-
- element: 'button[data-action=snippet]',
- placement: 'bottom',
- title: _t("Layout your event"),
- content: _t("Insert another block to your event."),
- popover: { fixed: true },
- },
- {
- snippet: '#snippet_structure .oe_snippet:eq(4)',
- placement: 'bottom',
- title: _t("Drag & Drop a block"),
- content: _t("Drag the 'Text Block' in your event page."),
- popover: { fixed: true },
- },
- {
- element: 'button[data-action=save]',
- placement: 'right',
- title: _t("Save your modifications"),
- content: _t("Once you click on save, your event is updated."),
- popover: { fixed: true },
- },
- {
- waitFor: 'button[data-action=edit]:visible',
- element: 'button.btn-danger.js_publish_btn',
- placement: 'top',
- title: _t("Publish your event"),
- content: _t("Click to publish your event."),
- },
- {
- waitFor: '.js_publish_management button.js_publish_btn.btn-success:visible',
- element: '.js_publish_management button[data-toggle="dropdown"]',
- placement: 'left',
- title: _t("Customize your event"),
- content: _t("Click here to customize your event further."),
- },
- {
- element: '.js_publish_management ul>li>a:last:visible',
- },
- ];
- return this._super();
- }
+ website.Tour.register({
+ id: 'event',
+ name: _t("Create an event"),
+ steps: [
+ {
+ title: _t("Create an Event"),
+ content: _t("Let's go through the first steps to publish a new event."),
+ popover: { next: _t("Start Tutorial"), end: _t("Skip It") },
+ },
+ {
+ element: '#content-menu-button',
+ placement: 'left',
+ title: _t("Add Content"),
+ content: _t("The Content menu allows you to create new pages, events, menus, etc."),
+ popover: { fixed: true },
+ },
+ {
+ element: 'a[data-action=new_event]',
+ placement: 'left',
+ title: _t("New Event"),
+ content: _t("Click here to create a new event."),
+ popover: { fixed: true },
+ },
+ {
+ element: '.modal #editor_new_event input[type=text]',
+ sampleText: 'Advanced Technical Training',
+ placement: 'right',
+ title: _t("Create an Event Name"),
+ content: _t("Create a name for your new event and click 'Continue'. e.g: Technical Training"),
+ },
+ {
+ waitNot: '.modal input[type=text]:not([value!=""])',
+ element: '.modal button.btn-primary',
+ placement: 'right',
+ title: _t("Create Event"),
+ content: _t("Click Continue to create the event."),
+ },
+ {
+ waitFor: 'body:has(button[data-action=save]:visible):has(.js_event)',
+ title: _t("New Event Created"),
+ content: _t("This is your new event page. We will edit the event presentation page."),
+ popover: { next: _t("Continue") },
+ },
+ {
+ element: 'button[data-action=snippet]',
+ placement: 'bottom',
+ title: _t("Layout your event"),
+ content: _t("Insert blocks to layout the body of your event."),
+ popover: { fixed: true },
+ },
+ {
+ snippet: '#snippet_structure .oe_snippet:eq(2)',
+ placement: 'bottom',
+ title: _t("Drag & Drop a block"),
+ content: _t("Drag the 'Image-Text' block and drop it in your page."),
+ popover: { fixed: true },
+ },
+ {
+
+ element: 'button[data-action=snippet]',
+ placement: 'bottom',
+ title: _t("Layout your event"),
+ content: _t("Insert another block to your event."),
+ popover: { fixed: true },
+ },
+ {
+ snippet: '#snippet_structure .oe_snippet:eq(4)',
+ placement: 'bottom',
+ title: _t("Drag & Drop a block"),
+ content: _t("Drag the 'Text Block' in your event page."),
+ popover: { fixed: true },
+ },
+ {
+ element: 'button[data-action=save]',
+ placement: 'right',
+ title: _t("Save your modifications"),
+ content: _t("Once you click on save, your event is updated."),
+ popover: { fixed: true },
+ },
+ {
+ waitFor: 'button[data-action=edit]:visible',
+ element: 'button.btn-danger.js_publish_btn',
+ placement: 'top',
+ title: _t("Publish your event"),
+ content: _t("Click to publish your event."),
+ },
+ {
+ waitFor: '.js_publish_management button.js_publish_btn.btn-success:visible',
+ element: '.js_publish_management button[data-toggle="dropdown"]',
+ placement: 'left',
+ title: _t("Customize your event"),
+ content: _t("Click here to customize your event further."),
+ },
+ {
+ element: '.js_publish_management ul>li>a:last:visible',
+ },
+ ]
});
}());
diff --git a/addons/website_event_sale/static/src/js/website.tour.event_sale.js b/addons/website_event_sale/static/src/js/website.tour.event_sale.js
index 48b9b62b349..92e57638cc8 100644
--- a/addons/website_event_sale/static/src/js/website.tour.event_sale.js
+++ b/addons/website_event_sale/static/src/js/website.tour.event_sale.js
@@ -3,77 +3,72 @@
var website = openerp.website;
- website.Tour.EventSaleTest = website.Tour.extend({
- id: 'event_buy_tickets',
+ website.Tour.register({
+ id: 'event_buy_tickets',
name: "Try to buy tickets for event",
path: '/event',
- init: function () {
- var self = this;
- self.steps = [
- {
- title: "select event",
- element: 'a[href*="/event"]:contains("Open Days in Los Angeles")',
+ mode: 'test',
+ steps: [
+ {
+ title: "select event",
+ element: 'a[href*="/event"]:contains("Open Days in Los Angeles")',
+ },
+ {
+ title: "go to register page",
+ waitNot: 'a[href*="/event"]:contains("Functional Webinar")',
+ onload: function () {
+ // use onload if website_event_track is installed
+ if (!$('form:contains("Ticket Type")').size()) {
+ window.location.href = $('a[href*="/event"][href*="/register"]').attr("href");
+ }
},
- {
- title: "go to register page",
- waitNot: 'a[href*="/event"]:contains("Functional Webinar")',
- onload: function () {
- // use onload if website_event_track is installed
- if (!$('form:contains("Ticket Type")').size()) {
- window.location.href = $('a[href*="/event"][href*="/register"]').attr("href");
- }
- },
+ },
+ {
+ title: "select 2 Standard tickets",
+ element: 'select[name="ticket-1"]',
+ sampleText: '2',
+ },
+ {
+ title: "select 3 VIP tickets",
+ waitFor: 'select[name="ticket-1"] option:contains(2):selected',
+ element: 'select[name="ticket-2"]',
+ sampleText: '3',
+ },
+ {
+ title: "Order Now",
+ waitFor: 'select[name="ticket-2"] option:contains(3):selected',
+ element: '.btn-primary:contains("Order Now")',
+ },
+ {
+ title: "Complete checkout",
+ waitFor: '#top_menu .my_cart_quantity:contains(5)',
+ element: 'form[action="/shop/confirm_order"] .btn:contains("Confirm")',
+ onload: function (tour) {
+ if ($("input[name='name']").val() === "")
+ $("input[name='name']").val("website_sale-test-shoptest");
+ if ($("input[name='email']").val() === "")
+ $("input[name='email']").val("website_event_sale_test_shoptest@websiteeventsaletest.optenerp.com");
+ $("input[name='phone']").val("123");
+ $("input[name='street']").val("123");
+ $("input[name='city']").val("123");
+ $("input[name='zip']").val("123");
+ $("select[name='country_id']").val("21");
},
- {
- title: "select 2 Standard tickets",
- element: 'select[name="ticket-1"]',
- sampleText: '2',
- },
- {
- title: "select 3 VIP tickets",
- waitFor: 'select[name="ticket-1"] option:contains(2):selected',
- element: 'select[name="ticket-2"]',
- sampleText: '3',
- },
- {
- title: "Order Now",
- waitFor: 'select[name="ticket-2"] option:contains(3):selected',
- element: '.btn-primary:contains("Order Now")',
- },
- {
- title: "Complete checkout",
- waitFor: '#top_menu .my_cart_quantity:contains(5)',
- element: 'form[action="/shop/confirm_order"] .btn:contains("Confirm")',
- onload: function (tour) {
- if ($("input[name='name']").val() === "")
- $("input[name='name']").val("website_sale-test-shoptest");
- if ($("input[name='email']").val() === "")
- $("input[name='email']").val("website_event_sale_test_shoptest@websiteeventsaletest.optenerp.com");
- $("input[name='phone']").val("123");
- $("input[name='street']").val("123");
- $("input[name='city']").val("123");
- $("input[name='zip']").val("123");
- $("select[name='country_id']").val("21");
- },
- },
- {
- title: "select payment",
- element: '#payment_method label:has(img[title="transfer"]) input',
- },
- {
- title: "Pay Now",
- waitFor: '#payment_method label:has(input:checked):has(img[title="transfer"])',
- element: '.oe_sale_acquirer_button .btn[name="submit"]:visible',
- },
- {
- title: "finish",
- waitFor: '.oe_website_sale:contains("Thank you for your order")',
- }
- ];
- return this._super();
- },
+ },
+ {
+ title: "select payment",
+ element: '#payment_method label:has(img[title="transfer"]) input',
+ },
+ {
+ title: "Pay Now",
+ waitFor: '#payment_method label:has(input:checked):has(img[title="transfer"])',
+ element: '.oe_sale_acquirer_button .btn[name="submit"]:visible',
+ },
+ {
+ title: "finish",
+ waitFor: '.oe_website_sale:contains("Thank you for your order")',
+ }
+ ]
});
- // for test without editor bar
- website.Tour.add(website.Tour.EventSaleTest);
}());
diff --git a/addons/website_sale/static/src/js/website.tour.sale.js b/addons/website_sale/static/src/js/website.tour.sale.js
index c9dd7e5e301..c7526b2468f 100644
--- a/addons/website_sale/static/src/js/website.tour.sale.js
+++ b/addons/website_sale/static/src/js/website.tour.sale.js
@@ -3,92 +3,87 @@
var website = openerp.website;
- website.Tour.ShopTest = website.Tour.extend({
- id: 'shop_buy_product',
+ website.Tour.register({
+ id: 'shop_buy_product',
name: "Try to buy products",
path: '/shop',
- init: function () {
- var self = this;
- self.steps = [
- {
- title: "select ipod",
- element: '.oe_product_cart a:contains("iPod")',
+ mode: 'test',
+ steps: [
+ {
+ title: "select ipod",
+ element: '.oe_product_cart a:contains("iPod")',
+ },
+ {
+ title: "select ipod 32Go",
+ element: 'input[name="product_id"]:not([checked])',
+ },
+ {
+ title: "click on add to cart",
+ waitFor: 'input[name="product_id"]:eq(1)[checked]',
+ element: 'form[action="/shop/add_cart"] .btn',
+ },
+ {
+ title: "add suggested",
+ element: 'form[action="/shop/add_cart"] .btn-link:contains("Add to Cart")',
+ },
+ {
+ title: "add one more iPod",
+ waitFor: '.my_cart_quantity:contains(2)',
+ element: '#mycart_products tr:contains("iPod: 32 Gb") a.js_add_cart_json:eq(1)',
+ },
+ {
+ title: "remove Headphones",
+ waitFor: '#mycart_products tr:contains("iPod: 32 Gb") input.js_quantity[value=2]',
+ element: '#mycart_products tr:contains("Apple In-Ear Headphones") a.js_add_cart_json:first',
+ },
+ {
+ title: "set one iPod",
+ waitNot: '#mycart_products tr:contains("Apple In-Ear Headphones")',
+ element: '#mycart_products input.js_quantity',
+ sampleText: '1',
+ },
+ {
+ title: "go to checkout",
+ waitFor: '#mycart_products input.js_quantity[value=1]',
+ element: 'a[href="/shop/checkout"]',
+ },
+ {
+ title: "test with input error",
+ element: 'form[action="/shop/confirm_order"] .btn:contains("Confirm")',
+ onload: function (tour) {
+ $("input[name='phone']").val("");
},
- {
- title: "select ipod 32Go",
- element: 'input[name="product_id"]:not([checked])',
+ },
+ {
+ title: "test without input error",
+ waitFor: 'form[action="/shop/confirm_order"] .has-error',
+ element: 'form[action="/shop/confirm_order"] .btn:contains("Confirm")',
+ onload: function (tour) {
+ if ($("input[name='name']").val() === "")
+ $("input[name='name']").val("website_sale-test-shoptest");
+ if ($("input[name='email']").val() === "")
+ $("input[name='email']").val("website_sale_test_shoptest@websitesaletest.optenerp.com");
+ $("input[name='phone']").val("123");
+ $("input[name='street']").val("123");
+ $("input[name='city']").val("123");
+ $("input[name='zip']").val("123");
+ $("select[name='country_id']").val("21");
},
- {
- title: "click on add to cart",
- waitFor: 'input[name="product_id"]:eq(1)[checked]',
- element: 'form[action="/shop/add_cart"] .btn',
- },
- {
- title: "add suggested",
- element: 'form[action="/shop/add_cart"] .btn-link:contains("Add to Cart")',
- },
- {
- title: "add one more iPod",
- waitFor: '.my_cart_quantity:contains(2)',
- element: '#mycart_products tr:contains("iPod: 32 Gb") a.js_add_cart_json:eq(1)',
- },
- {
- title: "remove Headphones",
- waitFor: '#mycart_products tr:contains("iPod: 32 Gb") input.js_quantity[value=2]',
- element: '#mycart_products tr:contains("Apple In-Ear Headphones") a.js_add_cart_json:first',
- },
- {
- title: "set one iPod",
- waitNot: '#mycart_products tr:contains("Apple In-Ear Headphones")',
- element: '#mycart_products input.js_quantity',
- sampleText: '1',
- },
- {
- title: "go to checkout",
- waitFor: '#mycart_products input.js_quantity[value=1]',
- element: 'a[href="/shop/checkout"]',
- },
- {
- title: "test with input error",
- element: 'form[action="/shop/confirm_order"] .btn:contains("Confirm")',
- onload: function (tour) {
- $("input[name='phone']").val("");
- },
- },
- {
- title: "test without input error",
- waitFor: 'form[action="/shop/confirm_order"] .has-error',
- element: 'form[action="/shop/confirm_order"] .btn:contains("Confirm")',
- onload: function (tour) {
- if ($("input[name='name']").val() === "")
- $("input[name='name']").val("website_sale-test-shoptest");
- if ($("input[name='email']").val() === "")
- $("input[name='email']").val("website_sale_test_shoptest@websitesaletest.optenerp.com");
- $("input[name='phone']").val("123");
- $("input[name='street']").val("123");
- $("input[name='city']").val("123");
- $("input[name='zip']").val("123");
- $("select[name='country_id']").val("21");
- },
- },
- {
- title: "select payment",
- element: '#payment_method label:has(img[title="transfer"]) input',
- },
- {
- title: "Pay Now",
- waitFor: '#payment_method label:has(input:checked):has(img[title="transfer"])',
- element: '.oe_sale_acquirer_button .btn[name="submit"]:visible',
- },
- {
- title: "finish",
- waitFor: '.oe_website_sale:contains("Thank you for your order")',
- }
- ];
- return this._super();
- },
+ },
+ {
+ title: "select payment",
+ element: '#payment_method label:has(img[title="transfer"]) input',
+ },
+ {
+ title: "Pay Now",
+ waitFor: '#payment_method label:has(input:checked):has(img[title="transfer"])',
+ element: '.oe_sale_acquirer_button .btn[name="submit"]:visible',
+ },
+ {
+ title: "finish",
+ waitFor: '.oe_website_sale:contains("Thank you for your order")',
+ }
+ ]
});
- // for test without editor bar
- website.Tour.add(website.Tour.ShopTest);
}());
diff --git a/addons/website_sale/static/src/js/website.tour.shop.js b/addons/website_sale/static/src/js/website.tour.shop.js
index adb4a9e556c..bd03523e054 100644
--- a/addons/website_sale/static/src/js/website.tour.shop.js
+++ b/addons/website_sale/static/src/js/website.tour.shop.js
@@ -4,141 +4,129 @@
var website = openerp.website;
var _t = openerp._t;
- website.EditorBar.include({
- start: function () {
- this.registerTour(new website.Tour.Shop(this));
- return this._super();
- },
- });
-
- website.Tour.Shop = website.Tour.extend({
+ website.Tour.register({
id: 'shop',
- name: "Create a product",
- testPath: '/shop',
- init: function () {
- var self = this;
- self.steps = [
- {
- title: _t("Welcome to your shop"),
- content: _t("You successfully installed the e-commerce. This guide will help you to create your product and promote your sales."),
- popover: { next: _t("Start Tutorial"), end: _t("Skip It") },
- },
- {
- element: '#content-menu-button',
- placement: 'left',
- title: _t("Create your first product"),
- content: _t("Click here to add a new product."),
- popover: { fixed: true },
- },
- {
- element: 'a[data-action=new_product]',
- placement: 'left',
- title: _t("Create a new product"),
- content: _t("Select 'New Product' to create it and manage its properties to boost your sales."),
- popover: { fixed: true },
- },
- {
- element: '.modal #editor_new_product input[type=text]',
- sampleText: 'New Product',
- placement: 'right',
- title: _t("Choose name"),
- content: _t("Enter a name for your new product then click 'Continue'."),
- },
- {
- waitNot: '.modal input[type=text]:not([value!=""])',
- element: '.modal button.btn-primary',
- placement: 'right',
- title: _t("Create Product"),
- content: _t("Click Continue to create the product."),
- },
- {
- waitFor: 'body:has(button[data-action=save]:visible):has(.js_sale)',
- title: _t("New product created"),
- content: _t("This page contains all the information related to the new product."),
- popover: { next: _t("Continue") },
- },
- {
- element: '.product_price .oe_currency_value',
- sampleText: '20.50',
- placement: 'left',
- title: _t("Change the price"),
- content: _t("Edit the price of this product by clicking on the amount."),
- },
- {
- waitNot: '.product_price .oe_currency_value:containsExact(1.00)',
- element: '#wrap img.img:first',
- placement: 'top',
- title: _t("Update image"),
- content: _t("Click here to set an image describing your product."),
- },
- {
- element: 'button.hover-edition-button:visible',
- placement: 'top',
- title: _t("Update image"),
- content: _t("Click here to set an image describing your product."),
- },
- {
- wait: 500,
- element: '.well a.pull-right',
- placement: 'bottom',
- title: _t("Select an Image"),
- content: _t("Let's select an existing image."),
- popover: { fixed: true },
- },
- {
- element: 'img[alt=imac]',
- placement: 'bottom',
- title: _t("Select an Image"),
- content: _t("Let's select an imac image."),
- popover: { fixed: true },
- },
- {
- waitNot: 'img[alt=imac]',
- element: '.modal-content button.save',
- placement: 'bottom',
- title: _t("Select this Image"),
- content: _t("Click to add the image to the product decsription."),
- popover: { fixed: true },
- },
- {
- waitNot: '.modal-content:visible',
- element: 'button[data-action=snippet]',
- placement: 'bottom',
- title: _t("Describe the Product"),
- content: _t("Insert blocks like text-image, or gallery to fully describe the product."),
- popover: { fixed: true },
- },
- {
- snippet: '#snippet_structure .oe_snippet:eq(7)',
- placement: 'bottom',
- title: _t("Drag & Drop a block"),
- content: _t("Drag the 'Big Picture' block and drop it in your page."),
- popover: { fixed: true },
- },
- {
- element: 'button[data-action=save]',
- placement: 'right',
- title: _t("Save your modifications"),
- content: _t("Once you click on save, your product is updated."),
- popover: { fixed: true },
+ name: _t("Create a product"),
+ steps: [
+ {
+ title: _t("Welcome to your shop"),
+ content: _t("You successfully installed the e-commerce. This guide will help you to create your product and promote your sales."),
+ popover: { next: _t("Start Tutorial"), end: _t("Skip It") },
+ },
+ {
+ element: '#content-menu-button',
+ placement: 'left',
+ title: _t("Create your first product"),
+ content: _t("Click here to add a new product."),
+ popover: { fixed: true },
+ },
+ {
+ element: 'a[data-action=new_product]',
+ placement: 'left',
+ title: _t("Create a new product"),
+ content: _t("Select 'New Product' to create it and manage its properties to boost your sales."),
+ popover: { fixed: true },
+ },
+ {
+ element: '.modal #editor_new_product input[type=text]',
+ sampleText: 'New Product',
+ placement: 'right',
+ title: _t("Choose name"),
+ content: _t("Enter a name for your new product then click 'Continue'."),
+ },
+ {
+ waitNot: '.modal input[type=text]:not([value!=""])',
+ element: '.modal button.btn-primary',
+ placement: 'right',
+ title: _t("Create Product"),
+ content: _t("Click Continue to create the product."),
+ },
+ {
+ waitFor: 'body:has(button[data-action=save]:visible):has(.js_sale)',
+ title: _t("New product created"),
+ content: _t("This page contains all the information related to the new product."),
+ popover: { next: _t("Continue") },
+ },
+ {
+ element: '.product_price .oe_currency_value',
+ sampleText: '20.50',
+ placement: 'left',
+ title: _t("Change the price"),
+ content: _t("Edit the price of this product by clicking on the amount."),
+ },
+ {
+ waitNot: '.product_price .oe_currency_value:containsExact(1.00)',
+ element: '#wrap img.img:first',
+ placement: 'top',
+ title: _t("Update image"),
+ content: _t("Click here to set an image describing your product."),
+ },
+ {
+ element: 'button.hover-edition-button:visible',
+ placement: 'top',
+ title: _t("Update image"),
+ content: _t("Click here to set an image describing your product."),
+ },
+ {
+ wait: 500,
+ element: '.well a.pull-right',
+ placement: 'bottom',
+ title: _t("Select an Image"),
+ content: _t("Let's select an existing image."),
+ popover: { fixed: true },
+ },
+ {
+ element: 'img[alt=imac]',
+ placement: 'bottom',
+ title: _t("Select an Image"),
+ content: _t("Let's select an imac image."),
+ popover: { fixed: true },
+ },
+ {
+ waitNot: 'img[alt=imac]',
+ element: '.modal-content button.save',
+ placement: 'bottom',
+ title: _t("Select this Image"),
+ content: _t("Click to add the image to the product decsription."),
+ popover: { fixed: true },
+ },
+ {
+ waitNot: '.modal-content:visible',
+ element: 'button[data-action=snippet]',
+ placement: 'bottom',
+ title: _t("Describe the Product"),
+ content: _t("Insert blocks like text-image, or gallery to fully describe the product."),
+ popover: { fixed: true },
+ },
+ {
+ snippet: '#snippet_structure .oe_snippet:eq(7)',
+ placement: 'bottom',
+ title: _t("Drag & Drop a block"),
+ content: _t("Drag the 'Big Picture' block and drop it in your page."),
+ popover: { fixed: true },
+ },
+ {
+ element: 'button[data-action=save]',
+ placement: 'right',
+ title: _t("Save your modifications"),
+ content: _t("Once you click on save, your product is updated."),
+ popover: { fixed: true },
- },
- {
- waitFor: '#website-top-navbar button[data-action="edit"]:visible',
- element: '.js_publish_management button.js_publish_btn.btn-danger',
- placement: 'top',
- title: _t("Publish your product"),
- content: _t("Click to publish your product so your customers can see it."),
- },
- {
- waitFor: '.js_publish_management button.js_publish_btn.btn-success:visible',
- title: _t("Congratulations"),
- content: _t("Congratulations! You just created and published your first product."),
- popover: { next: _t("Close Tutorial") },
- },
- ];
- return this._super();
- }
+ },
+ {
+ waitFor: '#website-top-navbar button[data-action="edit"]:visible',
+ element: '.js_publish_management button.js_publish_btn.btn-danger',
+ placement: 'top',
+ title: _t("Publish your product"),
+ content: _t("Click to publish your product so your customers can see it."),
+ },
+ {
+ waitFor: '.js_publish_management button.js_publish_btn.btn-success:visible',
+ title: _t("Congratulations"),
+ content: _t("Congratulations! You just created and published your first product."),
+ popover: { next: _t("Close Tutorial") },
+ },
+ ]
});
}());
From 0b75d4ea043e35c9c523b9ec24324eae8d149e8f Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Thu, 20 Mar 2014 09:56:06 +0100
Subject: [PATCH 02/26] [IMP] website: remove bootstrap_tour_stub
bzr revid: chm@openerp.com-20140320085606-qrghlkev6i9pu9bw
---
addons/website/static/src/js/website.tour.js | 20 ++++++--------------
1 file changed, 6 insertions(+), 14 deletions(-)
diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js
index c5ccd1f42c9..fc0dd513cf2 100644
--- a/addons/website/static/src/js/website.tour.js
+++ b/addons/website/static/src/js/website.tour.js
@@ -23,17 +23,6 @@ if (typeof website.Tour !== "undefined") {
// don't need template to use bootstrap Tour in automatic mode
if (typeof QWeb2 !== "undefined") {
website.add_template_file('/website/static/src/xml/website.tour.xml');
-
-}
-
-// don't need to use bootstrap Tour to launch an automatic tour
-function bootstrap_tour_stub () {
- if (typeof Tour === "undefined") {
- window.Tour = function Tour() {};
- Tour.prototype.addSteps = function () {};
- Tour.prototype.end = function () {};
- Tour.prototype.goto = function () {};
- }
}
if (website.EditorBar) {
@@ -150,7 +139,7 @@ website.Tour.registerSteps = function (tour) {
}
// rendering bootstrap tour and popover
- if (tour.mode != "test") {
+ if (tour.mode != "test" || typeof Tour !== "undefined") {
tour.tour = new Tour({
name: this.id,
storage: localStorage,
@@ -206,6 +195,7 @@ website.Tour.error = function (tour, step, message) {
+ '\nelement: ' + Boolean(!step.element || ($(step.element).size() && $(step.element).is(":visible") && !$(step.element).is(":hidden")))
+ '\nwaitNot: ' + Boolean(!step.waitNot || !$(step.waitNot).size())
+ '\nwaitFor: ' + Boolean(!step.waitFor || $(step.waitFor).size())
+ + "\nlocalStorage: " + localStorage.getItem("tour")
+ '\n\n' + $("body").html()
);
};
@@ -302,7 +292,9 @@ website.Tour.nextStep = function (tour, step, overlaps) {
// clear popover (fix for boostrap tour if the element is removed before destroy popover)
$(".popover.tour").remove();
// go to step in bootstrap tour
- tour.tour.goto(step.id);
+ if (tour.tour) {
+ tour.tour.goto(step.id);
+ }
step.onload();
var next = tour.steps[step.id+1];
@@ -349,7 +341,7 @@ website.Tour.autoNextStep = function (tour, step) {
if (!$element.size()) return;
if (step.snippet) {
-
+
website.Tour.autoDragAndDropSnippet($element);
} else if (step.sampleText) {
From abfccd8936da4f228919dcd3f59462c38d9efe41 Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Thu, 20 Mar 2014 16:15:42 +0100
Subject: [PATCH 03/26] [WIP] website tour: bootstrap-tour - v0.9.1
bzr revid: chm@openerp.com-20140320151542-blfr1rs1j24xanh8
---
.../lib/bootstrap-tour/bootstrap-tour.css | 44 +-
.../lib/bootstrap-tour/bootstrap-tour.js | 1057 ++++++++++-------
.../static/src/js/website.tour.banner.js | 3 -
addons/website/static/src/js/website.tour.js | 199 ++--
4 files changed, 755 insertions(+), 548 deletions(-)
mode change 100755 => 100644 addons/website/static/lib/bootstrap-tour/bootstrap-tour.css
mode change 100755 => 100644 addons/website/static/lib/bootstrap-tour/bootstrap-tour.js
diff --git a/addons/website/static/lib/bootstrap-tour/bootstrap-tour.css b/addons/website/static/lib/bootstrap-tour/bootstrap-tour.css
old mode 100755
new mode 100644
index 72c6e8cbab7..5449158e7f4
--- a/addons/website/static/lib/bootstrap-tour/bootstrap-tour.css
+++ b/addons/website/static/lib/bootstrap-tour/bootstrap-tour.css
@@ -1,37 +1,59 @@
+/* ===========================================================
+# bootstrap-tour - v0.9.1
+# http://bootstraptour.com
+# ==============================================================
+# Copyright 2012-2013 Ulrich Sossou
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+*/
.tour-backdrop {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
- z-index: 1009;
+ z-index: 1100;
background-color: #000;
opacity: 0.8;
}
.tour-step-backdrop {
position: relative;
- z-index: 1011;
+ z-index: 1101;
+ background: inherit;
}
.tour-step-background {
position: absolute;
- z-index: 1010;
- background: #fff;
+ z-index: 1100;
+ background: inherit;
border-radius: 6px;
}
+.popover[class*="tour-"] {
+ z-index: 1100;
+}
.popover[class*="tour-"] .popover-navigation {
padding: 9px 14px;
}
-.popover[class*="tour-"] .popover-navigation *[data-role=end] {
+.popover[class*="tour-"] .popover-navigation *[data-role="end"] {
float: right;
}
-.popover[class*="tour-"] .popover-navigation *[data-role=prev],
-.popover[class*="tour-"] .popover-navigation *[data-role=next],
-.popover[class*="tour-"] .popover-navigation *[data-role=end] {
+.popover[class*="tour-"] .popover-navigation *[data-role="prev"],
+.popover[class*="tour-"] .popover-navigation *[data-role="next"],
+.popover[class*="tour-"] .popover-navigation *[data-role="end"] {
cursor: pointer;
}
-.popover[class*="tour-"] .popover-navigation *[data-role=prev].disabled,
-.popover[class*="tour-"] .popover-navigation *[data-role=next].disabled,
-.popover[class*="tour-"] .popover-navigation *[data-role=end].disabled {
+.popover[class*="tour-"] .popover-navigation *[data-role="prev"].disabled,
+.popover[class*="tour-"] .popover-navigation *[data-role="next"].disabled,
+.popover[class*="tour-"] .popover-navigation *[data-role="end"].disabled {
cursor: default;
}
.popover[class*="tour-"].orphan {
diff --git a/addons/website/static/lib/bootstrap-tour/bootstrap-tour.js b/addons/website/static/lib/bootstrap-tour/bootstrap-tour.js
old mode 100755
new mode 100644
index 8b45d6da9ee..a0172c718c0
--- a/addons/website/static/lib/bootstrap-tour/bootstrap-tour.js
+++ b/addons/website/static/lib/bootstrap-tour/bootstrap-tour.js
@@ -1,5 +1,5 @@
/* ===========================================================
-# bootstrap-tour - v0.6.1
+# bootstrap-tour - v0.9.1
# http://bootstraptour.com
# ==============================================================
# Copyright 2012-2013 Ulrich Sossou
@@ -16,220 +16,233 @@
# See the License for the specific language governing permissions and
# limitations under the License.
*/
-(function() {
- (function($, window) {
- var Tour, document;
- document = window.document;
- Tour = (function() {
- function Tour(options) {
- this._options = $.extend({
- name: "tour",
- container: "body",
- keyboard: true,
- storage: window.localStorage,
- debug: false,
- backdrop: false,
- redirect: true,
- orphan: false,
- basePath: "",
- template: "",
- afterSetState: function(key, value) {},
- afterGetState: function(key, value) {},
- afterRemoveState: function(key) {},
- onStart: function(tour) {},
- onEnd: function(tour) {},
- onShow: function(tour) {},
- onShown: function(tour) {},
- onHide: function(tour) {},
- onHidden: function(tour) {},
- onNext: function(tour) {},
- onPrev: function(tour) {}
- }, options);
- this._steps = [];
- this.setCurrentStep();
- this.backdrop = {
- overlay: null,
- $element: null,
- $background: null
- };
+(function($, window) {
+ var Tour, document;
+ document = window.document;
+ Tour = (function() {
+ function Tour(options) {
+ this._options = $.extend({
+ name: "tour",
+ steps: [],
+ container: "body",
+ keyboard: true,
+ storage: window.localStorage,
+ debug: false,
+ backdrop: false,
+ redirect: true,
+ orphan: false,
+ duration: false,
+ basePath: "",
+ template: "
",
+ afterSetState: function(key, value) {},
+ afterGetState: function(key, value) {},
+ afterRemoveState: function(key) {},
+ onStart: function(tour) {},
+ onEnd: function(tour) {},
+ onShow: function(tour) {},
+ onShown: function(tour) {},
+ onHide: function(tour) {},
+ onHidden: function(tour) {},
+ onNext: function(tour) {},
+ onPrev: function(tour) {},
+ onPause: function(tour, duration) {},
+ onResume: function(tour, duration) {}
+ }, options);
+ this._force = false;
+ this._inited = false;
+ this.backdrop = {
+ overlay: null,
+ $element: null,
+ $background: null,
+ backgroundShown: false,
+ overlayElementShown: false
+ };
+ this;
+ }
+
+ Tour.prototype.addSteps = function(steps) {
+ var step, _i, _len;
+ for (_i = 0, _len = steps.length; _i < _len; _i++) {
+ step = steps[_i];
+ this.addStep(step);
}
+ return this;
+ };
- Tour.prototype.setState = function(key, value) {
- var keyName;
- if (this._options.storage) {
- keyName = "" + this._options.name + "_" + key;
- this._options.storage.setItem(keyName, value);
- return this._options.afterSetState(keyName, value);
- } else {
- if (this._state == null) {
- this._state = {};
- }
- return this._state[key] = value;
- }
- };
+ Tour.prototype.addStep = function(step) {
+ this._options.steps.push(step);
+ return this;
+ };
- Tour.prototype.removeState = function(key) {
- var keyName;
- if (this._options.storage) {
- keyName = "" + this._options.name + "_" + key;
- this._options.storage.removeItem(keyName);
- return this._options.afterRemoveState(keyName);
- } else {
- if (this._state != null) {
- return delete this._state[key];
- }
- }
- };
+ Tour.prototype.getStep = function(i) {
+ if (this._options.steps[i] != null) {
+ return $.extend({
+ id: "step-" + i,
+ path: "",
+ placement: "right",
+ title: "",
+ content: "",
+ next: i === this._options.steps.length - 1 ? -1 : i + 1,
+ prev: i - 1,
+ animation: true,
+ container: this._options.container,
+ backdrop: this._options.backdrop,
+ redirect: this._options.redirect,
+ orphan: this._options.orphan,
+ duration: this._options.duration,
+ template: this._options.template,
+ onShow: this._options.onShow,
+ onShown: this._options.onShown,
+ onHide: this._options.onHide,
+ onHidden: this._options.onHidden,
+ onNext: this._options.onNext,
+ onPrev: this._options.onPrev,
+ onPause: this._options.onPause,
+ onResume: this._options.onResume
+ }, this._options.steps[i]);
+ }
+ };
- Tour.prototype.getState = function(key) {
- var keyName, value;
- if (this._options.storage) {
- keyName = "" + this._options.name + "_" + key;
- value = this._options.storage.getItem(keyName);
- } else {
- if (this._state != null) {
- value = this._state[key];
- }
- }
- if (value === void 0 || value === "null") {
- value = null;
- }
- this._options.afterGetState(key, value);
- return value;
- };
-
- Tour.prototype.addSteps = function(steps) {
- var step, _i, _len, _results;
- _results = [];
- for (_i = 0, _len = steps.length; _i < _len; _i++) {
- step = steps[_i];
- _results.push(this.addStep(step));
- }
- return _results;
- };
-
- Tour.prototype.addStep = function(step) {
- return this._steps.push(step);
- };
-
- Tour.prototype.getStep = function(i) {
- if (this._steps[i] != null) {
- return $.extend({
- id: "step-" + i,
- path: "",
- placement: "right",
- title: "",
- content: "",
- next: i === this._steps.length - 1 ? -1 : i + 1,
- prev: i - 1,
- animation: true,
- container: this._options.container,
- backdrop: this._options.backdrop,
- redirect: this._options.redirect,
- orphan: this._options.orphan,
- template: this._options.template,
- onShow: this._options.onShow,
- onShown: this._options.onShown,
- onHide: this._options.onHide,
- onHidden: this._options.onHidden,
- onNext: this._options.onNext,
- onPrev: this._options.onPrev
- }, this._steps[i]);
- }
- };
-
- Tour.prototype.start = function(force) {
- var promise,
- _this = this;
- if (force == null) {
- force = false;
- }
- if (this.ended() && !force) {
- return this._debug("Tour ended, start prevented.");
- }
- $(document).off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role=next]").on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role=next]:not(.disabled)", function(e) {
- e.preventDefault();
- return _this.next();
- });
- $(document).off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role=prev]").on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role=prev]:not(.disabled)", function(e) {
- e.preventDefault();
- return _this.prev();
- });
- $(document).off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role=end]").on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role=end]", function(e) {
- e.preventDefault();
- return _this.end();
- });
- this._onResize(function() {
+ Tour.prototype.init = function(force) {
+ this._force = force;
+ if (this.ended()) {
+ this._debug("Tour ended, init prevented.");
+ return this;
+ }
+ this.setCurrentStep();
+ this._initMouseNavigation();
+ this._initKeyboardNavigation();
+ this._onResize((function(_this) {
+ return function() {
return _this.showStep(_this._current);
- });
- this._setupKeyboardNavigation();
+ };
+ })(this));
+ if (this._current !== null) {
+ this.showStep(this._current);
+ }
+ this._inited = true;
+ return this;
+ };
+
+ Tour.prototype.start = function(force) {
+ var promise;
+ if (force == null) {
+ force = false;
+ }
+ if (!this._inited) {
+ this.init(force);
+ }
+ if (this._current === null) {
promise = this._makePromise(this._options.onStart != null ? this._options.onStart(this) : void 0);
- return this._callOnPromiseDone(promise, this.showStep, this._current);
- };
+ this._callOnPromiseDone(promise, this.showStep, 0);
+ }
+ return this;
+ };
- Tour.prototype.next = function() {
- var promise;
- if (this.ended()) {
- return this._debug("Tour ended, next prevented.");
- }
- promise = this.hideStep(this._current);
- return this._callOnPromiseDone(promise, this._showNextStep);
- };
+ Tour.prototype.next = function() {
+ var promise;
+ promise = this.hideStep(this._current);
+ return this._callOnPromiseDone(promise, this._showNextStep);
+ };
- Tour.prototype.prev = function() {
- var promise;
- if (this.ended()) {
- return this._debug("Tour ended, prev prevented.");
- }
- promise = this.hideStep(this._current);
- return this._callOnPromiseDone(promise, this._showPrevStep);
- };
+ Tour.prototype.prev = function() {
+ var promise;
+ promise = this.hideStep(this._current);
+ return this._callOnPromiseDone(promise, this._showPrevStep);
+ };
- Tour.prototype.goto = function(i) {
- var promise;
- if (this.ended()) {
- return this._debug("Tour ended, goto prevented.");
- }
- promise = this.hideStep(this._current);
- return this._callOnPromiseDone(promise, this.showStep, i);
- };
+ Tour.prototype.goTo = function(i) {
+ var promise;
+ promise = this.hideStep(this._current);
+ return this._callOnPromiseDone(promise, this.showStep, i);
+ };
- Tour.prototype.end = function() {
- var endHelper, hidePromise,
- _this = this;
- endHelper = function(e) {
+ Tour.prototype.end = function() {
+ var endHelper, promise;
+ endHelper = (function(_this) {
+ return function(e) {
$(document).off("click.tour-" + _this._options.name);
$(document).off("keyup.tour-" + _this._options.name);
$(window).off("resize.tour-" + _this._options.name);
- _this.setState("end", "yes");
+ _this._setState("end", "yes");
+ _this._inited = false;
+ _this._force = false;
+ _this._clearTimer();
if (_this._options.onEnd != null) {
return _this._options.onEnd(_this);
}
};
- hidePromise = this.hideStep(this._current);
- return this._callOnPromiseDone(hidePromise, endHelper);
- };
+ })(this);
+ promise = this.hideStep(this._current);
+ return this._callOnPromiseDone(promise, endHelper);
+ };
- Tour.prototype.ended = function() {
- return !!this.getState("end");
- };
+ Tour.prototype.ended = function() {
+ return !this._force && !!this._getState("end");
+ };
- Tour.prototype.restart = function() {
- this.removeState("current_step");
- this.removeState("end");
- this.setCurrentStep(0);
- return this.start();
- };
+ Tour.prototype.restart = function() {
+ this._removeState("current_step");
+ this._removeState("end");
+ this.setCurrentStep(0);
+ return this.start();
+ };
- Tour.prototype.hideStep = function(i) {
- var hideStepHelper, promise, step,
- _this = this;
- step = this.getStep(i);
- promise = this._makePromise(step.onHide != null ? step.onHide(this, i) : void 0);
- hideStepHelper = function(e) {
+ Tour.prototype.pause = function() {
+ var step;
+ step = this.getStep(this._current);
+ if (!(step && step.duration)) {
+ return this;
+ }
+ this._paused = true;
+ this._duration -= new Date().getTime() - this._start;
+ window.clearTimeout(this._timer);
+ this._debug("Paused/Stopped step " + (this._current + 1) + " timer (" + this._duration + " remaining).");
+ if (step.onPause != null) {
+ return step.onPause(this, this._duration);
+ }
+ };
+
+ Tour.prototype.resume = function() {
+ var step;
+ step = this.getStep(this._current);
+ if (!(step && step.duration)) {
+ return this;
+ }
+ this._paused = false;
+ this._start = new Date().getTime();
+ this._duration = this._duration || step.duration;
+ this._timer = window.setTimeout((function(_this) {
+ return function() {
+ if (_this._isLast()) {
+ return _this.next();
+ } else {
+ return _this.end();
+ }
+ };
+ })(this), this._duration);
+ this._debug("Started step " + (this._current + 1) + " timer with duration " + this._duration);
+ if ((step.onResume != null) && this._duration !== step.duration) {
+ return step.onResume(this, this._duration);
+ }
+ };
+
+ Tour.prototype.hideStep = function(i) {
+ var hideStepHelper, promise, step;
+ step = this.getStep(i);
+ if (!step) {
+ return;
+ }
+ this._clearTimer();
+ promise = this._makePromise(step.onHide != null ? step.onHide(this, i) : void 0);
+ hideStepHelper = (function(_this) {
+ return function(e) {
var $element;
- $element = _this._isOrphan(step) ? $("body") : $(step.element);
- $element.popover("destroy");
+ $element = $(step.element);
+ if (!($element.data("bs.popover") || $element.data("popover"))) {
+ $element = $("body");
+ }
+ $element.popover("destroy").removeClass("tour-" + _this._options.name + "-element tour-" + _this._options.name + "-" + i + "-element");
if (step.reflex) {
$element.css("cursor", "").off("click.tour-" + _this._options.name);
}
@@ -240,23 +253,37 @@
return step.onHidden(_this);
}
};
- this._callOnPromiseDone(promise, hideStepHelper);
- return promise;
- };
+ })(this);
+ this._callOnPromiseDone(promise, hideStepHelper);
+ return promise;
+ };
- Tour.prototype.showStep = function(i) {
- var promise, showStepHelper, skipToPrevious, step,
- _this = this;
- step = this.getStep(i);
- if (!step) {
- return;
- }
- skipToPrevious = i < this._current;
- promise = this._makePromise(step.onShow != null ? step.onShow(this, i) : void 0);
- showStepHelper = function(e) {
+ Tour.prototype.showStep = function(i) {
+ var promise, showStepHelper, skipToPrevious, step;
+ if (this.ended()) {
+ this._debug("Tour ended, showStep prevented.");
+ return this;
+ }
+ step = this.getStep(i);
+ if (!step) {
+ return;
+ }
+ skipToPrevious = i < this._current;
+ promise = this._makePromise(step.onShow != null ? step.onShow(this, i) : void 0);
+ showStepHelper = (function(_this) {
+ return function(e) {
var current_path, path;
_this.setCurrentStep(i);
- path = $.isFunction(step.path) ? step.path.call() : _this._options.basePath + step.path;
+ path = (function() {
+ switch ({}.toString.call(step.path)) {
+ case "[object Function]":
+ return step.path();
+ case "[object String]":
+ return this._options.basePath + step.path;
+ default:
+ return step.path;
+ }
+ }).call(_this);
current_path = [document.location.pathname, document.location.hash].join("");
if (_this._isRedirect(path, current_path)) {
_this._redirect(step, path);
@@ -277,283 +304,413 @@
if (step.backdrop) {
_this._showBackdrop(!_this._isOrphan(step) ? step.element : void 0);
}
- _this._showPopover(step, i);
- if (step.onShown != null) {
- step.onShown(_this);
+ _this._scrollIntoView(step.element, function() {
+ if ((step.element != null) && step.backdrop) {
+ _this._showOverlayElement(step.element);
+ }
+ _this._showPopover(step, i);
+ if (step.onShown != null) {
+ step.onShown(_this);
+ }
+ return _this._debug("Step " + (_this._current + 1) + " of " + _this._options.steps.length);
+ });
+ if (step.duration) {
+ return _this.resume();
}
- return _this._debug("Step " + (_this._current + 1) + " of " + _this._steps.length);
};
- return this._callOnPromiseDone(promise, showStepHelper);
- };
+ })(this);
+ this._callOnPromiseDone(promise, showStepHelper);
+ return promise;
+ };
- Tour.prototype.setCurrentStep = function(value) {
- if (value != null) {
- this._current = value;
- return this.setState("current_step", value);
- } else {
- this._current = this.getState("current_step");
- return this._current = this._current === null ? 0 : parseInt(this._current, 10);
+ Tour.prototype.getCurrentStep = function() {
+ return this._current;
+ };
+
+ Tour.prototype.setCurrentStep = function(value) {
+ if (value != null) {
+ this._current = value;
+ this._setState("current_step", value);
+ } else {
+ this._current = this._getState("current_step");
+ this._current = this._current === null ? null : parseInt(this._current, 10);
+ }
+ return this;
+ };
+
+ Tour.prototype._setState = function(key, value) {
+ var e, keyName;
+ if (this._options.storage) {
+ keyName = "" + this._options.name + "_" + key;
+ try {
+ this._options.storage.setItem(keyName, value);
+ } catch (_error) {
+ e = _error;
+ if (e.code === DOMException.QUOTA_EXCEEDED_ERR) {
+ this.debug("LocalStorage quota exceeded. State storage failed.");
+ }
}
- };
+ return this._options.afterSetState(keyName, value);
+ } else {
+ if (this._state == null) {
+ this._state = {};
+ }
+ return this._state[key] = value;
+ }
+ };
- Tour.prototype._showNextStep = function() {
- var promise, showNextStepHelper, step,
- _this = this;
- step = this.getStep(this._current);
- showNextStepHelper = function(e) {
+ Tour.prototype._removeState = function(key) {
+ var keyName;
+ if (this._options.storage) {
+ keyName = "" + this._options.name + "_" + key;
+ this._options.storage.removeItem(keyName);
+ return this._options.afterRemoveState(keyName);
+ } else {
+ if (this._state != null) {
+ return delete this._state[key];
+ }
+ }
+ };
+
+ Tour.prototype._getState = function(key) {
+ var keyName, value;
+ if (this._options.storage) {
+ keyName = "" + this._options.name + "_" + key;
+ value = this._options.storage.getItem(keyName);
+ } else {
+ if (this._state != null) {
+ value = this._state[key];
+ }
+ }
+ if (value === void 0 || value === "null") {
+ value = null;
+ }
+ this._options.afterGetState(key, value);
+ return value;
+ };
+
+ Tour.prototype._showNextStep = function() {
+ var promise, showNextStepHelper, step;
+ step = this.getStep(this._current);
+ showNextStepHelper = (function(_this) {
+ return function(e) {
return _this.showStep(step.next);
};
- promise = this._makePromise((step.onNext != null ? step.onNext(this) : void 0));
- return this._callOnPromiseDone(promise, showNextStepHelper);
- };
+ })(this);
+ promise = this._makePromise(step.onNext != null ? step.onNext(this) : void 0);
+ return this._callOnPromiseDone(promise, showNextStepHelper);
+ };
- Tour.prototype._showPrevStep = function() {
- var promise, showPrevStepHelper, step,
- _this = this;
- step = this.getStep(this._current);
- showPrevStepHelper = function(e) {
+ Tour.prototype._showPrevStep = function() {
+ var promise, showPrevStepHelper, step;
+ step = this.getStep(this._current);
+ showPrevStepHelper = (function(_this) {
+ return function(e) {
return _this.showStep(step.prev);
};
- promise = this._makePromise((step.onPrev != null ? step.onPrev(this) : void 0));
- return this._callOnPromiseDone(promise, showPrevStepHelper);
- };
+ })(this);
+ promise = this._makePromise(step.onPrev != null ? step.onPrev(this) : void 0);
+ return this._callOnPromiseDone(promise, showPrevStepHelper);
+ };
- Tour.prototype._debug = function(text) {
- if (this._options.debug) {
- return window.console.log("Bootstrap Tour '" + this._options.name + "' | " + text);
- }
- };
+ Tour.prototype._debug = function(text) {
+ if (this._options.debug) {
+ return window.console.log("Bootstrap Tour '" + this._options.name + "' | " + text);
+ }
+ };
- Tour.prototype._isRedirect = function(path, currentPath) {
- return (path != null) && path !== "" && path.replace(/\?.*$/, "").replace(/\/?$/, "") !== currentPath.replace(/\/?$/, "");
- };
+ Tour.prototype._isRedirect = function(path, currentPath) {
+ return (path != null) && path !== "" && ((toString.call(path) === "[object RegExp]" && !path.test(currentPath)) || (toString.call(path) === "[object String]" && path.replace(/\?.*$/, "").replace(/\/?$/, "") !== currentPath.replace(/\/?$/, "")));
+ };
- Tour.prototype._redirect = function(step, path) {
- if ($.isFunction(step.redirect)) {
- return step.redirect.call(this, path);
- } else if (step.redirect === true) {
- this._debug("Redirect to " + path);
- return document.location.href = path;
- }
- };
+ Tour.prototype._redirect = function(step, path) {
+ if ($.isFunction(step.redirect)) {
+ return step.redirect.call(this, path);
+ } else if (step.redirect === true) {
+ this._debug("Redirect to " + path);
+ return document.location.href = path;
+ }
+ };
- Tour.prototype._isOrphan = function(step) {
- return (step.element == null) || !$(step.element).length || $(step.element).is(":hidden");
- };
+ Tour.prototype._isOrphan = function(step) {
+ return (step.element == null) || !$(step.element).length || $(step.element).is(":hidden") && ($(step.element)[0].namespaceURI !== "http://www.w3.org/2000/svg");
+ };
- Tour.prototype._showPopover = function(step, i) {
- var $element, $navigation, $template, $tip, isOrphan, options,
- _this = this;
- options = $.extend({}, this._options);
- $template = $.isFunction(step.template) ? $(step.template(i, step)) : $(step.template);
- $navigation = $template.find(".popover-navigation");
- isOrphan = this._isOrphan(step);
- if (isOrphan) {
- step.element = "body";
- step.placement = "top";
- $template = $template.addClass("orphan");
- }
- $element = $(step.element);
- $template.addClass("tour-" + this._options.name);
- if (step.options) {
- $.extend(options, step.options);
- }
- if (step.reflex) {
- $element.css("cursor", "pointer").on("click.tour-" + this._options.name, function(e) {
- if (_this._current < _this._steps.length - 1) {
+ Tour.prototype._isLast = function() {
+ return this._current < this._options.steps.length - 1;
+ };
+
+ Tour.prototype._showPopover = function(step, i) {
+ var $element, $navigation, $template, $tip, isOrphan, options;
+ options = $.extend({}, this._options);
+ $template = $.isFunction(step.template) ? $(step.template(i, step)) : $(step.template);
+ $navigation = $template.find(".popover-navigation");
+ isOrphan = this._isOrphan(step);
+ if (isOrphan) {
+ step.element = "body>*:last";
+ step.placement = "top";
+ $template = $template.addClass("orphan");
+ }
+ $element = $(step.element);
+ $template.addClass("tour-" + this._options.name + " tour-" + this._options.name + "-" + i);
+ $element.addClass("tour-" + this._options.name + "-element tour-" + this._options.name + "-" + i + "-element");
+ if (step.options) {
+ $.extend(options, step.options);
+ }
+ if (step.reflex) {
+ $element.css("cursor", "pointer").on("click.tour-" + this._options.name, (function(_this) {
+ return function() {
+ if (_this._isLast()) {
return _this.next();
} else {
return _this.end();
}
- });
- }
- if (step.prev < 0) {
- $navigation.find("*[data-role=prev]").addClass("disabled");
- }
- if (step.next < 0) {
- $navigation.find("*[data-role=next]").addClass("disabled");
- }
- step.template = $template.clone().wrap("").parent().html();
- $element.popover({
- placement: step.placement,
- trigger: "manual",
- title: step.title,
- content: step.content,
- html: true,
- animation: step.animation,
- container: step.container,
- template: step.template,
- selector: step.element
- }).popover("show");
- $tip = $element.data("bs.popover") ? $element.data("bs.popover").tip() : $element.data("popover").tip();
- $tip.attr("id", step.id);
- this._scrollIntoView($tip);
- this._reposition($tip, step);
- if (isOrphan) {
- return this._center($tip);
- }
- };
+ };
+ })(this));
+ }
+ if (step.prev < 0) {
+ $navigation.find("[data-role='prev']").addClass("disabled");
+ }
+ if (step.next < 0) {
+ $navigation.find("[data-role='next']").addClass("disabled");
+ }
+ if (!step.duration) {
+ $navigation.find("[data-role='pause-resume']").remove();
+ }
+ step.template = $template.clone().wrap("
").parent().html();
+ $element.popover({
+ placement: step.placement,
+ trigger: "manual",
+ title: step.title,
+ content: step.content,
+ html: true,
+ animation: step.animation,
+ container: step.container,
+ template: step.template,
+ selector: step.element
+ }).popover("show");
+ $tip = $element.data("bs.popover") ? $element.data("bs.popover").tip() : $element.data("popover").tip();
+ $tip.attr("id", step.id);
+ this._reposition($tip, step);
+ if (isOrphan) {
+ return this._center($tip);
+ }
+ };
- Tour.prototype._reposition = function($tip, step) {
- var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset;
- offsetWidth = $tip[0].offsetWidth;
- offsetHeight = $tip[0].offsetHeight;
- tipOffset = $tip.offset();
- originalLeft = tipOffset.left;
- originalTop = tipOffset.top;
- offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight();
- if (offsetBottom < 0) {
- tipOffset.top = tipOffset.top + offsetBottom;
+ Tour.prototype._reposition = function($tip, step) {
+ var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset;
+ offsetWidth = $tip[0].offsetWidth;
+ offsetHeight = $tip[0].offsetHeight;
+ tipOffset = $tip.offset();
+ originalLeft = tipOffset.left;
+ originalTop = tipOffset.top;
+ offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight();
+ if (offsetBottom < 0) {
+ tipOffset.top = tipOffset.top + offsetBottom;
+ }
+ offsetRight = $("html").outerWidth() - tipOffset.left - $tip.outerWidth();
+ if (offsetRight < 0) {
+ tipOffset.left = tipOffset.left + offsetRight;
+ }
+ if (tipOffset.top < 0) {
+ tipOffset.top = 0;
+ }
+ if (tipOffset.left < 0) {
+ tipOffset.left = 0;
+ }
+ $tip.offset(tipOffset);
+ if (step.placement === "bottom" || step.placement === "top") {
+ if (originalLeft !== tipOffset.left) {
+ return this._replaceArrow($tip, (tipOffset.left - originalLeft) * 2, offsetWidth, "left");
}
- offsetRight = $("html").outerWidth() - tipOffset.left - $tip.outerWidth();
- if (offsetRight < 0) {
- tipOffset.left = tipOffset.left + offsetRight;
+ } else {
+ if (originalTop !== tipOffset.top) {
+ return this._replaceArrow($tip, (tipOffset.top - originalTop) * 2, offsetHeight, "top");
}
- if (tipOffset.top < 0) {
- tipOffset.top = 0;
- }
- if (tipOffset.left < 0) {
- tipOffset.left = 0;
- }
- $tip.offset(tipOffset);
- if (step.placement === "bottom" || step.placement === "top") {
- if (originalLeft !== tipOffset.left) {
- return this._replaceArrow($tip, (tipOffset.left - originalLeft) * 2, offsetWidth, "left");
+ }
+ };
+
+ Tour.prototype._center = function($tip) {
+ return $tip.css("top", $(window).outerHeight() / 2 - $tip.outerHeight() / 2);
+ };
+
+ Tour.prototype._replaceArrow = function($tip, delta, dimension, position) {
+ return $tip.find(".arrow").css(position, delta ? 50 * (1 - delta / dimension) + "%" : "");
+ };
+
+ Tour.prototype._scrollIntoView = function(element, callback) {
+ var $element, $window, counter, offsetTop, scrollTop, windowHeight;
+ $element = $(element);
+ if (!$element.length) {
+ return callback();
+ }
+ $window = $(window);
+ offsetTop = $element.offset().top;
+ windowHeight = $window.height();
+ scrollTop = Math.max(0, offsetTop - (windowHeight / 2));
+ this._debug("Scroll into view. ScrollTop: " + scrollTop + ". Element offset: " + offsetTop + ". Window height: " + windowHeight + ".");
+ counter = 0;
+ return $("body,html").stop(true, true).animate({
+ scrollTop: Math.ceil(scrollTop)
+ }, (function(_this) {
+ return function() {
+ if (++counter === 2) {
+ callback();
+ return _this._debug("Scroll into view. Animation end element offset: " + ($element.offset().top) + ". Window height: " + ($window.height()) + ".");
}
+ };
+ })(this));
+ };
+
+ Tour.prototype._onResize = function(callback, timeout) {
+ return $(window).on("resize.tour-" + this._options.name, function() {
+ clearTimeout(timeout);
+ return timeout = setTimeout(callback, 100);
+ });
+ };
+
+ Tour.prototype._initMouseNavigation = function() {
+ var _this;
+ _this = this;
+ return $(document).off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']:not(.disabled)").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='next']:not(.disabled)").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']").on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='next']:not(.disabled)", (function(_this) {
+ return function(e) {
+ e.preventDefault();
+ return _this.next();
+ };
+ })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']:not(.disabled)", (function(_this) {
+ return function(e) {
+ e.preventDefault();
+ return _this.prev();
+ };
+ })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']", (function(_this) {
+ return function(e) {
+ e.preventDefault();
+ return _this.end();
+ };
+ })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']", function(e) {
+ var $this;
+ e.preventDefault();
+ $this = $(this);
+ $this.text(_this._paused ? $this.data("pause-text") : $this.data("resume-text"));
+ if (_this._paused) {
+ return _this.resume();
} else {
- if (originalTop !== tipOffset.top) {
- return this._replaceArrow($tip, (tipOffset.top - originalTop) * 2, offsetHeight, "top");
- }
+ return _this.pause();
}
- };
+ });
+ };
- Tour.prototype._center = function($tip) {
- return $tip.css("top", $(window).outerHeight() / 2 - $tip.outerHeight() / 2);
- };
-
- Tour.prototype._replaceArrow = function($tip, delta, dimension, position) {
- return $tip.find(".arrow").css(position, delta ? 50 * (1 - delta / dimension) + "%" : "");
- };
-
- Tour.prototype._scrollIntoView = function(tip) {
- return $("html, body").stop().animate({
- scrollTop: Math.ceil(tip.offset().top - ($(window).height() / 2))
- });
- };
-
- Tour.prototype._onResize = function(callback, timeout) {
- return $(window).on("resize.tour-" + this._options.name, function() {
- clearTimeout(timeout);
- return timeout = setTimeout(callback, 100);
- });
- };
-
- Tour.prototype._setupKeyboardNavigation = function() {
- var _this = this;
- if (this._options.keyboard) {
- return $(document).on("keyup.tour-" + this._options.name, function(e) {
- if (!e.which) {
- return;
- }
- switch (e.which) {
- case 39:
- e.preventDefault();
- if (_this._current < _this._steps.length - 1) {
- return _this.next();
- } else {
- return _this.end();
- }
- break;
- case 37:
- e.preventDefault();
- if (_this._current > 0) {
- return _this.prev();
- }
- break;
- case 27:
- e.preventDefault();
+ Tour.prototype._initKeyboardNavigation = function() {
+ if (!this._options.keyboard) {
+ return;
+ }
+ return $(document).on("keyup.tour-" + this._options.name, (function(_this) {
+ return function(e) {
+ if (!e.which) {
+ return;
+ }
+ switch (e.which) {
+ case 39:
+ e.preventDefault();
+ if (_this._isLast()) {
+ return _this.next();
+ } else {
return _this.end();
- }
- });
- }
- };
+ }
+ break;
+ case 37:
+ e.preventDefault();
+ if (_this._current > 0) {
+ return _this.prev();
+ }
+ break;
+ case 27:
+ e.preventDefault();
+ return _this.end();
+ }
+ };
+ })(this));
+ };
- Tour.prototype._makePromise = function(result) {
- if (result && $.isFunction(result.then)) {
- return result;
- } else {
- return null;
- }
- };
+ Tour.prototype._makePromise = function(result) {
+ if (result && $.isFunction(result.then)) {
+ return result;
+ } else {
+ return null;
+ }
+ };
- Tour.prototype._callOnPromiseDone = function(promise, cb, arg) {
- var _this = this;
- if (promise) {
- return promise.then(function(e) {
+ Tour.prototype._callOnPromiseDone = function(promise, cb, arg) {
+ if (promise) {
+ return promise.then((function(_this) {
+ return function(e) {
return cb.call(_this, arg);
- });
- } else {
- return cb.call(this, arg);
- }
- };
+ };
+ })(this));
+ } else {
+ return cb.call(this, arg);
+ }
+ };
- Tour.prototype._showBackdrop = function(element) {
- if (this.backdrop.overlay !== null) {
- return;
- }
- this._showOverlay();
- if (element != null) {
- return this._showOverlayElement(element);
- }
- };
+ Tour.prototype._showBackdrop = function(element) {
+ if (this.backdrop.backgroundShown) {
+ return;
+ }
+ this.backdrop = $("
", {
+ "class": "tour-backdrop"
+ });
+ this.backdrop.backgroundShown = true;
+ return $("body").append(this.backdrop);
+ };
- Tour.prototype._hideBackdrop = function() {
- if (this.backdrop.overlay === null) {
- return;
- }
- if (this.backdrop.$element) {
- this._hideOverlayElement();
- }
- return this._hideOverlay();
- };
+ Tour.prototype._hideBackdrop = function() {
+ this._hideOverlayElement();
+ return this._hideBackground();
+ };
- Tour.prototype._showOverlay = function() {
- this.backdrop = $("
", {
- "class": "tour-backdrop"
- });
- return $("body").append(this.backdrop);
- };
+ Tour.prototype._hideBackground = function() {
+ this.backdrop.remove();
+ this.backdrop.overlay = null;
+ return this.backdrop.backgroundShown = false;
+ };
- Tour.prototype._hideOverlay = function() {
- this.backdrop.remove();
- return this.backdrop.overlay = null;
- };
+ Tour.prototype._showOverlayElement = function(element) {
+ var $background, $element, offset;
+ $element = $(element);
+ if (!$element || $element.length === 0 || this.backdrop.overlayElementShown) {
+ return;
+ }
+ this.backdrop.overlayElementShown = true;
+ $background = $("
");
+ offset = $element.offset();
+ offset.top = offset.top;
+ offset.left = offset.left;
+ $background.width($element.innerWidth()).height($element.innerHeight()).addClass("tour-step-background").offset(offset);
+ $element.addClass("tour-step-backdrop");
+ $("body").append($background);
+ this.backdrop.$element = $element;
+ return this.backdrop.$background = $background;
+ };
- Tour.prototype._showOverlayElement = function(element) {
- var $background, $element, offset;
- $element = $(element);
- $background = $("
");
- offset = $element.offset();
- offset.top = offset.top;
- offset.left = offset.left;
- $background.width($element.innerWidth()).height($element.innerHeight()).addClass("tour-step-background").offset(offset);
- $element.addClass("tour-step-backdrop");
- $("body").append($background);
- this.backdrop.$element = $element;
- return this.backdrop.$background = $background;
- };
+ Tour.prototype._hideOverlayElement = function() {
+ if (!this.backdrop.overlayElementShown) {
+ return;
+ }
+ this.backdrop.$element.removeClass("tour-step-backdrop");
+ this.backdrop.$background.remove();
+ this.backdrop.$element = null;
+ this.backdrop.$background = null;
+ return this.backdrop.overlayElementShown = false;
+ };
- Tour.prototype._hideOverlayElement = function() {
- this.backdrop.$element.removeClass("tour-step-backdrop");
- this.backdrop.$background.remove();
- this.backdrop.$element = null;
- return this.backdrop.$background = null;
- };
+ Tour.prototype._clearTimer = function() {
+ window.clearTimeout(this._timer);
+ this._timer = null;
+ return this._duration = null;
+ };
- return Tour;
+ return Tour;
- })();
- return window.Tour = Tour;
- })(jQuery, window);
-
-}).call(this);
+ })();
+ return window.Tour = Tour;
+})(jQuery, window);
diff --git a/addons/website/static/src/js/website.tour.banner.js b/addons/website/static/src/js/website.tour.banner.js
index 65099d03986..443405e2401 100644
--- a/addons/website/static/src/js/website.tour.banner.js
+++ b/addons/website/static/src/js/website.tour.banner.js
@@ -15,7 +15,6 @@
popover: { next: _t("Start Tutorial"), end: _t("Skip It") },
},
{
- waitNot: '.popover.tour',
element: 'button[data-action=edit]',
placement: 'bottom',
title: _t("Edit this page"),
@@ -52,7 +51,6 @@
popover: { next: _t("Continue") },
},
{
- waitNot: '.popover.tour',
element: 'button[data-action=snippet]',
placement: 'bottom',
title: _t("Add Another Block"),
@@ -81,7 +79,6 @@
popover: { next: _t("Continue") },
},
{
- waitNot: '.popover.tour',
element: 'a[data-action=show-mobile-preview]',
placement: 'bottom',
title: _t("Test Your Mobile Version"),
diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js
index fc0dd513cf2..df6108e0278 100644
--- a/addons/website/static/src/js/website.tour.js
+++ b/addons/website/static/src/js/website.tour.js
@@ -32,7 +32,7 @@ if (website.EditorBar) {
var self = this;
var menu = $('#help-menu');
_.each(website.Tour.tours, function (tour) {
- if (tour.mode != "tutorial") {
+ if (tour.mode === "test") {
return;
}
var $menuItem = $($.parseHTML('
'+tour.name+''));
@@ -90,16 +90,19 @@ website.Tour = {};
website.Tour.tours = {};
website.Tour.state = null;
website.Tour.register = function (tour) {
+ if (tour.mode !== "test") tour.mode = "tutorial";
website.Tour.tours[tour.id] = tour;
};
website.Tour.run = function (tour_id, mode) {
- if (localStorage.getItem("tour")) { // only one test running
+ if (localStorage.getItem("tour") && mode === "test") { // only one test running
return;
}
var tour = website.Tour.tours[tour_id];
- website.Tour.save_state(tour.id, mode || tour.mode, 0);
- if (tour.path) {
+ website.Tour.saveState(tour.id, mode || tour.mode, 0);
+ if (tour.path && !window.location.href.match(new RegExp("("+website.Tour.getLang()+")?"+tour.path+"#?$", "i"))) {
window.location.href = "/"+website.Tour.getLang()+tour.path;
+ } else {
+ website.Tour.running();
}
};
website.Tour.registerSteps = function (tour) {
@@ -114,48 +117,82 @@ website.Tour.registerSteps = function (tour) {
if (!step.waitNot && index > 0 && tour.steps[index-1] &&
tour.steps[index-1].popover && tour.steps[index-1].popover.next) {
- step.waitNot = '.popover.tour:visible';
+ step.waitNot = '.popover.tour.fade.in:visible';
}
if (!step.waitFor && index > 0 && tour.steps[index-1].snippet) {
step.waitFor = '.oe_overlay_options .oe_options:visible';
}
- if (!step.element) step.orphan = true;
-
- var snippet = step.element.match(/#oe_snippets (.*) \.oe_snippet_thumbnail/);
+ var snippet = step.element && step.element.match(/#oe_snippets (.*) \.oe_snippet_thumbnail/);
if (snippet) {
step.snippet = snippet[1];
} else if (step.snippet) {
step.element = '#oe_snippets '+step.snippet+' .oe_snippet_thumbnail';
}
+
+ if (!step.element) step.orphan = true;
}
if (tour.steps[index-1] &&
tour.steps[index-1].popover && tour.steps[index-1].popover.next) {
var step = {
- step_id: index,
- waitNot: '.popover.tour:visible'
+ id: index,
+ waitNot: '.popover.tour.fade.in:visible'
};
tour.steps.push(step);
}
// rendering bootstrap tour and popover
- if (tour.mode != "test" || typeof Tour !== "undefined") {
+ if (tour.mode !== "test" || typeof Tour !== "undefined") {
tour.tour = new Tour({
- name: this.id,
+ debug: true,
+ name: tour.id,
storage: localStorage,
keyboard: false,
- template: this.popover(),
+ template: website.Tour.popover(),
onHide: function () {
window.scrollTo(0, 0);
}
});
+
for (var index=0, len=tour.steps.length; index
-1) {
- tour_id = window.location.href.match(/#tutorial\.(.*)=true/)[1];
- mode = "tutorial";
- step_id = 0;
+website.Tour.getState = function () {
+ var state = JSON.parse(localStorage.getItem("tour") || 'false') || {};
+ var tour_id,mode,step_id;
+ if (!state.id && window.location.href.indexOf("#tutorial.") > -1) {
+ state = {
+ "id": window.location.href.match(/#tutorial\.(.*)=true/)[1],
+ "mode": "tutorial",
+ "step_id": 0
+ };
}
- if (!tour_id) {
+ if (!state.id) {
return;
}
- var tour = website.Tour.tours[tour_id];
- return {'tour': tour, 'tour_id': tour_id, 'mode': mode, 'step_id': step_id};
+ state.tour = website.Tour.tours[state.id];
+ state.step = state.tour.steps[state.step_id];
+ return state;
};
website.Tour.error = function (tour, step, message) {
website.Tour.reset();
throw new Error(message +
- + "\ntour:" + tour.id +
- + "\nstep:" + step.id + ": '" + (step._title || step.title) + "'"
+ + "\ntour: " + tour.id +
+ + "\nstep: " + step.id + ": '" + (step._title || step.title) + "'"
+ '\nhref: ' + window.location.href
+ '\nreferrer: ' + document.referrer
+ '\nelement: ' + Boolean(!step.element || ($(step.element).size() && $(step.element).is(":visible") && !$(step.element).is(":hidden")))
+ '\nwaitNot: ' + Boolean(!step.waitNot || !$(step.waitNot).size())
+ '\nwaitFor: ' + Boolean(!step.waitFor || $(step.waitFor).size())
- + "\nlocalStorage: " + localStorage.getItem("tour")
+ + "\nlocalStorage: " + JSON.stringify(localStorage)
+ '\n\n' + $("body").html()
);
};
@@ -206,24 +242,39 @@ website.Tour.lists = function () {
}
return tour_ids;
};
-website.Tour.save_state = function (tour_id, mode, step_id) {
- localStorage.setItem("tour", '{tour_id:'+tour_id+', mode:'+mode+', step_id:'+step_id+'}');
+website.Tour.saveState = function (tour_id, mode, step_id) {
+ localStorage.setItem("tour", JSON.stringify({"id":tour_id, "mode":mode, "step_id":step_id}));
};
website.Tour.reset = function () {
- var running = website.Tour.get_state();
- for (var k in running.tour.steps) {
- running.tour.steps[k].busy = false;
+ var state = website.Tour.getState();
+ if (state) {
+ for (var k in state.tour.steps) {
+ state.tour.steps[k].busy = false;
+ }
+ if (state.tour.tour) {
+ state.tour.tour.end();
+ }
}
localStorage.removeItem("tour");
clearTimeout(website.Tour.timer);
clearTimeout(website.Tour.testtimer);
- $('.popover.tour').remove();
+ $(".popover.tour").remove();
};
website.Tour.running = function () {
- var running = website.Tour.get_state();
- website.Tour.registerSteps(running.tour);
- website.Tour.nextStep( running.tour, running.step_id );
+ var state = website.Tour.getState();
+ if (state) {
+ website.Tour.registerSteps(state.tour);
+ if ($.ajaxBusy) {
+ $(document).ajaxStop(function() {
+ setTimeout(function () {
+ website.Tour.nextStep( state.tour, state.step, state.mode === "test" ? 5000 : 0 );
+ },0);
+ });
+ } else {
+ website.Tour.nextStep( state.tour, state.step, state.mode === "test" ? 5000 : 0 );
+ }
+ }
};
website.Tour.timer = null;
@@ -238,83 +289,62 @@ website.Tour.check = function (step) {
website.Tour.waitNextStep = function (tour, step, overlaps) {
var time = new Date().getTime();
var timer;
+ var next = tour.steps[step.id+1];
window.onbeforeunload = function () {
clearTimeout(website.Tour.timer);
clearTimeout(website.Tour.testtimer);
};
- // check popover activity
- $(".popover.tour button")
- .off()
- .on("click", function () {
- $(".popover.tour").remove();
- if (step.busy) return;
- if (!$(this).is("[data-role='next']")) {
- clearTimeout(website.Tour.timer);
- step.busy = true;
- if (tour.tour) {
- tour.tour.end();
- }
- tour.endTour(tour);
- }
- });
-
function checkNext () {
+ website.Tour.autoToggleBootstrapTour();
+
clearTimeout(website.Tour.timer);
- if (step.busy) return;
- if (website.Tour.check(step)) {
- step.busy = true;
+ if (next.busy) return;
+ if (website.Tour.check(next)) {
+ next.busy = true;
+ clearTimeout(website.Tour.currentTimer);
// use an other timeout for cke dom loading
setTimeout(function () {
- website.Tour.nextStep(tour, step, overlaps);
+ website.Tour.nextStep(tour, next, overlaps);
}, website.Tour.defaultDelay);
} else if (!overlaps || new Date().getTime() - time < overlaps) {
- if (self.current.element) {
- var $popover = $(".popover.tour");
- if(!$(self.current.element).is(":visible")) {
- $popover.data("hide", true).fadeOut(300);
- } else if($popover.data("hide")) {
- $popover.data("hide", false).fadeIn(150);
- }
- }
website.Tour.timer = setTimeout(checkNext, website.Tour.defaultDelay);
} else {
- website.Tour.error(tour, step, "Can't arrive to the next step");
+ website.Tour.error(tour, next, "Can't arrive to the next step");
}
}
checkNext();
};
+website.Tour.currentTimer = null;
website.Tour.nextStep = function (tour, step, overlaps) {
- var state = website.Tour.get_state();
- website.Tour.save_state(tour.id, state.mode, step.id);
+ var state = website.Tour.getState();
+ website.Tour.saveState(state.id, state.mode, step.id);
- // clear popover (fix for boostrap tour if the element is removed before destroy popover)
- $(".popover.tour").remove();
- // go to step in bootstrap tour
- if (tour.tour) {
- tour.tour.goto(step.id);
+ website.Tour.autoToggleBootstrapTour();
+
+ if (step.onload) {
+ step.onload();
}
- step.onload();
var next = tour.steps[step.id+1];
if (next) {
setTimeout(function () {
- website.Tour.waitNextStep(tour, next, overlaps);
+ website.Tour.waitNextStep(tour, step, overlaps);
if (state.mode === "test") {
setTimeout(function(){
website.Tour.autoNextStep(tour, step);
}, website.Tour.defaultDelay);
}
- }, next && next.wait || 0);
+ }, next.wait || 0);
} else {
website.Tour.endTour(tour);
}
};
website.Tour.endTour = function (tour) {
- var state = website.Tour.get_state();
- var test = state.step_id >= tour.steps.length-1;
- this.reset();
+ var state = website.Tour.getState();
+ var test = state.step.id >= state.tour.steps.length-1;
+ website.Tour.reset();
if (test) {
console.log('ok');
} else {
@@ -388,7 +418,8 @@ website.Tour.autoDragAndDropSnippet = function (selector) {
$dropZone.trigger($.Event("mouseup", { which: 1, pageX: dropPosition.left, pageY: dropPosition.top }));
};
-website.ready(website.Tour.running);
+//$(document).ready(website.Tour.running);
+website.ready().then(website.Tour.running);
}());
From 58b6aeb01d489922f8311e6a390805d9cb1c877f Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Fri, 21 Mar 2014 12:07:50 +0100
Subject: [PATCH 04/26] [IMP] website tour: remove bootstrap Tour lib
bzr revid: chm@openerp.com-20140321110750-ew8rj3nv2jcort1x
---
.../lib/bootstrap-tour/bootstrap-tour.css | 65 --
.../lib/bootstrap-tour/bootstrap-tour.js | 716 ------------------
addons/website/static/src/css/editor.css | 24 +-
addons/website/static/src/css/editor.sass | 19 +-
.../static/src/js/website.tour.banner.js | 2 +
addons/website/static/src/js/website.tour.js | 349 +++++----
6 files changed, 258 insertions(+), 917 deletions(-)
delete mode 100644 addons/website/static/lib/bootstrap-tour/bootstrap-tour.css
delete mode 100644 addons/website/static/lib/bootstrap-tour/bootstrap-tour.js
diff --git a/addons/website/static/lib/bootstrap-tour/bootstrap-tour.css b/addons/website/static/lib/bootstrap-tour/bootstrap-tour.css
deleted file mode 100644
index 5449158e7f4..00000000000
--- a/addons/website/static/lib/bootstrap-tour/bootstrap-tour.css
+++ /dev/null
@@ -1,65 +0,0 @@
-/* ===========================================================
-# bootstrap-tour - v0.9.1
-# http://bootstraptour.com
-# ==============================================================
-# Copyright 2012-2013 Ulrich Sossou
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-*/
-.tour-backdrop {
- position: fixed;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: 1100;
- background-color: #000;
- opacity: 0.8;
-}
-.tour-step-backdrop {
- position: relative;
- z-index: 1101;
- background: inherit;
-}
-.tour-step-background {
- position: absolute;
- z-index: 1100;
- background: inherit;
- border-radius: 6px;
-}
-.popover[class*="tour-"] {
- z-index: 1100;
-}
-.popover[class*="tour-"] .popover-navigation {
- padding: 9px 14px;
-}
-.popover[class*="tour-"] .popover-navigation *[data-role="end"] {
- float: right;
-}
-.popover[class*="tour-"] .popover-navigation *[data-role="prev"],
-.popover[class*="tour-"] .popover-navigation *[data-role="next"],
-.popover[class*="tour-"] .popover-navigation *[data-role="end"] {
- cursor: pointer;
-}
-.popover[class*="tour-"] .popover-navigation *[data-role="prev"].disabled,
-.popover[class*="tour-"] .popover-navigation *[data-role="next"].disabled,
-.popover[class*="tour-"] .popover-navigation *[data-role="end"].disabled {
- cursor: default;
-}
-.popover[class*="tour-"].orphan {
- position: fixed;
- margin-top: 0;
-}
-.popover[class*="tour-"].orphan .arrow {
- display: none;
-}
diff --git a/addons/website/static/lib/bootstrap-tour/bootstrap-tour.js b/addons/website/static/lib/bootstrap-tour/bootstrap-tour.js
deleted file mode 100644
index a0172c718c0..00000000000
--- a/addons/website/static/lib/bootstrap-tour/bootstrap-tour.js
+++ /dev/null
@@ -1,716 +0,0 @@
-/* ===========================================================
-# bootstrap-tour - v0.9.1
-# http://bootstraptour.com
-# ==============================================================
-# Copyright 2012-2013 Ulrich Sossou
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-*/
-(function($, window) {
- var Tour, document;
- document = window.document;
- Tour = (function() {
- function Tour(options) {
- this._options = $.extend({
- name: "tour",
- steps: [],
- container: "body",
- keyboard: true,
- storage: window.localStorage,
- debug: false,
- backdrop: false,
- redirect: true,
- orphan: false,
- duration: false,
- basePath: "",
- template: "
",
- afterSetState: function(key, value) {},
- afterGetState: function(key, value) {},
- afterRemoveState: function(key) {},
- onStart: function(tour) {},
- onEnd: function(tour) {},
- onShow: function(tour) {},
- onShown: function(tour) {},
- onHide: function(tour) {},
- onHidden: function(tour) {},
- onNext: function(tour) {},
- onPrev: function(tour) {},
- onPause: function(tour, duration) {},
- onResume: function(tour, duration) {}
- }, options);
- this._force = false;
- this._inited = false;
- this.backdrop = {
- overlay: null,
- $element: null,
- $background: null,
- backgroundShown: false,
- overlayElementShown: false
- };
- this;
- }
-
- Tour.prototype.addSteps = function(steps) {
- var step, _i, _len;
- for (_i = 0, _len = steps.length; _i < _len; _i++) {
- step = steps[_i];
- this.addStep(step);
- }
- return this;
- };
-
- Tour.prototype.addStep = function(step) {
- this._options.steps.push(step);
- return this;
- };
-
- Tour.prototype.getStep = function(i) {
- if (this._options.steps[i] != null) {
- return $.extend({
- id: "step-" + i,
- path: "",
- placement: "right",
- title: "",
- content: "",
- next: i === this._options.steps.length - 1 ? -1 : i + 1,
- prev: i - 1,
- animation: true,
- container: this._options.container,
- backdrop: this._options.backdrop,
- redirect: this._options.redirect,
- orphan: this._options.orphan,
- duration: this._options.duration,
- template: this._options.template,
- onShow: this._options.onShow,
- onShown: this._options.onShown,
- onHide: this._options.onHide,
- onHidden: this._options.onHidden,
- onNext: this._options.onNext,
- onPrev: this._options.onPrev,
- onPause: this._options.onPause,
- onResume: this._options.onResume
- }, this._options.steps[i]);
- }
- };
-
- Tour.prototype.init = function(force) {
- this._force = force;
- if (this.ended()) {
- this._debug("Tour ended, init prevented.");
- return this;
- }
- this.setCurrentStep();
- this._initMouseNavigation();
- this._initKeyboardNavigation();
- this._onResize((function(_this) {
- return function() {
- return _this.showStep(_this._current);
- };
- })(this));
- if (this._current !== null) {
- this.showStep(this._current);
- }
- this._inited = true;
- return this;
- };
-
- Tour.prototype.start = function(force) {
- var promise;
- if (force == null) {
- force = false;
- }
- if (!this._inited) {
- this.init(force);
- }
- if (this._current === null) {
- promise = this._makePromise(this._options.onStart != null ? this._options.onStart(this) : void 0);
- this._callOnPromiseDone(promise, this.showStep, 0);
- }
- return this;
- };
-
- Tour.prototype.next = function() {
- var promise;
- promise = this.hideStep(this._current);
- return this._callOnPromiseDone(promise, this._showNextStep);
- };
-
- Tour.prototype.prev = function() {
- var promise;
- promise = this.hideStep(this._current);
- return this._callOnPromiseDone(promise, this._showPrevStep);
- };
-
- Tour.prototype.goTo = function(i) {
- var promise;
- promise = this.hideStep(this._current);
- return this._callOnPromiseDone(promise, this.showStep, i);
- };
-
- Tour.prototype.end = function() {
- var endHelper, promise;
- endHelper = (function(_this) {
- return function(e) {
- $(document).off("click.tour-" + _this._options.name);
- $(document).off("keyup.tour-" + _this._options.name);
- $(window).off("resize.tour-" + _this._options.name);
- _this._setState("end", "yes");
- _this._inited = false;
- _this._force = false;
- _this._clearTimer();
- if (_this._options.onEnd != null) {
- return _this._options.onEnd(_this);
- }
- };
- })(this);
- promise = this.hideStep(this._current);
- return this._callOnPromiseDone(promise, endHelper);
- };
-
- Tour.prototype.ended = function() {
- return !this._force && !!this._getState("end");
- };
-
- Tour.prototype.restart = function() {
- this._removeState("current_step");
- this._removeState("end");
- this.setCurrentStep(0);
- return this.start();
- };
-
- Tour.prototype.pause = function() {
- var step;
- step = this.getStep(this._current);
- if (!(step && step.duration)) {
- return this;
- }
- this._paused = true;
- this._duration -= new Date().getTime() - this._start;
- window.clearTimeout(this._timer);
- this._debug("Paused/Stopped step " + (this._current + 1) + " timer (" + this._duration + " remaining).");
- if (step.onPause != null) {
- return step.onPause(this, this._duration);
- }
- };
-
- Tour.prototype.resume = function() {
- var step;
- step = this.getStep(this._current);
- if (!(step && step.duration)) {
- return this;
- }
- this._paused = false;
- this._start = new Date().getTime();
- this._duration = this._duration || step.duration;
- this._timer = window.setTimeout((function(_this) {
- return function() {
- if (_this._isLast()) {
- return _this.next();
- } else {
- return _this.end();
- }
- };
- })(this), this._duration);
- this._debug("Started step " + (this._current + 1) + " timer with duration " + this._duration);
- if ((step.onResume != null) && this._duration !== step.duration) {
- return step.onResume(this, this._duration);
- }
- };
-
- Tour.prototype.hideStep = function(i) {
- var hideStepHelper, promise, step;
- step = this.getStep(i);
- if (!step) {
- return;
- }
- this._clearTimer();
- promise = this._makePromise(step.onHide != null ? step.onHide(this, i) : void 0);
- hideStepHelper = (function(_this) {
- return function(e) {
- var $element;
- $element = $(step.element);
- if (!($element.data("bs.popover") || $element.data("popover"))) {
- $element = $("body");
- }
- $element.popover("destroy").removeClass("tour-" + _this._options.name + "-element tour-" + _this._options.name + "-" + i + "-element");
- if (step.reflex) {
- $element.css("cursor", "").off("click.tour-" + _this._options.name);
- }
- if (step.backdrop) {
- _this._hideBackdrop();
- }
- if (step.onHidden != null) {
- return step.onHidden(_this);
- }
- };
- })(this);
- this._callOnPromiseDone(promise, hideStepHelper);
- return promise;
- };
-
- Tour.prototype.showStep = function(i) {
- var promise, showStepHelper, skipToPrevious, step;
- if (this.ended()) {
- this._debug("Tour ended, showStep prevented.");
- return this;
- }
- step = this.getStep(i);
- if (!step) {
- return;
- }
- skipToPrevious = i < this._current;
- promise = this._makePromise(step.onShow != null ? step.onShow(this, i) : void 0);
- showStepHelper = (function(_this) {
- return function(e) {
- var current_path, path;
- _this.setCurrentStep(i);
- path = (function() {
- switch ({}.toString.call(step.path)) {
- case "[object Function]":
- return step.path();
- case "[object String]":
- return this._options.basePath + step.path;
- default:
- return step.path;
- }
- }).call(_this);
- current_path = [document.location.pathname, document.location.hash].join("");
- if (_this._isRedirect(path, current_path)) {
- _this._redirect(step, path);
- return;
- }
- if (_this._isOrphan(step)) {
- if (!step.orphan) {
- _this._debug("Skip the orphan step " + (_this._current + 1) + ". Orphan option is false and the element doesn't exist or is hidden.");
- if (skipToPrevious) {
- _this._showPrevStep();
- } else {
- _this._showNextStep();
- }
- return;
- }
- _this._debug("Show the orphan step " + (_this._current + 1) + ". Orphans option is true.");
- }
- if (step.backdrop) {
- _this._showBackdrop(!_this._isOrphan(step) ? step.element : void 0);
- }
- _this._scrollIntoView(step.element, function() {
- if ((step.element != null) && step.backdrop) {
- _this._showOverlayElement(step.element);
- }
- _this._showPopover(step, i);
- if (step.onShown != null) {
- step.onShown(_this);
- }
- return _this._debug("Step " + (_this._current + 1) + " of " + _this._options.steps.length);
- });
- if (step.duration) {
- return _this.resume();
- }
- };
- })(this);
- this._callOnPromiseDone(promise, showStepHelper);
- return promise;
- };
-
- Tour.prototype.getCurrentStep = function() {
- return this._current;
- };
-
- Tour.prototype.setCurrentStep = function(value) {
- if (value != null) {
- this._current = value;
- this._setState("current_step", value);
- } else {
- this._current = this._getState("current_step");
- this._current = this._current === null ? null : parseInt(this._current, 10);
- }
- return this;
- };
-
- Tour.prototype._setState = function(key, value) {
- var e, keyName;
- if (this._options.storage) {
- keyName = "" + this._options.name + "_" + key;
- try {
- this._options.storage.setItem(keyName, value);
- } catch (_error) {
- e = _error;
- if (e.code === DOMException.QUOTA_EXCEEDED_ERR) {
- this.debug("LocalStorage quota exceeded. State storage failed.");
- }
- }
- return this._options.afterSetState(keyName, value);
- } else {
- if (this._state == null) {
- this._state = {};
- }
- return this._state[key] = value;
- }
- };
-
- Tour.prototype._removeState = function(key) {
- var keyName;
- if (this._options.storage) {
- keyName = "" + this._options.name + "_" + key;
- this._options.storage.removeItem(keyName);
- return this._options.afterRemoveState(keyName);
- } else {
- if (this._state != null) {
- return delete this._state[key];
- }
- }
- };
-
- Tour.prototype._getState = function(key) {
- var keyName, value;
- if (this._options.storage) {
- keyName = "" + this._options.name + "_" + key;
- value = this._options.storage.getItem(keyName);
- } else {
- if (this._state != null) {
- value = this._state[key];
- }
- }
- if (value === void 0 || value === "null") {
- value = null;
- }
- this._options.afterGetState(key, value);
- return value;
- };
-
- Tour.prototype._showNextStep = function() {
- var promise, showNextStepHelper, step;
- step = this.getStep(this._current);
- showNextStepHelper = (function(_this) {
- return function(e) {
- return _this.showStep(step.next);
- };
- })(this);
- promise = this._makePromise(step.onNext != null ? step.onNext(this) : void 0);
- return this._callOnPromiseDone(promise, showNextStepHelper);
- };
-
- Tour.prototype._showPrevStep = function() {
- var promise, showPrevStepHelper, step;
- step = this.getStep(this._current);
- showPrevStepHelper = (function(_this) {
- return function(e) {
- return _this.showStep(step.prev);
- };
- })(this);
- promise = this._makePromise(step.onPrev != null ? step.onPrev(this) : void 0);
- return this._callOnPromiseDone(promise, showPrevStepHelper);
- };
-
- Tour.prototype._debug = function(text) {
- if (this._options.debug) {
- return window.console.log("Bootstrap Tour '" + this._options.name + "' | " + text);
- }
- };
-
- Tour.prototype._isRedirect = function(path, currentPath) {
- return (path != null) && path !== "" && ((toString.call(path) === "[object RegExp]" && !path.test(currentPath)) || (toString.call(path) === "[object String]" && path.replace(/\?.*$/, "").replace(/\/?$/, "") !== currentPath.replace(/\/?$/, "")));
- };
-
- Tour.prototype._redirect = function(step, path) {
- if ($.isFunction(step.redirect)) {
- return step.redirect.call(this, path);
- } else if (step.redirect === true) {
- this._debug("Redirect to " + path);
- return document.location.href = path;
- }
- };
-
- Tour.prototype._isOrphan = function(step) {
- return (step.element == null) || !$(step.element).length || $(step.element).is(":hidden") && ($(step.element)[0].namespaceURI !== "http://www.w3.org/2000/svg");
- };
-
- Tour.prototype._isLast = function() {
- return this._current < this._options.steps.length - 1;
- };
-
- Tour.prototype._showPopover = function(step, i) {
- var $element, $navigation, $template, $tip, isOrphan, options;
- options = $.extend({}, this._options);
- $template = $.isFunction(step.template) ? $(step.template(i, step)) : $(step.template);
- $navigation = $template.find(".popover-navigation");
- isOrphan = this._isOrphan(step);
- if (isOrphan) {
- step.element = "body>*:last";
- step.placement = "top";
- $template = $template.addClass("orphan");
- }
- $element = $(step.element);
- $template.addClass("tour-" + this._options.name + " tour-" + this._options.name + "-" + i);
- $element.addClass("tour-" + this._options.name + "-element tour-" + this._options.name + "-" + i + "-element");
- if (step.options) {
- $.extend(options, step.options);
- }
- if (step.reflex) {
- $element.css("cursor", "pointer").on("click.tour-" + this._options.name, (function(_this) {
- return function() {
- if (_this._isLast()) {
- return _this.next();
- } else {
- return _this.end();
- }
- };
- })(this));
- }
- if (step.prev < 0) {
- $navigation.find("[data-role='prev']").addClass("disabled");
- }
- if (step.next < 0) {
- $navigation.find("[data-role='next']").addClass("disabled");
- }
- if (!step.duration) {
- $navigation.find("[data-role='pause-resume']").remove();
- }
- step.template = $template.clone().wrap("").parent().html();
- $element.popover({
- placement: step.placement,
- trigger: "manual",
- title: step.title,
- content: step.content,
- html: true,
- animation: step.animation,
- container: step.container,
- template: step.template,
- selector: step.element
- }).popover("show");
- $tip = $element.data("bs.popover") ? $element.data("bs.popover").tip() : $element.data("popover").tip();
- $tip.attr("id", step.id);
- this._reposition($tip, step);
- if (isOrphan) {
- return this._center($tip);
- }
- };
-
- Tour.prototype._reposition = function($tip, step) {
- var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset;
- offsetWidth = $tip[0].offsetWidth;
- offsetHeight = $tip[0].offsetHeight;
- tipOffset = $tip.offset();
- originalLeft = tipOffset.left;
- originalTop = tipOffset.top;
- offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight();
- if (offsetBottom < 0) {
- tipOffset.top = tipOffset.top + offsetBottom;
- }
- offsetRight = $("html").outerWidth() - tipOffset.left - $tip.outerWidth();
- if (offsetRight < 0) {
- tipOffset.left = tipOffset.left + offsetRight;
- }
- if (tipOffset.top < 0) {
- tipOffset.top = 0;
- }
- if (tipOffset.left < 0) {
- tipOffset.left = 0;
- }
- $tip.offset(tipOffset);
- if (step.placement === "bottom" || step.placement === "top") {
- if (originalLeft !== tipOffset.left) {
- return this._replaceArrow($tip, (tipOffset.left - originalLeft) * 2, offsetWidth, "left");
- }
- } else {
- if (originalTop !== tipOffset.top) {
- return this._replaceArrow($tip, (tipOffset.top - originalTop) * 2, offsetHeight, "top");
- }
- }
- };
-
- Tour.prototype._center = function($tip) {
- return $tip.css("top", $(window).outerHeight() / 2 - $tip.outerHeight() / 2);
- };
-
- Tour.prototype._replaceArrow = function($tip, delta, dimension, position) {
- return $tip.find(".arrow").css(position, delta ? 50 * (1 - delta / dimension) + "%" : "");
- };
-
- Tour.prototype._scrollIntoView = function(element, callback) {
- var $element, $window, counter, offsetTop, scrollTop, windowHeight;
- $element = $(element);
- if (!$element.length) {
- return callback();
- }
- $window = $(window);
- offsetTop = $element.offset().top;
- windowHeight = $window.height();
- scrollTop = Math.max(0, offsetTop - (windowHeight / 2));
- this._debug("Scroll into view. ScrollTop: " + scrollTop + ". Element offset: " + offsetTop + ". Window height: " + windowHeight + ".");
- counter = 0;
- return $("body,html").stop(true, true).animate({
- scrollTop: Math.ceil(scrollTop)
- }, (function(_this) {
- return function() {
- if (++counter === 2) {
- callback();
- return _this._debug("Scroll into view. Animation end element offset: " + ($element.offset().top) + ". Window height: " + ($window.height()) + ".");
- }
- };
- })(this));
- };
-
- Tour.prototype._onResize = function(callback, timeout) {
- return $(window).on("resize.tour-" + this._options.name, function() {
- clearTimeout(timeout);
- return timeout = setTimeout(callback, 100);
- });
- };
-
- Tour.prototype._initMouseNavigation = function() {
- var _this;
- _this = this;
- return $(document).off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']:not(.disabled)").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='next']:not(.disabled)").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']").off("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']").on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='next']:not(.disabled)", (function(_this) {
- return function(e) {
- e.preventDefault();
- return _this.next();
- };
- })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='prev']:not(.disabled)", (function(_this) {
- return function(e) {
- e.preventDefault();
- return _this.prev();
- };
- })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='end']", (function(_this) {
- return function(e) {
- e.preventDefault();
- return _this.end();
- };
- })(this)).on("click.tour-" + this._options.name, ".popover.tour-" + this._options.name + " *[data-role='pause-resume']", function(e) {
- var $this;
- e.preventDefault();
- $this = $(this);
- $this.text(_this._paused ? $this.data("pause-text") : $this.data("resume-text"));
- if (_this._paused) {
- return _this.resume();
- } else {
- return _this.pause();
- }
- });
- };
-
- Tour.prototype._initKeyboardNavigation = function() {
- if (!this._options.keyboard) {
- return;
- }
- return $(document).on("keyup.tour-" + this._options.name, (function(_this) {
- return function(e) {
- if (!e.which) {
- return;
- }
- switch (e.which) {
- case 39:
- e.preventDefault();
- if (_this._isLast()) {
- return _this.next();
- } else {
- return _this.end();
- }
- break;
- case 37:
- e.preventDefault();
- if (_this._current > 0) {
- return _this.prev();
- }
- break;
- case 27:
- e.preventDefault();
- return _this.end();
- }
- };
- })(this));
- };
-
- Tour.prototype._makePromise = function(result) {
- if (result && $.isFunction(result.then)) {
- return result;
- } else {
- return null;
- }
- };
-
- Tour.prototype._callOnPromiseDone = function(promise, cb, arg) {
- if (promise) {
- return promise.then((function(_this) {
- return function(e) {
- return cb.call(_this, arg);
- };
- })(this));
- } else {
- return cb.call(this, arg);
- }
- };
-
- Tour.prototype._showBackdrop = function(element) {
- if (this.backdrop.backgroundShown) {
- return;
- }
- this.backdrop = $("
", {
- "class": "tour-backdrop"
- });
- this.backdrop.backgroundShown = true;
- return $("body").append(this.backdrop);
- };
-
- Tour.prototype._hideBackdrop = function() {
- this._hideOverlayElement();
- return this._hideBackground();
- };
-
- Tour.prototype._hideBackground = function() {
- this.backdrop.remove();
- this.backdrop.overlay = null;
- return this.backdrop.backgroundShown = false;
- };
-
- Tour.prototype._showOverlayElement = function(element) {
- var $background, $element, offset;
- $element = $(element);
- if (!$element || $element.length === 0 || this.backdrop.overlayElementShown) {
- return;
- }
- this.backdrop.overlayElementShown = true;
- $background = $("
");
- offset = $element.offset();
- offset.top = offset.top;
- offset.left = offset.left;
- $background.width($element.innerWidth()).height($element.innerHeight()).addClass("tour-step-background").offset(offset);
- $element.addClass("tour-step-backdrop");
- $("body").append($background);
- this.backdrop.$element = $element;
- return this.backdrop.$background = $background;
- };
-
- Tour.prototype._hideOverlayElement = function() {
- if (!this.backdrop.overlayElementShown) {
- return;
- }
- this.backdrop.$element.removeClass("tour-step-backdrop");
- this.backdrop.$background.remove();
- this.backdrop.$element = null;
- this.backdrop.$background = null;
- return this.backdrop.overlayElementShown = false;
- };
-
- Tour.prototype._clearTimer = function() {
- window.clearTimeout(this._timer);
- this._timer = null;
- return this._duration = null;
- };
-
- return Tour;
-
- })();
- return window.Tour = Tour;
-})(jQuery, window);
diff --git a/addons/website/static/src/css/editor.css b/addons/website/static/src/css/editor.css
index da0fad43caf..0bd20bdcca9 100644
--- a/addons/website/static/src/css/editor.css
+++ b/addons/website/static/src/css/editor.css
@@ -484,10 +484,30 @@ div.tour-backdrop {
z-index: 2009;
}
-.popover.tour {
- z-index: 2010;
+.popover.tour.orphan .arrow {
+ display: none;
+}
+.popover.tour .popover-navigation {
+ padding: 9px 14px;
+}
+.popover.tour .popover-navigation *[data-role="end"] {
+ float: right;
+}
+.popover.tour .popover-navigation *[data-role="next"], .popover.tour .popover-navigation *[data-role="end"] {
+ cursor: pointer;
}
.popover.fixed {
position: fixed;
}
+
+.tour-backdrop {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1100;
+ background-color: black;
+ opacity: 0.8;
+}
diff --git a/addons/website/static/src/css/editor.sass b/addons/website/static/src/css/editor.sass
index 4571dcd257e..bd0f4628009 100644
--- a/addons/website/static/src/css/editor.sass
+++ b/addons/website/static/src/css/editor.sass
@@ -424,9 +424,26 @@ $editorbar_height: 30px
div.tour-backdrop
z-index: 2009
.popover.tour
- z-index: 2010
+ &.orphan .arrow
+ display: none
+ .popover-navigation
+ padding: 9px 14px
+ *[data-role="end"]
+ float: right
+ *[data-role="next"],*[data-role="end"]
+ cursor: pointer
.popover.fixed
position: fixed
+.tour-backdrop
+ position: fixed
+ top: 0
+ right: 0
+ bottom: 0
+ left: 0
+ z-index: 1100
+ background-color: #000
+ opacity: 0.8
+
// }}}
diff --git a/addons/website/static/src/js/website.tour.banner.js b/addons/website/static/src/js/website.tour.banner.js
index 443405e2401..a8abbcf59e2 100644
--- a/addons/website/static/src/js/website.tour.banner.js
+++ b/addons/website/static/src/js/website.tour.banner.js
@@ -13,6 +13,7 @@
title: _t("Welcome to your website!"),
content: _t("This tutorial will guide you to build your home page. We will start by adding a banner."),
popover: { next: _t("Start Tutorial"), end: _t("Skip It") },
+ backdrop: true,
},
{
element: 'button[data-action=edit]',
@@ -77,6 +78,7 @@
title: _t("Good Job!"),
content: _t("Well done, you created your homepage."),
popover: { next: _t("Continue") },
+ backdrop: true,
},
{
element: 'a[data-action=show-mobile-preview]',
diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js
index df6108e0278..3bfd4e06da0 100644
--- a/addons/website/static/src/js/website.tour.js
+++ b/addons/website/static/src/js/website.tour.js
@@ -15,8 +15,8 @@ if (typeof openerp === "undefined") {
var website = window.openerp.website;
-// don't rewrite website.Tour in test mode
-if (typeof website.Tour !== "undefined") {
+// don't rewrite T in test mode
+if (typeof T !== "undefined") {
return;
}
@@ -31,14 +31,14 @@ if (website.EditorBar) {
start: function () {
var self = this;
var menu = $('#help-menu');
- _.each(website.Tour.tours, function (tour) {
+ _.each(T.tours, function (tour) {
if (tour.mode === "test") {
return;
}
var $menuItem = $($.parseHTML('
'+tour.name+''));
$menuItem.click(function () {
- website.Tour.reset();
- website.Tour.run(tour.id);
+ T.reset();
+ T.run(tour.id);
});
menu.append($menuItem);
});
@@ -80,32 +80,36 @@ $.ajaxSetup({
}
});
-
/////////////////////////////////////////////////
-
var localStorage = window.localStorage;
-website.Tour = {};
-website.Tour.tours = {};
-website.Tour.state = null;
-website.Tour.register = function (tour) {
+var T = website.Tour = {};
+T.tours = {};
+T.defaultDelay = 50;
+T.errorDelay = 5000;
+T.state = null;
+T.$element = null;
+T.timer = null;
+T.testtimer = null;
+T.currentTimer = null;
+T.register = function (tour) {
if (tour.mode !== "test") tour.mode = "tutorial";
- website.Tour.tours[tour.id] = tour;
+ T.tours[tour.id] = tour;
};
-website.Tour.run = function (tour_id, mode) {
+T.run = function (tour_id, mode) {
if (localStorage.getItem("tour") && mode === "test") { // only one test running
return;
}
- var tour = website.Tour.tours[tour_id];
- website.Tour.saveState(tour.id, mode || tour.mode, 0);
- if (tour.path && !window.location.href.match(new RegExp("("+website.Tour.getLang()+")?"+tour.path+"#?$", "i"))) {
- window.location.href = "/"+website.Tour.getLang()+tour.path;
+ var tour = T.tours[tour_id];
+ T.saveState(tour.id, mode || tour.mode, 0);
+ if (tour.path && !window.location.href.match(new RegExp("("+T.getLang()+")?"+tour.path+"#?$", "i"))) {
+ window.location.href = "/"+T.getLang()+tour.path;
} else {
- website.Tour.running();
+ T.running();
}
};
-website.Tour.registerSteps = function (tour) {
+T.registerSteps = function (tour) {
if (tour.register) {
return;
}
@@ -130,7 +134,10 @@ website.Tour.registerSteps = function (tour) {
step.element = '#oe_snippets '+step.snippet+' .oe_snippet_thumbnail';
}
- if (!step.element) step.orphan = true;
+ if (!step.element) {
+ step.element = "body";
+ step.orphan = true;
+ }
}
if (tour.steps[index-1] &&
tour.steps[index-1].popover && tour.steps[index-1].popover.next) {
@@ -142,69 +149,151 @@ website.Tour.registerSteps = function (tour) {
}
// rendering bootstrap tour and popover
- if (tour.mode !== "test" || typeof Tour !== "undefined") {
- tour.tour = new Tour({
- debug: true,
- name: tour.id,
- storage: localStorage,
- keyboard: false,
- template: website.Tour.popover(),
- onHide: function () {
- window.scrollTo(0, 0);
- }
- });
-
+ if (tour.mode !== "test") {
for (var index=0, len=tour.steps.length; index
');
+ }
+
+ if (step.backdrop || $element.parents("#website-top-navbar, .modal").size()) {
+ $tip.css("z-index", 2010);
+ }
+
+ // button click event
+ $tip.find("button")
+ .one("click", function () {
+ step.busy = true;
+ if (!$(this).is("[data-role='next']")) {
+ clearTimeout(T.timer);
+ T.endTour();
+ }
+ T.closePopover();
+ });
+
+ T.repositionPopover();
+};
+T.repositionPopover = function() {
+ var popover = T.$element.data("bs.popover");
+ var $tip = T.$element.data("bs.popover").tip();
+
+ if (popover.options.orphan) {
+ return $tip.css("top", $(window).outerHeight() / 2 - $tip.outerHeight() / 2);
+ }
+
+ var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset;
+ offsetWidth = $tip[0].offsetWidth;
+ offsetHeight = $tip[0].offsetHeight;
+ tipOffset = $tip.offset();
+ originalLeft = tipOffset.left;
+ originalTop = tipOffset.top;
+ offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight();
+ if (offsetBottom < 0) {
+ tipOffset.top = tipOffset.top + offsetBottom;
+ }
+ offsetRight = $("html").outerWidth() - tipOffset.left - $tip.outerWidth();
+ if (offsetRight < 0) {
+ tipOffset.left = tipOffset.left + offsetRight;
+ }
+ if (tipOffset.top < 0) {
+ tipOffset.top = 0;
+ }
+ if (tipOffset.left < 0) {
+ tipOffset.left = 0;
+ }
+ $tip.offset(tipOffset);
+ if (popover.options.placement === "bottom" || popover.options.placement === "top") {
+ var left = T.$element.offset().left + T.$element.outerWidth()/2 - tipOffset.left;
+ $tip.find(".arrow").css("left", left ? left + "px" : "");
} else {
- tour.end();
+ var top = T.$element.offset().top + T.$element.outerHeight()/2 - tipOffset.top;
+ $tip.find(".arrow").css("top", top ? top + "px" : "");
}
};
-website.Tour.popoverTitle = function (tour, options) {
+T.popoverTitle = function (tour, options) {
return openerp.qweb.render('website.tour_popover_title', options);
};
-website.Tour.popover = function (options) {
+T.popover = function (options) {
return openerp.qweb.render('website.tour_popover', options);
};
-website.Tour.getLang = function () {
+T.getLang = function () {
return $("html").attr("lang").replace(/-/, '_');
};
-website.Tour.getState = function () {
+T.getState = function () {
var state = JSON.parse(localStorage.getItem("tour") || 'false') || {};
var tour_id,mode,step_id;
if (!state.id && window.location.href.indexOf("#tutorial.") > -1) {
@@ -217,15 +306,16 @@ website.Tour.getState = function () {
if (!state.id) {
return;
}
- state.tour = website.Tour.tours[state.id];
+ state.tour = T.tours[state.id];
state.step = state.tour.steps[state.step_id];
return state;
};
-website.Tour.error = function (tour, step, message) {
- website.Tour.reset();
+T.error = function (message) {
+ var state = T.getState();
+ T.reset();
throw new Error(message +
- + "\ntour: " + tour.id +
- + "\nstep: " + step.id + ": '" + (step._title || step.title) + "'"
+ + "\ntour: " + state.tour.id +
+ + "\nstep: " + state.step.id + ": '" + (state.step._title || state.step.title) + "'"
+ '\nhref: ' + window.location.href
+ '\nreferrer: ' + document.referrer
+ '\nelement: ' + Boolean(!step.element || ($(step.element).size() && $(step.element).is(":visible") && !$(step.element).is(":hidden")))
@@ -235,124 +325,121 @@ website.Tour.error = function (tour, step, message) {
+ '\n\n' + $("body").html()
);
};
-website.Tour.lists = function () {
+T.lists = function () {
var tour_ids = [];
- for (var k in website.Tour.tours) {
+ for (var k in T.tours) {
tour_ids.push(k);
}
return tour_ids;
};
-website.Tour.saveState = function (tour_id, mode, step_id) {
- localStorage.setItem("tour", JSON.stringify({"id":tour_id, "mode":mode, "step_id":step_id}));
+T.saveState = function (tour_id, mode, step_id) {
+ localStorage.setItem("tour", JSON.stringify({"id":tour_id, "mode":mode, "step_id":step_id || 0}));
};
-website.Tour.reset = function () {
- var state = website.Tour.getState();
+T.reset = function () {
+ var state = T.getState();
if (state) {
for (var k in state.tour.steps) {
state.tour.steps[k].busy = false;
}
- if (state.tour.tour) {
- state.tour.tour.end();
- }
}
localStorage.removeItem("tour");
- clearTimeout(website.Tour.timer);
- clearTimeout(website.Tour.testtimer);
-
- $(".popover.tour").remove();
+ clearTimeout(T.timer);
+ clearTimeout(T.testtimer);
+ T.closePopover();
};
-website.Tour.running = function () {
- var state = website.Tour.getState();
+T.running = function () {
+ var state = T.getState();
if (state) {
- website.Tour.registerSteps(state.tour);
+ T.registerSteps(state.tour);
if ($.ajaxBusy) {
$(document).ajaxStop(function() {
setTimeout(function () {
- website.Tour.nextStep( state.tour, state.step, state.mode === "test" ? 5000 : 0 );
+ T.nextStep();
},0);
});
} else {
- website.Tour.nextStep( state.tour, state.step, state.mode === "test" ? 5000 : 0 );
+ T.nextStep();
}
}
};
-
-website.Tour.timer = null;
-website.Tour.testtimer = null;
-website.Tour.defaultDelay = 50;
-website.Tour.check = function (step) {
+T.check = function (step) {
return (step &&
(!step.element || ($(step.element).size() && $(step.element).is(":visible") && !$(step.element).is(":hidden"))) &&
(!step.waitNot || !$(step.waitNot).size()) &&
(!step.waitFor || $(step.waitFor).size()));
};
-website.Tour.waitNextStep = function (tour, step, overlaps) {
+T.waitNextStep = function () {
+ var state = T.getState();
var time = new Date().getTime();
var timer;
- var next = tour.steps[step.id+1];
+ var next = state.tour.steps[state.step.id+1];
+ var overlaps = state.mode === "test" ? T.errorDelay : 0;
window.onbeforeunload = function () {
- clearTimeout(website.Tour.timer);
- clearTimeout(website.Tour.testtimer);
+ clearTimeout(T.timer);
+ clearTimeout(T.testtimer);
};
function checkNext () {
- website.Tour.autoToggleBootstrapTour();
+ T.autoTogglePopover();
- clearTimeout(website.Tour.timer);
- if (next.busy) return;
- if (website.Tour.check(next)) {
- next.busy = true;
- clearTimeout(website.Tour.currentTimer);
+ clearTimeout(T.timer);
+ if (T.check(next)) {
+ clearTimeout(T.currentTimer);
// use an other timeout for cke dom loading
setTimeout(function () {
- website.Tour.nextStep(tour, next, overlaps);
- }, website.Tour.defaultDelay);
+ T.nextStep(next);
+ }, T.defaultDelay);
} else if (!overlaps || new Date().getTime() - time < overlaps) {
- website.Tour.timer = setTimeout(checkNext, website.Tour.defaultDelay);
+ T.timer = setTimeout(checkNext, T.defaultDelay);
} else {
- website.Tour.error(tour, next, "Can't arrive to the next step");
+ T.error("Can't arrive to the next step");
}
}
checkNext();
};
-website.Tour.currentTimer = null;
-website.Tour.nextStep = function (tour, step, overlaps) {
- var state = website.Tour.getState();
- website.Tour.saveState(state.id, state.mode, step.id);
+T.nextStep = function (step) {
+ var state = T.getState();
- website.Tour.autoToggleBootstrapTour();
+ if (!state) {
+ return;
+ }
+
+ step = step || state.step;
+ T.saveState(state.id, state.mode, step.id);
+
+ T.autoTogglePopover(true);
if (step.onload) {
step.onload();
}
- var next = tour.steps[step.id+1];
+ var next = state.tour.steps[step.id+1];
if (next) {
setTimeout(function () {
- website.Tour.waitNextStep(tour, step, overlaps);
+ T.waitNextStep();
if (state.mode === "test") {
setTimeout(function(){
- website.Tour.autoNextStep(tour, step);
- }, website.Tour.defaultDelay);
+ T.autoNextStep();
+ }, T.defaultDelay);
}
}, next.wait || 0);
} else {
- website.Tour.endTour(tour);
+ T.endTour();
}
};
-website.Tour.endTour = function (tour) {
- var state = website.Tour.getState();
+T.endTour = function () {
+ var state = T.getState();
var test = state.step.id >= state.tour.steps.length-1;
- website.Tour.reset();
+ T.reset();
if (test) {
console.log('ok');
} else {
console.log('error');
}
};
-website.Tour.autoNextStep = function (tour, step) {
- clearTimeout(website.Tour.testtimer);
+T.autoNextStep = function (tour, step) {
+ clearTimeout(T.testtimer);
function autoStep () {
if (!step) return;
@@ -361,18 +448,14 @@ website.Tour.autoNextStep = function (tour, step) {
step.autoComplete(tour);
}
- var $popover = $(".popover.tour");
- if ($popover.find("button[data-role='next']:visible").size()) {
- $popover.find("button[data-role='next']:visible").click();
- $popover.remove();
- }
+ T.closePopover();
var $element = $(step.element);
if (!$element.size()) return;
if (step.snippet) {
- website.Tour.autoDragAndDropSnippet($element);
+ T.autoDragAndDropSnippet($element);
} else if (step.sampleText) {
@@ -388,7 +471,7 @@ website.Tour.autoNextStep = function (tour, step) {
setTimeout(function () {
$element.trigger($.Event("keyup", { srcElement: $element }));
$element.trigger($.Event("change", { srcElement: $element }));
- }, website.Tour.defaultDelay<<1);
+ }, T.defaultDelay<<1);
} else if ($element.is(":visible")) {
@@ -406,9 +489,9 @@ website.Tour.autoNextStep = function (tour, step) {
}, 1000);
}
}
- website.Tour.testtimer = setTimeout(autoStep, 100);
+ T.testtimer = setTimeout(autoStep, 100);
};
-website.Tour.autoDragAndDropSnippet = function (selector) {
+T.autoDragAndDropSnippet = function (selector) {
var $thumbnail = $(selector).first();
var thumbnailPosition = $thumbnail.position();
$thumbnail.trigger($.Event("mousedown", { which: 1, pageX: thumbnailPosition.left, pageY: thumbnailPosition.top }));
@@ -418,8 +501,8 @@ website.Tour.autoDragAndDropSnippet = function (selector) {
$dropZone.trigger($.Event("mouseup", { which: 1, pageX: dropPosition.left, pageY: dropPosition.top }));
};
-//$(document).ready(website.Tour.running);
-website.ready().then(website.Tour.running);
+//$(document).ready(T.running);
+website.ready().then(T.running);
}());
From 254b3a29fa80ffcaeec2da60a2a2b0abac8da925 Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Fri, 21 Mar 2014 12:18:15 +0100
Subject: [PATCH 05/26] [IMP] website tour: auto set backdrop if no selector
element
bzr revid: chm@openerp.com-20140321111815-t0312xxl7l83w9rx
---
addons/website/static/src/js/website.tour.banner.js | 2 --
addons/website/static/src/js/website.tour.js | 1 +
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/addons/website/static/src/js/website.tour.banner.js b/addons/website/static/src/js/website.tour.banner.js
index a8abbcf59e2..443405e2401 100644
--- a/addons/website/static/src/js/website.tour.banner.js
+++ b/addons/website/static/src/js/website.tour.banner.js
@@ -13,7 +13,6 @@
title: _t("Welcome to your website!"),
content: _t("This tutorial will guide you to build your home page. We will start by adding a banner."),
popover: { next: _t("Start Tutorial"), end: _t("Skip It") },
- backdrop: true,
},
{
element: 'button[data-action=edit]',
@@ -78,7 +77,6 @@
title: _t("Good Job!"),
content: _t("Well done, you created your homepage."),
popover: { next: _t("Continue") },
- backdrop: true,
},
{
element: 'a[data-action=show-mobile-preview]',
diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js
index 3bfd4e06da0..ce20bf69718 100644
--- a/addons/website/static/src/js/website.tour.js
+++ b/addons/website/static/src/js/website.tour.js
@@ -137,6 +137,7 @@ T.registerSteps = function (tour) {
if (!step.element) {
step.element = "body";
step.orphan = true;
+ step.backdrop = true;
}
}
if (tour.steps[index-1] &&
From 429324999c9fe7149e34ec5f501c14aa7a8a7fdc Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Fri, 21 Mar 2014 12:23:44 +0100
Subject: [PATCH 06/26] [IMP] website tour: remove tag script and css to lib
bootstrap
bzr revid: chm@openerp.com-20140321112344-mwh2p8pp02j9sdq0
---
addons/website/views/website_templates.xml | 2 --
addons/website_report/views/layouts.xml | 2 --
2 files changed, 4 deletions(-)
diff --git a/addons/website/views/website_templates.xml b/addons/website/views/website_templates.xml
index 66a38f09651..7849c701bd4 100644
--- a/addons/website/views/website_templates.xml
+++ b/addons/website/views/website_templates.xml
@@ -253,7 +253,6 @@
-
@@ -265,7 +264,6 @@
-
diff --git a/addons/website_report/views/layouts.xml b/addons/website_report/views/layouts.xml
index 091bb8dd3db..219780317c3 100644
--- a/addons/website_report/views/layouts.xml
+++ b/addons/website_report/views/layouts.xml
@@ -33,7 +33,6 @@
-
@@ -42,7 +41,6 @@
-
From d8f27686e5e70a626d12d4fcfdc6af5e5e642468 Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Fri, 21 Mar 2014 12:57:24 +0100
Subject: [PATCH 07/26] [IMP] website tour: fix test tour
bzr revid: chm@openerp.com-20140321115724-iwu17fkzdzaksmrs
---
addons/website/static/src/js/website.tour.js | 25 ++++++++++----------
1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js
index ce20bf69718..26fa5af0b9f 100644
--- a/addons/website/static/src/js/website.tour.js
+++ b/addons/website/static/src/js/website.tour.js
@@ -313,18 +313,17 @@ T.getState = function () {
};
T.error = function (message) {
var state = T.getState();
+ message += '\n tour: ' + state.id
+ + '\n step: ' + state.step_id + ": '" + (state.step._title || state.step.title) + "'"
+ + '\n href: ' + window.location.href
+ + '\n referrer: ' + document.referrer
+ + '\n element: ' + Boolean(!state.step.element || ($(state.step.element).size() && $(state.step.element).is(":visible") && !$(state.step.element).is(":hidden")))
+ + '\n waitNot: ' + Boolean(!state.step.waitNot || !$(state.step.waitNot).size())
+ + '\n waitFor: ' + Boolean(!state.step.waitFor || $(state.step.waitFor).size())
+ + "\n localStorage: " + JSON.stringify(localStorage)
+ + '\n\n' + $("body").html();
T.reset();
- throw new Error(message +
- + "\ntour: " + state.tour.id +
- + "\nstep: " + state.step.id + ": '" + (state.step._title || state.step.title) + "'"
- + '\nhref: ' + window.location.href
- + '\nreferrer: ' + document.referrer
- + '\nelement: ' + Boolean(!step.element || ($(step.element).size() && $(step.element).is(":visible") && !$(step.element).is(":hidden")))
- + '\nwaitNot: ' + Boolean(!step.waitNot || !$(step.waitNot).size())
- + '\nwaitFor: ' + Boolean(!step.waitFor || $(step.waitFor).size())
- + "\nlocalStorage: " + JSON.stringify(localStorage)
- + '\n\n' + $("body").html()
- );
+ throw new Error(message);
};
T.lists = function () {
var tour_ids = [];
@@ -421,7 +420,7 @@ T.nextStep = function (step) {
T.waitNextStep();
if (state.mode === "test") {
setTimeout(function(){
- T.autoNextStep();
+ T.autoNextStep(state.tour, step);
}, T.defaultDelay);
}
}, next.wait || 0);
@@ -449,7 +448,7 @@ T.autoNextStep = function (tour, step) {
step.autoComplete(tour);
}
- T.closePopover();
+ $(".popover.tour [data-role='next']").click();
var $element = $(step.element);
if (!$element.size()) return;
From 89a6bd06495c4fe599756866828298331f375747 Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Fri, 21 Mar 2014 13:37:22 +0100
Subject: [PATCH 08/26] [IMP] website tour: fix auto test
bzr revid: chm@openerp.com-20140321123722-dmfdckh59cvot00i
---
addons/website/static/src/js/website.tour.js | 4 ++--
.../static/src/js/website.tour.event_sale.js | 4 ++--
addons/website_sale/static/src/js/website.tour.sale.js | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js
index 26fa5af0b9f..a033e6f1ecd 100644
--- a/addons/website/static/src/js/website.tour.js
+++ b/addons/website/static/src/js/website.tour.js
@@ -16,7 +16,7 @@ if (typeof openerp === "undefined") {
var website = window.openerp.website;
// don't rewrite T in test mode
-if (typeof T !== "undefined") {
+if (typeof website.Tour !== "undefined") {
return;
}
@@ -393,7 +393,7 @@ T.waitNextStep = function () {
} else if (!overlaps || new Date().getTime() - time < overlaps) {
T.timer = setTimeout(checkNext, T.defaultDelay);
} else {
- T.error("Can't arrive to the next step");
+ T.error("Can't reach the next step");
}
}
checkNext();
diff --git a/addons/website_event_sale/static/src/js/website.tour.event_sale.js b/addons/website_event_sale/static/src/js/website.tour.event_sale.js
index 92e57638cc8..668a05001af 100644
--- a/addons/website_event_sale/static/src/js/website.tour.event_sale.js
+++ b/addons/website_event_sale/static/src/js/website.tour.event_sale.js
@@ -16,7 +16,7 @@
{
title: "go to register page",
waitNot: 'a[href*="/event"]:contains("Functional Webinar")',
- onload: function () {
+ autoComplete: function () {
// use onload if website_event_track is installed
if (!$('form:contains("Ticket Type")').size()) {
window.location.href = $('a[href*="/event"][href*="/register"]').attr("href");
@@ -43,7 +43,7 @@
title: "Complete checkout",
waitFor: '#top_menu .my_cart_quantity:contains(5)',
element: 'form[action="/shop/confirm_order"] .btn:contains("Confirm")',
- onload: function (tour) {
+ autoComplete: function (tour) {
if ($("input[name='name']").val() === "")
$("input[name='name']").val("website_sale-test-shoptest");
if ($("input[name='email']").val() === "")
diff --git a/addons/website_sale/static/src/js/website.tour.sale.js b/addons/website_sale/static/src/js/website.tour.sale.js
index c7526b2468f..62455e0b811 100644
--- a/addons/website_sale/static/src/js/website.tour.sale.js
+++ b/addons/website_sale/static/src/js/website.tour.sale.js
@@ -50,7 +50,7 @@
{
title: "test with input error",
element: 'form[action="/shop/confirm_order"] .btn:contains("Confirm")',
- onload: function (tour) {
+ autoComplete: function (tour) {
$("input[name='phone']").val("");
},
},
@@ -58,7 +58,7 @@
title: "test without input error",
waitFor: 'form[action="/shop/confirm_order"] .has-error',
element: 'form[action="/shop/confirm_order"] .btn:contains("Confirm")',
- onload: function (tour) {
+ autoComplete: function (tour) {
if ($("input[name='name']").val() === "")
$("input[name='name']").val("website_sale-test-shoptest");
if ($("input[name='email']").val() === "")
From f9b0c7469a7762bbba6d142e7799fc854aa01d24 Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Fri, 21 Mar 2014 14:42:07 +0100
Subject: [PATCH 09/26] [IMP] website tour: change syntax
bzr revid: chm@openerp.com-20140321134207-y54uj2fynl5p0e8a
---
addons/website/static/src/js/website.tour.js | 795 ++++++++++---------
1 file changed, 399 insertions(+), 396 deletions(-)
diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js
index a033e6f1ecd..6a5f8faab76 100644
--- a/addons/website/static/src/js/website.tour.js
+++ b/addons/website/static/src/js/website.tour.js
@@ -84,421 +84,424 @@ $.ajaxSetup({
var localStorage = window.localStorage;
-var T = website.Tour = {};
-T.tours = {};
-T.defaultDelay = 50;
-T.errorDelay = 5000;
-T.state = null;
-T.$element = null;
-T.timer = null;
-T.testtimer = null;
-T.currentTimer = null;
-T.register = function (tour) {
- if (tour.mode !== "test") tour.mode = "tutorial";
- T.tours[tour.id] = tour;
-};
-T.run = function (tour_id, mode) {
- if (localStorage.getItem("tour") && mode === "test") { // only one test running
- return;
- }
- var tour = T.tours[tour_id];
- T.saveState(tour.id, mode || tour.mode, 0);
- if (tour.path && !window.location.href.match(new RegExp("("+T.getLang()+")?"+tour.path+"#?$", "i"))) {
- window.location.href = "/"+T.getLang()+tour.path;
- } else {
- T.running();
- }
-};
-T.registerSteps = function (tour) {
- if (tour.register) {
- return;
- }
- tour.register = true;
-
- for (var index=0, len=tour.steps.length; index 0 && tour.steps[index-1] &&
- tour.steps[index-1].popover && tour.steps[index-1].popover.next) {
- step.waitNot = '.popover.tour.fade.in:visible';
+var T = website.Tour = {
+ tours: {},
+ defaultDelay: 50,
+ errorDelay: 5000,
+ state: null,
+ $element: null,
+ timer: null,
+ testtimer: null,
+ currentTimer: null,
+ register: function (tour) {
+ if (tour.mode !== "test") tour.mode = "tutorial";
+ T.tours[tour.id] = tour;
+ },
+ run: function (tour_id, mode) {
+ if (localStorage.getItem("tour") && mode === "test") { // only one test running
+ return;
}
- if (!step.waitFor && index > 0 && tour.steps[index-1].snippet) {
- step.waitFor = '.oe_overlay_options .oe_options:visible';
+ var tour = T.tours[tour_id];
+ T.saveState(tour.id, mode || tour.mode, 0);
+ if (tour.path && !window.location.href.match(new RegExp("("+T.getLang()+")?"+tour.path+"#?$", "i"))) {
+ window.location.href = "/"+T.getLang()+tour.path;
+ } else {
+ T.running();
}
-
- var snippet = step.element && step.element.match(/#oe_snippets (.*) \.oe_snippet_thumbnail/);
- if (snippet) {
- step.snippet = snippet[1];
- } else if (step.snippet) {
- step.element = '#oe_snippets '+step.snippet+' .oe_snippet_thumbnail';
+ },
+ registerSteps: function (tour) {
+ if (tour.register) {
+ return;
}
+ tour.register = true;
- if (!step.element) {
- step.element = "body";
- step.orphan = true;
- step.backdrop = true;
- }
- }
- if (tour.steps[index-1] &&
- tour.steps[index-1].popover && tour.steps[index-1].popover.next) {
- var step = {
- id: index,
- waitNot: '.popover.tour.fade.in:visible'
- };
- tour.steps.push(step);
- }
-
- // rendering bootstrap tour and popover
- if (tour.mode !== "test") {
for (var index=0, len=tour.steps.length; index');
- }
-
- if (step.backdrop || $element.parents("#website-top-navbar, .modal").size()) {
- $tip.css("z-index", 2010);
- }
-
- // button click event
- $tip.find("button")
- .one("click", function () {
- step.busy = true;
- if (!$(this).is("[data-role='next']")) {
- clearTimeout(T.timer);
- T.endTour();
+ if (!step.waitNot && index > 0 && tour.steps[index-1] &&
+ tour.steps[index-1].popover && tour.steps[index-1].popover.next) {
+ step.waitNot = '.popover.tour.fade.in:visible';
+ }
+ if (!step.waitFor && index > 0 && tour.steps[index-1].snippet) {
+ step.waitFor = '.oe_overlay_options .oe_options:visible';
}
- T.closePopover();
- });
- T.repositionPopover();
-};
-T.repositionPopover = function() {
- var popover = T.$element.data("bs.popover");
- var $tip = T.$element.data("bs.popover").tip();
+ var snippet = step.element && step.element.match(/#oe_snippets (.*) \.oe_snippet_thumbnail/);
+ if (snippet) {
+ step.snippet = snippet[1];
+ } else if (step.snippet) {
+ step.element = '#oe_snippets '+step.snippet+' .oe_snippet_thumbnail';
+ }
- if (popover.options.orphan) {
- return $tip.css("top", $(window).outerHeight() / 2 - $tip.outerHeight() / 2);
- }
-
- var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset;
- offsetWidth = $tip[0].offsetWidth;
- offsetHeight = $tip[0].offsetHeight;
- tipOffset = $tip.offset();
- originalLeft = tipOffset.left;
- originalTop = tipOffset.top;
- offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight();
- if (offsetBottom < 0) {
- tipOffset.top = tipOffset.top + offsetBottom;
- }
- offsetRight = $("html").outerWidth() - tipOffset.left - $tip.outerWidth();
- if (offsetRight < 0) {
- tipOffset.left = tipOffset.left + offsetRight;
- }
- if (tipOffset.top < 0) {
- tipOffset.top = 0;
- }
- if (tipOffset.left < 0) {
- tipOffset.left = 0;
- }
- $tip.offset(tipOffset);
- if (popover.options.placement === "bottom" || popover.options.placement === "top") {
- var left = T.$element.offset().left + T.$element.outerWidth()/2 - tipOffset.left;
- $tip.find(".arrow").css("left", left ? left + "px" : "");
- } else {
- var top = T.$element.offset().top + T.$element.outerHeight()/2 - tipOffset.top;
- $tip.find(".arrow").css("top", top ? top + "px" : "");
- }
-};
-T.popoverTitle = function (tour, options) {
- return openerp.qweb.render('website.tour_popover_title', options);
-};
-T.popover = function (options) {
- return openerp.qweb.render('website.tour_popover', options);
-};
-T.getLang = function () {
- return $("html").attr("lang").replace(/-/, '_');
-};
-T.getState = function () {
- var state = JSON.parse(localStorage.getItem("tour") || 'false') || {};
- var tour_id,mode,step_id;
- if (!state.id && window.location.href.indexOf("#tutorial.") > -1) {
- state = {
- "id": window.location.href.match(/#tutorial\.(.*)=true/)[1],
- "mode": "tutorial",
- "step_id": 0
- };
- }
- if (!state.id) {
- return;
- }
- state.tour = T.tours[state.id];
- state.step = state.tour.steps[state.step_id];
- return state;
-};
-T.error = function (message) {
- var state = T.getState();
- message += '\n tour: ' + state.id
- + '\n step: ' + state.step_id + ": '" + (state.step._title || state.step.title) + "'"
- + '\n href: ' + window.location.href
- + '\n referrer: ' + document.referrer
- + '\n element: ' + Boolean(!state.step.element || ($(state.step.element).size() && $(state.step.element).is(":visible") && !$(state.step.element).is(":hidden")))
- + '\n waitNot: ' + Boolean(!state.step.waitNot || !$(state.step.waitNot).size())
- + '\n waitFor: ' + Boolean(!state.step.waitFor || $(state.step.waitFor).size())
- + "\n localStorage: " + JSON.stringify(localStorage)
- + '\n\n' + $("body").html();
- T.reset();
- throw new Error(message);
-};
-T.lists = function () {
- var tour_ids = [];
- for (var k in T.tours) {
- tour_ids.push(k);
- }
- return tour_ids;
-};
-T.saveState = function (tour_id, mode, step_id) {
- localStorage.setItem("tour", JSON.stringify({"id":tour_id, "mode":mode, "step_id":step_id || 0}));
-};
-T.reset = function () {
- var state = T.getState();
- if (state) {
- for (var k in state.tour.steps) {
- state.tour.steps[k].busy = false;
+ if (!step.element) {
+ step.element = "body";
+ step.orphan = true;
+ step.backdrop = true;
+ }
}
- }
- localStorage.removeItem("tour");
- clearTimeout(T.timer);
- clearTimeout(T.testtimer);
- T.closePopover();
-};
-T.running = function () {
- var state = T.getState();
- if (state) {
- T.registerSteps(state.tour);
- if ($.ajaxBusy) {
- $(document).ajaxStop(function() {
- setTimeout(function () {
- T.nextStep();
- },0);
+ if (tour.steps[index-1] &&
+ tour.steps[index-1].popover && tour.steps[index-1].popover.next) {
+ var step = {
+ id: index,
+ waitNot: '.popover.tour.fade.in:visible'
+ };
+ tour.steps.push(step);
+ }
+
+ // rendering bootstrap tour and popover
+ if (tour.mode !== "test") {
+ for (var index=0, len=tour.steps.length; index
');
+ }
+
+ if (step.backdrop || $element.parents("#website-top-navbar, .modal").size()) {
+ $tip.css("z-index", 2010);
+ }
+
+ // button click event
+ $tip.find("button")
+ .one("click", function () {
+ step.busy = true;
+ if (!$(this).is("[data-role='next']")) {
+ clearTimeout(T.timer);
+ T.endTour();
+ }
+ T.closePopover();
});
- } else {
- T.nextStep();
- }
- }
-};
-T.check = function (step) {
- return (step &&
- (!step.element || ($(step.element).size() && $(step.element).is(":visible") && !$(step.element).is(":hidden"))) &&
- (!step.waitNot || !$(step.waitNot).size()) &&
- (!step.waitFor || $(step.waitFor).size()));
-};
-T.waitNextStep = function () {
- var state = T.getState();
- var time = new Date().getTime();
- var timer;
- var next = state.tour.steps[state.step.id+1];
- var overlaps = state.mode === "test" ? T.errorDelay : 0;
- window.onbeforeunload = function () {
+ T.repositionPopover();
+ },
+ repositionPopover: function() {
+ var popover = T.$element.data("bs.popover");
+ var $tip = T.$element.data("bs.popover").tip();
+
+ if (popover.options.orphan) {
+ return $tip.css("top", $(window).outerHeight() / 2 - $tip.outerHeight() / 2);
+ }
+
+ var offsetBottom, offsetHeight, offsetRight, offsetWidth, originalLeft, originalTop, tipOffset;
+ offsetWidth = $tip[0].offsetWidth;
+ offsetHeight = $tip[0].offsetHeight;
+ tipOffset = $tip.offset();
+ originalLeft = tipOffset.left;
+ originalTop = tipOffset.top;
+ offsetBottom = $(document).outerHeight() - tipOffset.top - $tip.outerHeight();
+ if (offsetBottom < 0) {
+ tipOffset.top = tipOffset.top + offsetBottom;
+ }
+ offsetRight = $("html").outerWidth() - tipOffset.left - $tip.outerWidth();
+ if (offsetRight < 0) {
+ tipOffset.left = tipOffset.left + offsetRight;
+ }
+ if (tipOffset.top < 0) {
+ tipOffset.top = 0;
+ }
+ if (tipOffset.left < 0) {
+ tipOffset.left = 0;
+ }
+ $tip.offset(tipOffset);
+ if (popover.options.placement === "bottom" || popover.options.placement === "top") {
+ var left = T.$element.offset().left + T.$element.outerWidth()/2 - tipOffset.left;
+ $tip.find(".arrow").css("left", left ? left + "px" : "");
+ } else if (popover.options.placement !== "auto") {
+ var top = T.$element.offset().top + T.$element.outerHeight()/2 - tipOffset.top;
+ $tip.find(".arrow").css("top", top ? top + "px" : "");
+ }
+ },
+ popoverTitle: function (tour, options) {
+ return openerp.qweb.render('website.tour_popover_title', options);
+ },
+ popover: function (options) {
+ return openerp.qweb.render('website.tour_popover', options);
+ },
+ getLang: function () {
+ return $("html").attr("lang").replace(/-/, '_');
+ },
+ getState: function () {
+ var state = JSON.parse(localStorage.getItem("tour") || 'false') || {};
+ var tour_id,mode,step_id;
+ if (!state.id && window.location.href.indexOf("#tutorial.") > -1) {
+ state = {
+ "id": window.location.href.match(/#tutorial\.(.*)=true/)[1],
+ "mode": "tutorial",
+ "step_id": 0
+ };
+ window.location.hash = "";
+ T.saveState(state.id, state.mode, state.step_id);
+ }
+ if (!state.id) {
+ return;
+ }
+ state.tour = T.tours[state.id];
+ state.step = state.tour.steps[state.step_id];
+ return state;
+ },
+ error: function (message) {
+ var state = T.getState();
+ message += '\n tour: ' + state.id
+ + '\n step: ' + state.step_id + ": '" + (state.step._title || state.step.title) + "'"
+ + '\n href: ' + window.location.href
+ + '\n referrer: ' + document.referrer
+ + '\n element: ' + Boolean(!state.step.element || ($(state.step.element).size() && $(state.step.element).is(":visible") && !$(state.step.element).is(":hidden")))
+ + '\n waitNot: ' + Boolean(!state.step.waitNot || !$(state.step.waitNot).size())
+ + '\n waitFor: ' + Boolean(!state.step.waitFor || $(state.step.waitFor).size())
+ + "\n localStorage: " + JSON.stringify(localStorage)
+ + '\n\n' + $("body").html();
+ T.reset();
+ throw new Error(message);
+ },
+ lists: function () {
+ var tour_ids = [];
+ for (var k in T.tours) {
+ tour_ids.push(k);
+ }
+ return tour_ids;
+ },
+ saveState: function (tour_id, mode, step_id) {
+ localStorage.setItem("tour", JSON.stringify({"id":tour_id, "mode":mode, "step_id":step_id || 0}));
+ },
+ reset: function () {
+ var state = T.getState();
+ if (state) {
+ for (var k in state.tour.steps) {
+ state.tour.steps[k].busy = false;
+ }
+ }
+ localStorage.removeItem("tour");
clearTimeout(T.timer);
clearTimeout(T.testtimer);
- };
-
- function checkNext () {
- T.autoTogglePopover();
-
- clearTimeout(T.timer);
- if (T.check(next)) {
- clearTimeout(T.currentTimer);
- // use an other timeout for cke dom loading
- setTimeout(function () {
- T.nextStep(next);
- }, T.defaultDelay);
- } else if (!overlaps || new Date().getTime() - time < overlaps) {
- T.timer = setTimeout(checkNext, T.defaultDelay);
- } else {
- T.error("Can't reach the next step");
- }
- }
- checkNext();
-};
-T.nextStep = function (step) {
- var state = T.getState();
-
- if (!state) {
- return;
- }
-
- step = step || state.step;
- T.saveState(state.id, state.mode, step.id);
-
- T.autoTogglePopover(true);
-
- if (step.onload) {
- step.onload();
- }
-
- var next = state.tour.steps[step.id+1];
- if (next) {
- setTimeout(function () {
- T.waitNextStep();
- if (state.mode === "test") {
- setTimeout(function(){
- T.autoNextStep(state.tour, step);
- }, T.defaultDelay);
- }
- }, next.wait || 0);
- } else {
- T.endTour();
- }
-};
-T.endTour = function () {
- var state = T.getState();
- var test = state.step.id >= state.tour.steps.length-1;
- T.reset();
- if (test) {
- console.log('ok');
- } else {
- console.log('error');
- }
-};
-T.autoNextStep = function (tour, step) {
- clearTimeout(T.testtimer);
-
- function autoStep () {
- if (!step) return;
-
- if (step.autoComplete) {
- step.autoComplete(tour);
- }
-
- $(".popover.tour [data-role='next']").click();
-
- var $element = $(step.element);
- if (!$element.size()) return;
-
- if (step.snippet) {
-
- T.autoDragAndDropSnippet($element);
-
- } else if (step.sampleText) {
-
- $element.trigger($.Event("keydown", { srcElement: $element }));
- if ($element.is("input") ) {
- $element.val(step.sampleText);
- } if ($element.is("select")) {
- $element.find("[value='"+step.sampleText+"'], option:contains('"+step.sampleText+"')").attr("selected", true);
- $element.val(step.sampleText);
+ T.closePopover();
+ },
+ running: function () {
+ var state = T.getState();
+ if (state) {
+ T.registerSteps(state.tour);
+ if ($.ajaxBusy) {
+ $(document).ajaxStop(function() {
+ setTimeout(function () {
+ T.nextStep();
+ },0);
+ });
} else {
- $element.html(step.sampleText);
+ T.nextStep();
}
- setTimeout(function () {
- $element.trigger($.Event("keyup", { srcElement: $element }));
- $element.trigger($.Event("change", { srcElement: $element }));
- }, T.defaultDelay<<1);
-
- } else if ($element.is(":visible")) {
-
- $element.trigger($.Event("mouseenter", { srcElement: $element[0] }));
- $element.trigger($.Event("mousedown", { srcElement: $element[0] }));
-
- var evt = document.createEvent("MouseEvents");
- evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
- $element[0].dispatchEvent(evt);
-
- // trigger after for step like: mouseenter, next step click on button display with mouseenter
- setTimeout(function () {
- $element.trigger($.Event("mouseup", { srcElement: $element[0] }));
- $element.trigger($.Event("mouseleave", { srcElement: $element[0] }));
- }, 1000);
}
+ },
+ check: function (step) {
+ return (step &&
+ (!step.element || ($(step.element).size() && $(step.element).is(":visible") && !$(step.element).is(":hidden"))) &&
+ (!step.waitNot || !$(step.waitNot).size()) &&
+ (!step.waitFor || $(step.waitFor).size()));
+ },
+ waitNextStep: function () {
+ var state = T.getState();
+ var time = new Date().getTime();
+ var timer;
+ var next = state.tour.steps[state.step.id+1];
+ var overlaps = state.mode === "test" ? T.errorDelay : 0;
+
+ window.onbeforeunload = function () {
+ clearTimeout(T.timer);
+ clearTimeout(T.testtimer);
+ };
+
+ function checkNext () {
+ T.autoTogglePopover();
+
+ clearTimeout(T.timer);
+ if (T.check(next)) {
+ clearTimeout(T.currentTimer);
+ // use an other timeout for cke dom loading
+ setTimeout(function () {
+ T.nextStep(next);
+ }, T.defaultDelay);
+ } else if (!overlaps || new Date().getTime() - time < overlaps) {
+ T.timer = setTimeout(checkNext, T.defaultDelay);
+ } else {
+ T.error("Can't reach the next step");
+ }
+ }
+ checkNext();
+ },
+ nextStep: function (step) {
+ var state = T.getState();
+
+ if (!state) {
+ return;
+ }
+
+ step = step || state.step;
+ T.saveState(state.id, state.mode, step.id);
+
+ T.autoTogglePopover(true);
+
+ if (step.onload) {
+ step.onload();
+ }
+
+ var next = state.tour.steps[step.id+1];
+ if (next) {
+ setTimeout(function () {
+ T.waitNextStep();
+ if (state.mode === "test") {
+ setTimeout(function(){
+ T.autoNextStep(state.tour, step);
+ }, T.defaultDelay);
+ }
+ }, next.wait || 0);
+ } else {
+ T.endTour();
+ }
+ },
+ endTour: function () {
+ var state = T.getState();
+ var test = state.step.id >= state.tour.steps.length-1;
+ T.reset();
+ if (test) {
+ console.log('ok');
+ } else {
+ console.log('error');
+ }
+ },
+ autoNextStep: function (tour, step) {
+ clearTimeout(T.testtimer);
+
+ function autoStep () {
+ if (!step) return;
+
+ if (step.autoComplete) {
+ step.autoComplete(tour);
+ }
+
+ $(".popover.tour [data-role='next']").click();
+
+ var $element = $(step.element);
+ if (!$element.size()) return;
+
+ if (step.snippet) {
+
+ T.autoDragAndDropSnippet($element);
+
+ } else if (step.sampleText) {
+
+ $element.trigger($.Event("keydown", { srcElement: $element }));
+ if ($element.is("input") ) {
+ $element.val(step.sampleText);
+ } if ($element.is("select")) {
+ $element.find("[value='"+step.sampleText+"'], option:contains('"+step.sampleText+"')").attr("selected", true);
+ $element.val(step.sampleText);
+ } else {
+ $element.html(step.sampleText);
+ }
+ setTimeout(function () {
+ $element.trigger($.Event("keyup", { srcElement: $element }));
+ $element.trigger($.Event("change", { srcElement: $element }));
+ }, T.defaultDelay<<1);
+
+ } else if ($element.is(":visible")) {
+
+ $element.trigger($.Event("mouseenter", { srcElement: $element[0] }));
+ $element.trigger($.Event("mousedown", { srcElement: $element[0] }));
+
+ var evt = document.createEvent("MouseEvents");
+ evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ $element[0].dispatchEvent(evt);
+
+ // trigger after for step like: mouseenter, next step click on button display with mouseenter
+ setTimeout(function () {
+ $element.trigger($.Event("mouseup", { srcElement: $element[0] }));
+ $element.trigger($.Event("mouseleave", { srcElement: $element[0] }));
+ }, 1000);
+ }
+ }
+ T.testtimer = setTimeout(autoStep, 100);
+ },
+ autoDragAndDropSnippet: function (selector) {
+ var $thumbnail = $(selector).first();
+ var thumbnailPosition = $thumbnail.position();
+ $thumbnail.trigger($.Event("mousedown", { which: 1, pageX: thumbnailPosition.left, pageY: thumbnailPosition.top }));
+ $thumbnail.trigger($.Event("mousemove", { which: 1, pageX: document.body.scrollWidth/2, pageY: document.body.scrollHeight/2 }));
+ var $dropZone = $(".oe_drop_zone").first();
+ var dropPosition = $dropZone.position();
+ $dropZone.trigger($.Event("mouseup", { which: 1, pageX: dropPosition.left, pageY: dropPosition.top }));
}
- T.testtimer = setTimeout(autoStep, 100);
-};
-T.autoDragAndDropSnippet = function (selector) {
- var $thumbnail = $(selector).first();
- var thumbnailPosition = $thumbnail.position();
- $thumbnail.trigger($.Event("mousedown", { which: 1, pageX: thumbnailPosition.left, pageY: thumbnailPosition.top }));
- $thumbnail.trigger($.Event("mousemove", { which: 1, pageX: document.body.scrollWidth/2, pageY: document.body.scrollHeight/2 }));
- var $dropZone = $(".oe_drop_zone").first();
- var dropPosition = $dropZone.position();
- $dropZone.trigger($.Event("mouseup", { which: 1, pageX: dropPosition.left, pageY: dropPosition.top }));
};
//$(document).ready(T.running);
From 24d37e284407a26987b1be3e539fa0243d81f656 Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Fri, 21 Mar 2014 14:45:46 +0100
Subject: [PATCH 10/26] [FIX] website tour: template loading hide the real
error
bzr revid: chm@openerp.com-20140321134546-i5nw73en8thzrwc2
---
addons/website/static/src/js/website.tour.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js
index 6a5f8faab76..eed431e071b 100644
--- a/addons/website/static/src/js/website.tour.js
+++ b/addons/website/static/src/js/website.tour.js
@@ -286,10 +286,10 @@ var T = website.Tour = {
}
},
popoverTitle: function (tour, options) {
- return openerp.qweb.render('website.tour_popover_title', options);
+ return openerp.qweb ? openerp.qweb.render('website.tour_popover_title', options) : options.title;
},
popover: function (options) {
- return openerp.qweb.render('website.tour_popover', options);
+ return openerp.qweb ? openerp.qweb.render('website.tour_popover', options) : options.title;
},
getLang: function () {
return $("html").attr("lang").replace(/-/, '_');
From 62814f9c2331340a5721331d652b0fdc0d2a201d Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Mon, 24 Mar 2014 09:11:12 +0100
Subject: [PATCH 11/26] [FIX] website: activate new tour tests
bzr revid: chm@openerp.com-20140324081112-15n58puu29weydme
---
addons/website/tests/test_ui.py | 2 +-
addons/website_blog/tests/test_ui.py | 2 +-
addons/website_event/tests/test_ui.py | 2 +-
addons/website_event_sale/tests/test_ui.py | 6 +++---
addons/website_sale/tests/test_ui.py | 8 ++++----
5 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/addons/website/tests/test_ui.py b/addons/website/tests/test_ui.py
index 54cd8a73a67..7eb88d00df3 100644
--- a/addons/website/tests/test_ui.py
+++ b/addons/website/tests/test_ui.py
@@ -8,6 +8,6 @@ class TestUi(openerp.tests.HttpCase):
self.phantom_js("/", "console.log('ok')", "openerp.website.editor", login='admin')
def test_04_admin_tour_banner(self):
- self.phantom_js("/", "openerp.website.Tour.run_test('banner')", "openerp.website.Tour.tours.banner", login='admin')
+ self.phantom_js("/", "openerp.website.Tour.run('banner', 'test')", "openerp.website.Tour.tours.banner", login='admin')
# vim:et:
diff --git a/addons/website_blog/tests/test_ui.py b/addons/website_blog/tests/test_ui.py
index e99884ba4b1..35b7fdc56e7 100644
--- a/addons/website_blog/tests/test_ui.py
+++ b/addons/website_blog/tests/test_ui.py
@@ -2,5 +2,5 @@ import openerp.tests
class TestUi(openerp.tests.HttpCase):
def test_admin(self):
- self.phantom_js("/", "openerp.website.Tour.run_test('blog')", "openerp.website.Tour")
+ self.phantom_js("/", "openerp.website.Tour.run('blog', 'test')", "openerp.website.Tour")
diff --git a/addons/website_event/tests/test_ui.py b/addons/website_event/tests/test_ui.py
index c4e884c0325..b59cdd94dcc 100644
--- a/addons/website_event/tests/test_ui.py
+++ b/addons/website_event/tests/test_ui.py
@@ -2,5 +2,5 @@ import openerp.tests
class TestUi(openerp.tests.HttpCase):
def test_admin(self):
- self.phantom_js("/", "openerp.website.Tour.run_test('event')", "openerp.website.Tour")
+ self.phantom_js("/", "openerp.website.Tour.run('event', 'test')", "openerp.website.Tour")
diff --git a/addons/website_event_sale/tests/test_ui.py b/addons/website_event_sale/tests/test_ui.py
index b5950aaec54..b204b2bad69 100644
--- a/addons/website_event_sale/tests/test_ui.py
+++ b/addons/website_event_sale/tests/test_ui.py
@@ -9,11 +9,11 @@ inject = [
@openerp.tests.common.post_install(True)
class TestUi(openerp.tests.HttpCase):
def test_admin(self):
- self.phantom_js("/", "openerp.website.Tour.run_test('event_buy_tickets')", "openerp.website.Tour", inject=inject)
+ self.phantom_js("/", "openerp.website.Tour.run('event_buy_tickets', 'test')", "openerp.website.Tour", inject=inject)
def test_demo(self):
- self.phantom_js("/", "openerp.website.Tour.run_test('event_buy_tickets')", "openerp.website.Tour", login="demo", password="demo", inject=inject);
+ self.phantom_js("/", "openerp.website.Tour.run('event_buy_tickets', 'test')", "openerp.website.Tour", login="demo", password="demo", inject=inject);
def test_public(self):
- self.phantom_js("/", "openerp.website.Tour.run_test('event_buy_tickets')", "openerp.website.Tour", login=None, inject=inject);
+ self.phantom_js("/", "openerp.website.Tour.run('event_buy_tickets', 'test')", "openerp.website.Tour", login=None, inject=inject);
diff --git a/addons/website_sale/tests/test_ui.py b/addons/website_sale/tests/test_ui.py
index 0eb5daae97a..0cedf2d0409 100644
--- a/addons/website_sale/tests/test_ui.py
+++ b/addons/website_sale/tests/test_ui.py
@@ -11,13 +11,13 @@ inject = [
@openerp.tests.common.post_install(True)
class TestUi(openerp.tests.HttpCase):
def test_01_admin_shop_tour(self):
- self.phantom_js("/", "openerp.website.Tour.run_test('shop')", "openerp.website.Tour.Shop", login="admin")
+ self.phantom_js("/", "openerp.website.Tour.run('shop', 'test')", "openerp.website.Tour.Shop", login="admin")
def test_02_admin_checkout(self):
- self.phantom_js("/", "openerp.website.Tour.run_test('shop_buy_product')", "openerp.website.Tour.ShopTest", login="admin", inject=inject)
+ self.phantom_js("/", "openerp.website.Tour.run('shop_buy_product', 'test')", "openerp.website.Tour.ShopTest", login="admin", inject=inject)
def test_03_demo_checkout(self):
- self.phantom_js("/", "openerp.website.Tour.run_test('shop_buy_product')", "openerp.website.Tour.ShopTest", login="demo", inject=inject)
+ self.phantom_js("/", "openerp.website.Tour.run('shop_buy_product', 'test')", "openerp.website.Tour.ShopTest", login="demo", inject=inject)
def test_04_public_checkout(self):
- self.phantom_js("/", "openerp.website.Tour.run_test('shop_buy_product')", "openerp.website.Tour.ShopTest", inject=inject)
+ self.phantom_js("/", "openerp.website.Tour.run('shop_buy_product', 'test')", "openerp.website.Tour.ShopTest", inject=inject)
From b28a32f6ef398347ed0a207762a75c98a2d5a5b1 Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Wed, 26 Mar 2014 15:44:42 +0100
Subject: [PATCH 12/26] [FIX] website: test_ui running
bzr revid: chm@openerp.com-20140326144442-ye2a51f03wyaxi8a
---
addons/website_blog/tests/test_ui.py | 2 +-
addons/website_event/tests/test_ui.py | 2 +-
addons/website_event_sale/tests/test_ui.py | 6 +++---
addons/website_sale/tests/test_ui.py | 10 +++++-----
4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/addons/website_blog/tests/test_ui.py b/addons/website_blog/tests/test_ui.py
index 35b7fdc56e7..b34ef25c002 100644
--- a/addons/website_blog/tests/test_ui.py
+++ b/addons/website_blog/tests/test_ui.py
@@ -2,5 +2,5 @@ import openerp.tests
class TestUi(openerp.tests.HttpCase):
def test_admin(self):
- self.phantom_js("/", "openerp.website.Tour.run('blog', 'test')", "openerp.website.Tour")
+ self.phantom_js("/", "openerp.website.Tour.run('blog', 'test')", "openerp.website.Tour.tours.blog")
diff --git a/addons/website_event/tests/test_ui.py b/addons/website_event/tests/test_ui.py
index b59cdd94dcc..96a17a91563 100644
--- a/addons/website_event/tests/test_ui.py
+++ b/addons/website_event/tests/test_ui.py
@@ -2,5 +2,5 @@ import openerp.tests
class TestUi(openerp.tests.HttpCase):
def test_admin(self):
- self.phantom_js("/", "openerp.website.Tour.run('event', 'test')", "openerp.website.Tour")
+ self.phantom_js("/", "openerp.website.Tour.run('event', 'test')", "openerp.website.Tour.tours.event")
diff --git a/addons/website_event_sale/tests/test_ui.py b/addons/website_event_sale/tests/test_ui.py
index b204b2bad69..3e26fba5cf4 100644
--- a/addons/website_event_sale/tests/test_ui.py
+++ b/addons/website_event_sale/tests/test_ui.py
@@ -9,11 +9,11 @@ inject = [
@openerp.tests.common.post_install(True)
class TestUi(openerp.tests.HttpCase):
def test_admin(self):
- self.phantom_js("/", "openerp.website.Tour.run('event_buy_tickets', 'test')", "openerp.website.Tour", inject=inject)
+ self.phantom_js("/", "openerp.website.Tour.run('event_buy_tickets', 'test')", "openerp.website.Tour.tours.event_buy_tickets", inject=inject)
def test_demo(self):
- self.phantom_js("/", "openerp.website.Tour.run('event_buy_tickets', 'test')", "openerp.website.Tour", login="demo", password="demo", inject=inject);
+ self.phantom_js("/", "openerp.website.Tour.run('event_buy_tickets', 'test')", "openerp.website.Tour.tours.event_buy_tickets", login="demo", password="demo", inject=inject);
def test_public(self):
- self.phantom_js("/", "openerp.website.Tour.run('event_buy_tickets', 'test')", "openerp.website.Tour", login=None, inject=inject);
+ self.phantom_js("/", "openerp.website.Tour.run('event_buy_tickets', 'test')", "openerp.website.Tour.tours.event_buy_tickets", login=None, inject=inject);
diff --git a/addons/website_sale/tests/test_ui.py b/addons/website_sale/tests/test_ui.py
index 0cedf2d0409..61b0e904abf 100644
--- a/addons/website_sale/tests/test_ui.py
+++ b/addons/website_sale/tests/test_ui.py
@@ -4,20 +4,20 @@ import openerp.tests
inject = [
("openerp.website.Tour", os.path.join(os.path.dirname(__file__), '../../website/static/src/js/website.tour.js')),
- ("openerp.website.Tour.ShopTest", os.path.join(os.path.dirname(__file__), "../static/src/js/website.tour.sale.js")),
+ ("openerp.website.Tour.tours.shop_buy_product", os.path.join(os.path.dirname(__file__), "../static/src/js/website.tour.sale.js")),
]
@openerp.tests.common.at_install(False)
@openerp.tests.common.post_install(True)
class TestUi(openerp.tests.HttpCase):
def test_01_admin_shop_tour(self):
- self.phantom_js("/", "openerp.website.Tour.run('shop', 'test')", "openerp.website.Tour.Shop", login="admin")
+ self.phantom_js("/", "openerp.website.Tour.run('shop', 'test')", "openerp.website.Tour.tours.shop", login="admin")
def test_02_admin_checkout(self):
- self.phantom_js("/", "openerp.website.Tour.run('shop_buy_product', 'test')", "openerp.website.Tour.ShopTest", login="admin", inject=inject)
+ self.phantom_js("/", "openerp.website.Tour.run('shop_buy_product', 'test')", "openerp.website.Tour.tours.shop_buy_product", login="admin", inject=inject)
def test_03_demo_checkout(self):
- self.phantom_js("/", "openerp.website.Tour.run('shop_buy_product', 'test')", "openerp.website.Tour.ShopTest", login="demo", inject=inject)
+ self.phantom_js("/", "openerp.website.Tour.run('shop_buy_product', 'test')", "openerp.website.Tour.tours.shop_buy_product", login="demo", inject=inject)
def test_04_public_checkout(self):
- self.phantom_js("/", "openerp.website.Tour.run('shop_buy_product', 'test')", "openerp.website.Tour.ShopTest", inject=inject)
+ self.phantom_js("/", "openerp.website.Tour.run('shop_buy_product', 'test')", "openerp.website.Tour.tours.shop_buy_product", inject=inject)
From fd593a3049407103165e4a872e92b9d39f641578 Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Mon, 31 Mar 2014 17:12:37 +0200
Subject: [PATCH 13/26] [FIX] website_sale: test tour and activate
website_event_sale test
bzr revid: chm@openerp.com-20140331151237-ec0j7ywfsbjsw83k
---
addons/website/static/src/js/website.tour.js | 17 +++++++++--------
addons/website_event_sale/tests/__init__.py | 2 +-
addons/website_event_sale/tests/test_ui.py | 6 ++++--
3 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js
index eed431e071b..1a4a987739f 100644
--- a/addons/website/static/src/js/website.tour.js
+++ b/addons/website/static/src/js/website.tour.js
@@ -306,7 +306,7 @@ var T = website.Tour = {
window.location.hash = "";
T.saveState(state.id, state.mode, state.step_id);
}
- if (!state.id) {
+ if (!state.id || !T.tours[state.id]) {
return;
}
state.tour = T.tours[state.id];
@@ -349,20 +349,21 @@ var T = website.Tour = {
clearTimeout(T.testtimer);
T.closePopover();
},
+ testRunning: 0,
running: function () {
- var state = T.getState();
- if (state) {
- T.registerSteps(state.tour);
+ setTimeout(function () {
if ($.ajaxBusy) {
$(document).ajaxStop(function() {
- setTimeout(function () {
- T.nextStep();
- },0);
+ var state = T.getState();
+ T.registerSteps(state.tour);
+ T.nextStep();
});
} else {
+ var state = T.getState();
+ T.registerSteps(state.tour);
T.nextStep();
}
- }
+ },0);
},
check: function (step) {
return (step &&
diff --git a/addons/website_event_sale/tests/__init__.py b/addons/website_event_sale/tests/__init__.py
index c9d4e3399ba..bf8ba6321ad 100644
--- a/addons/website_event_sale/tests/__init__.py
+++ b/addons/website_event_sale/tests/__init__.py
@@ -1 +1 @@
-#import test_ui
+import test_ui
diff --git a/addons/website_event_sale/tests/test_ui.py b/addons/website_event_sale/tests/test_ui.py
index 3e26fba5cf4..fccbabb9d18 100644
--- a/addons/website_event_sale/tests/test_ui.py
+++ b/addons/website_event_sale/tests/test_ui.py
@@ -1,8 +1,10 @@
+import os
+
import openerp.tests
inject = [
- "./../../../website/static/src/js/website.tour.test.js",
- "./../../../website_event_sale/static/src/js/website.tour.event_sale.js",
+ ("openerp.website.Tour", os.path.join(os.path.dirname(__file__), '../../website/static/src/js/website.tour.js')),
+ ("openerp.website.Tour.tours.event_buy_tickets", os.path.join(os.path.dirname(__file__), "../static/src/js/website.tour.event_sale.js")),
]
@openerp.tests.common.at_install(False)
From f4225eda24d7ccd8485c778d917b43409e8e64fa Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Tue, 8 Apr 2014 14:41:19 +0200
Subject: [PATCH 14/26] [FIX] website test tour
bzr revid: chm@openerp.com-20140408124119-jkmeh5vfdb3sjlna
---
addons/website/static/src/js/website.tour.js | 19 ++++++++++---------
.../static/src/js/website.tour.event_sale.js | 4 ++--
2 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js
index 1a4a987739f..02befe4fdbb 100644
--- a/addons/website/static/src/js/website.tour.js
+++ b/addons/website/static/src/js/website.tour.js
@@ -351,18 +351,19 @@ var T = website.Tour = {
},
testRunning: 0,
running: function () {
- setTimeout(function () {
- if ($.ajaxBusy) {
- $(document).ajaxStop(function() {
- var state = T.getState();
- T.registerSteps(state.tour);
- T.nextStep();
- });
- } else {
- var state = T.getState();
+ function run () {
+ var state = T.getState();
+ if (state) {
T.registerSteps(state.tour);
T.nextStep();
}
+ }
+ setTimeout(function () {
+ if ($.ajaxBusy) {
+ $(document).ajaxStop(run);
+ } else {
+ run();
+ }
},0);
},
check: function (step) {
diff --git a/addons/website_event_sale/static/src/js/website.tour.event_sale.js b/addons/website_event_sale/static/src/js/website.tour.event_sale.js
index 668a05001af..97de098240e 100644
--- a/addons/website_event_sale/static/src/js/website.tour.event_sale.js
+++ b/addons/website_event_sale/static/src/js/website.tour.event_sale.js
@@ -57,11 +57,11 @@
},
{
title: "select payment",
- element: '#payment_method label:has(img[title="transfer"]) input',
+ element: '#payment_method label:has(img[title="Wire Transfer"]) input',
},
{
title: "Pay Now",
- waitFor: '#payment_method label:has(input:checked):has(img[title="transfer"])',
+ waitFor: '#payment_method label:has(input:checked):has(img[title="Wire Transfer"])',
element: '.oe_sale_acquirer_button .btn[name="submit"]:visible',
},
{
From 69dfcab5d9c9b461df49d297b5fa2f8d5539de90 Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Tue, 8 Apr 2014 16:47:41 +0200
Subject: [PATCH 15/26] [WIP] add console.log
bzr revid: chm@openerp.com-20140408144741-ylt01232o58xb7ys
---
.../static/src/js/website.tour.event_sale.js | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/addons/website_event_sale/static/src/js/website.tour.event_sale.js b/addons/website_event_sale/static/src/js/website.tour.event_sale.js
index 97de098240e..75ad2297f6b 100644
--- a/addons/website_event_sale/static/src/js/website.tour.event_sale.js
+++ b/addons/website_event_sale/static/src/js/website.tour.event_sale.js
@@ -18,6 +18,11 @@
waitNot: 'a[href*="/event"]:contains("Functional Webinar")',
autoComplete: function () {
// use onload if website_event_track is installed
+ console.log("--------------------------------------------");
+ console.log($('form:contains("Ticket Type")').size());
+ console.log("--------------------------------------------");
+ console.log($('a[href*="/event"][href*="/register"]').attr("href"));
+ console.log("--------------------------------------------");
if (!$('form:contains("Ticket Type")').size()) {
window.location.href = $('a[href*="/event"][href*="/register"]').attr("href");
}
From 584f2bea071ef4d603fb19786b79bac80170ed77 Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Fri, 11 Apr 2014 12:51:05 +0200
Subject: [PATCH 16/26] [IMP] website: Tour: add a log time
bzr revid: chm@openerp.com-20140411105105-y7vxgkf7nydjb1f8
---
addons/website/static/src/js/website.tour.js | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js
index 02befe4fdbb..ce01b2e0cae 100644
--- a/addons/website/static/src/js/website.tour.js
+++ b/addons/website/static/src/js/website.tour.js
@@ -102,10 +102,12 @@ var T = website.Tour = {
return;
}
var tour = T.tours[tour_id];
- T.saveState(tour.id, mode || tour.mode, 0);
+ this.time = new Date().getTime();
if (tour.path && !window.location.href.match(new RegExp("("+T.getLang()+")?"+tour.path+"#?$", "i"))) {
+ T.saveState(tour.id, mode || tour.mode, -1);
window.location.href = "/"+T.getLang()+tour.path;
} else {
+ T.saveState(tour.id, mode || tour.mode, 0);
T.running();
}
},
@@ -296,6 +298,7 @@ var T = website.Tour = {
},
getState: function () {
var state = JSON.parse(localStorage.getItem("tour") || 'false') || {};
+ if (state) { this.time = state.time; }
var tour_id,mode,step_id;
if (!state.id && window.location.href.indexOf("#tutorial.") > -1) {
state = {
@@ -310,7 +313,7 @@ var T = website.Tour = {
return;
}
state.tour = T.tours[state.id];
- state.step = state.tour.steps[state.step_id];
+ state.step = state.tour.steps[state.step_id === -1 ? 0 : state.step_id];
return state;
},
error: function (message) {
@@ -335,7 +338,7 @@ var T = website.Tour = {
return tour_ids;
},
saveState: function (tour_id, mode, step_id) {
- localStorage.setItem("tour", JSON.stringify({"id":tour_id, "mode":mode, "step_id":step_id || 0}));
+ localStorage.setItem("tour", JSON.stringify({"id":tour_id, "mode":mode, "step_id":step_id || 0, "time": this.time}));
},
reset: function () {
var state = T.getState();
@@ -412,6 +415,10 @@ var T = website.Tour = {
step = step || state.step;
T.saveState(state.id, state.mode, step.id);
+ if (step.id !== state.step_id) {
+ console.log("Tour Step: '" + step._title + "' (" + (new Date().getTime() - this.time) + "ms)");
+ }
+
T.autoTogglePopover(true);
if (step.onload) {
From aa6386467a121e39266c7fd3e07684477cd3bc89 Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Fri, 11 Apr 2014 13:53:14 +0200
Subject: [PATCH 17/26] [FIX] website: snippet clean_for_save: filter snippet
before create overlay
bzr revid: chm@openerp.com-20140411115314-xr5yutao88j8fusu
---
addons/website/static/src/js/website.snippets.editor.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/website/static/src/js/website.snippets.editor.js b/addons/website/static/src/js/website.snippets.editor.js
index d8eee3cbec5..7aa189db653 100644
--- a/addons/website/static/src/js/website.snippets.editor.js
+++ b/addons/website/static/src/js/website.snippets.editor.js
@@ -361,7 +361,7 @@
},
clean_for_save: function () {
var self = this;
- $(website.snippet.globalSelector).each(function () {
+ this.dom_filter(website.snippet.globalSelector).each(function () {
var $snippet = $(this);
self.make_active($snippet);
self.make_active(false);
From ab5aa5daff007b1c6f26b0aa8dfd3c50cd48bfb3 Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Fri, 11 Apr 2014 13:55:02 +0200
Subject: [PATCH 18/26] [FIX] website tour: write undefined in log
bzr revid: chm@openerp.com-20140411115502-804e5669do02swm2
---
addons/website/static/src/js/website.tour.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js
index ce01b2e0cae..743e3445fa5 100644
--- a/addons/website/static/src/js/website.tour.js
+++ b/addons/website/static/src/js/website.tour.js
@@ -416,7 +416,7 @@ var T = website.Tour = {
T.saveState(state.id, state.mode, step.id);
if (step.id !== state.step_id) {
- console.log("Tour Step: '" + step._title + "' (" + (new Date().getTime() - this.time) + "ms)");
+ console.log("Tour Step: '" + (step._title || step.title) + "' (" + (new Date().getTime() - this.time) + "ms)");
}
T.autoTogglePopover(true);
From 4550b532ca24a24b7bfae46ddcddf049bf5afdab Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Fri, 11 Apr 2014 13:59:39 +0200
Subject: [PATCH 19/26] [FIX] website_sale: add product: customize img
(forgotten merge)
bzr revid: chm@openerp.com-20140411115939-yw257u179wqbh6sy
---
.../static/src/js/website.tour.shop.js | 32 ++++++-------------
1 file changed, 9 insertions(+), 23 deletions(-)
diff --git a/addons/website_sale/static/src/js/website.tour.shop.js b/addons/website_sale/static/src/js/website.tour.shop.js
index 4f9a97dbb54..3dd5b54b357 100644
--- a/addons/website_sale/static/src/js/website.tour.shop.js
+++ b/addons/website_sale/static/src/js/website.tour.shop.js
@@ -54,41 +54,27 @@
title: _t("Change the price"),
content: _t("Edit the price of this product by clicking on the amount."),
},
+
+
{
waitNot: '.product_price .oe_currency_value:containsExact(1.00)',
- element: '#wrap img.img:first',
+ element: '#wrap img.product_detail_img',
placement: 'top',
title: _t("Update image"),
content: _t("Click here to set an image describing your product."),
},
{
- element: 'button.hover-edition-button:visible',
+ element: 'img[alt=ipad]',
placement: 'top',
- title: _t("Update image"),
- content: _t("Click here to set an image describing your product."),
- },
- {
- wait: 500,
- element: '.well a.pull-right',
- placement: 'bottom',
title: _t("Select an Image"),
- content: _t("Let's select an existing image."),
- popover: { fixed: true },
+ content: _t("Let's select an ipad image."),
},
{
- element: 'img[alt=imac]',
- placement: 'bottom',
- title: _t("Select an Image"),
- content: _t("Let's select an imac image."),
- popover: { fixed: true },
- },
- {
- waitNot: 'img[alt=imac]',
+ waitFor: '.media_selected img[alt=ipad]',
element: '.modal-content button.save',
- placement: 'bottom',
- title: _t("Select this Image"),
- content: _t("Click to add the image to the product decsription."),
- popover: { fixed: true },
+ placement: 'top',
+ title: _t("Save this Image"),
+ content: _t("Click on save to add the image to the product decsription."),
},
{
waitNot: '.modal-content:visible',
From a2f62bc341ab080ced91a069e0724421bbb94c3c Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Fri, 11 Apr 2014 14:33:05 +0200
Subject: [PATCH 20/26] [FIX] website tour: error log
bzr revid: chm@openerp.com-20140411123305-t2n1aej9akn0zb5r
---
addons/website/static/src/js/website.tour.js | 12 ++++++------
.../static/src/js/website.tour.event_sale.js | 9 ++-------
2 files changed, 8 insertions(+), 13 deletions(-)
diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js
index 743e3445fa5..28d80fb2272 100644
--- a/addons/website/static/src/js/website.tour.js
+++ b/addons/website/static/src/js/website.tour.js
@@ -316,15 +316,15 @@ var T = website.Tour = {
state.step = state.tour.steps[state.step_id === -1 ? 0 : state.step_id];
return state;
},
- error: function (message) {
+ error: function (step, message) {
var state = T.getState();
message += '\n tour: ' + state.id
- + '\n step: ' + state.step_id + ": '" + (state.step._title || state.step.title) + "'"
+ + '\n step: ' + step.id + ": '" + (step._title || step.title) + "'"
+ '\n href: ' + window.location.href
+ '\n referrer: ' + document.referrer
- + '\n element: ' + Boolean(!state.step.element || ($(state.step.element).size() && $(state.step.element).is(":visible") && !$(state.step.element).is(":hidden")))
- + '\n waitNot: ' + Boolean(!state.step.waitNot || !$(state.step.waitNot).size())
- + '\n waitFor: ' + Boolean(!state.step.waitFor || $(state.step.waitFor).size())
+ + '\n element: ' + Boolean(!step.element || ($(step.element).size() && $(step.element).is(":visible") && !$(step.element).is(":hidden")))
+ + '\n waitNot: ' + Boolean(!step.waitNot || !$(step.waitNot).size())
+ + '\n waitFor: ' + Boolean(!step.waitFor || $(step.waitFor).size())
+ "\n localStorage: " + JSON.stringify(localStorage)
+ '\n\n' + $("body").html();
T.reset();
@@ -400,7 +400,7 @@ var T = website.Tour = {
} else if (!overlaps || new Date().getTime() - time < overlaps) {
T.timer = setTimeout(checkNext, T.defaultDelay);
} else {
- T.error("Can't reach the next step");
+ T.error(next, "Can't reach the next step");
}
}
checkNext();
diff --git a/addons/website_event_sale/static/src/js/website.tour.event_sale.js b/addons/website_event_sale/static/src/js/website.tour.event_sale.js
index 75ad2297f6b..9a200ece499 100644
--- a/addons/website_event_sale/static/src/js/website.tour.event_sale.js
+++ b/addons/website_event_sale/static/src/js/website.tour.event_sale.js
@@ -11,20 +11,15 @@
steps: [
{
title: "select event",
- element: 'a[href*="/event"]:contains("Open Days in Los Angeles")',
+ element: 'a[href*="/event"]:contains("Open Days in Los Angeles"):first',
},
{
title: "go to register page",
waitNot: 'a[href*="/event"]:contains("Functional Webinar")',
autoComplete: function () {
// use onload if website_event_track is installed
- console.log("--------------------------------------------");
- console.log($('form:contains("Ticket Type")').size());
- console.log("--------------------------------------------");
- console.log($('a[href*="/event"][href*="/register"]').attr("href"));
- console.log("--------------------------------------------");
if (!$('form:contains("Ticket Type")').size()) {
- window.location.href = $('a[href*="/event"][href*="/register"]').attr("href");
+ window.location.href = $('a[href*="/event/Open-Days-in-Los-Angeles"][href*="/register"]').attr("href");
}
},
},
From 3f7e567acc1542134d46aeb747a373588279d2f9 Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Mon, 14 Apr 2014 10:14:51 +0200
Subject: [PATCH 21/26] [FIX] website
bzr revid: chm@openerp.com-20140414081451-0hzjgaewtcok6rod
---
addons/website/static/src/js/website.editor.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js
index 365b8cf46ea..c2e2ed46783 100644
--- a/addons/website/static/src/js/website.editor.js
+++ b/addons/website/static/src/js/website.editor.js
@@ -544,7 +544,7 @@
observer.disconnect();
var editor = this.rte.editor;
- var root = editor.element.$;
+ var root = editor.element && editor.element.$;
editor.destroy();
// FIXME: select editables then filter by dirty?
var defs = this.rte.fetch_editables(root)
From a001e9c4bcadcd04a9c9dcd64b88aa6dc5bafb5c Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Mon, 14 Apr 2014 10:48:33 +0200
Subject: [PATCH 22/26] [FIX] website: tour for website_event_sale
bzr revid: chm@openerp.com-20140414084833-gsanxrhysk7jn9bo
---
.../static/src/js/website.tour.event_sale.js | 21 ++++++-------------
addons/website_report/views/layouts.xml | 1 -
2 files changed, 6 insertions(+), 16 deletions(-)
diff --git a/addons/website_event_sale/static/src/js/website.tour.event_sale.js b/addons/website_event_sale/static/src/js/website.tour.event_sale.js
index 9a200ece499..333481bc349 100644
--- a/addons/website_event_sale/static/src/js/website.tour.event_sale.js
+++ b/addons/website_event_sale/static/src/js/website.tour.event_sale.js
@@ -11,32 +11,23 @@
steps: [
{
title: "select event",
- element: 'a[href*="/event"]:contains("Open Days in Los Angeles"):first',
- },
- {
- title: "go to register page",
- waitNot: 'a[href*="/event"]:contains("Functional Webinar")',
- autoComplete: function () {
- // use onload if website_event_track is installed
- if (!$('form:contains("Ticket Type")').size()) {
- window.location.href = $('a[href*="/event/Open-Days-in-Los-Angeles"][href*="/register"]').attr("href");
- }
- },
+ element: 'a[href*="/event"]:contains("Conference on Business Applications"):first',
},
{
+ waitNot: 'a[href*="/event"]:contains("Conference on Business Applications")',
title: "select 2 Standard tickets",
- element: 'select[name="ticket-1"]',
+ element: 'select:eq(0)',
sampleText: '2',
},
{
title: "select 3 VIP tickets",
- waitFor: 'select[name="ticket-1"] option:contains(2):selected',
- element: 'select[name="ticket-2"]',
+ waitFor: 'select:eq(0) option:contains(2):selected',
+ element: 'select:eq(1)',
sampleText: '3',
},
{
title: "Order Now",
- waitFor: 'select[name="ticket-2"] option:contains(3):selected',
+ waitFor: 'select:eq(1) option:contains(3):selected',
element: '.btn-primary:contains("Order Now")',
},
{
diff --git a/addons/website_report/views/layouts.xml b/addons/website_report/views/layouts.xml
index c17fdf8c1ab..c9b2508489a 100644
--- a/addons/website_report/views/layouts.xml
+++ b/addons/website_report/views/layouts.xml
@@ -49,7 +49,6 @@
-
From 9c0526b1bde33922fcf7dddf1e65bf4429b64bff Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Tue, 15 Apr 2014 17:37:34 +0200
Subject: [PATCH 23/26] [FIX] website tour: test mode + add log
bzr revid: chm@openerp.com-20140415153734-5n2sz3xn01ydfeh6
---
addons/website/static/src/js/website.tour.js | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js
index 28d80fb2272..368a316e6f7 100644
--- a/addons/website/static/src/js/website.tour.js
+++ b/addons/website/static/src/js/website.tour.js
@@ -98,15 +98,15 @@ var T = website.Tour = {
T.tours[tour.id] = tour;
},
run: function (tour_id, mode) {
- if (localStorage.getItem("tour") && mode === "test") { // only one test running
- return;
- }
var tour = T.tours[tour_id];
this.time = new Date().getTime();
if (tour.path && !window.location.href.match(new RegExp("("+T.getLang()+")?"+tour.path+"#?$", "i"))) {
+ var href = "/"+T.getLang()+tour.path;
+ console.log("Tour Begin from run method (redirection to "+href+")");
T.saveState(tour.id, mode || tour.mode, -1);
- window.location.href = "/"+T.getLang()+tour.path;
+ window.location.href = href;
} else {
+ console.log("Tour Begin from run method");
T.saveState(tour.id, mode || tour.mode, 0);
T.running();
}
@@ -307,6 +307,7 @@ var T = website.Tour = {
"step_id": 0
};
window.location.hash = "";
+ console.log("Tour Begin from url hash");
T.saveState(state.id, state.mode, state.step_id);
}
if (!state.id || !T.tours[state.id]) {
@@ -357,6 +358,7 @@ var T = website.Tour = {
function run () {
var state = T.getState();
if (state) {
+ console.log("Tour '"+state.id+"' is running");
T.registerSteps(state.tour);
T.nextStep();
}
From 9284bd4817e970ff26cb17d3cd8aff0d5c2efb24 Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Wed, 16 Apr 2014 10:21:38 +0200
Subject: [PATCH 24/26] [FIX] website: tour test inject javascript
bzr revid: chm@openerp.com-20140416082138-rhwo2tl9l6jrko78
---
addons/website_event_sale/tests/test_ui.py | 4 ++--
addons/website_sale/tests/test_ui.py | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/addons/website_event_sale/tests/test_ui.py b/addons/website_event_sale/tests/test_ui.py
index fccbabb9d18..9e0ae31484e 100644
--- a/addons/website_event_sale/tests/test_ui.py
+++ b/addons/website_event_sale/tests/test_ui.py
@@ -3,8 +3,8 @@ import os
import openerp.tests
inject = [
- ("openerp.website.Tour", os.path.join(os.path.dirname(__file__), '../../website/static/src/js/website.tour.js')),
- ("openerp.website.Tour.tours.event_buy_tickets", os.path.join(os.path.dirname(__file__), "../static/src/js/website.tour.event_sale.js")),
+ os.path.join(os.path.dirname(__file__), '../../website/static/src/js/website.tour.js'),
+ os.path.join(os.path.dirname(__file__), "../static/src/js/website.tour.event_sale.js"),
]
@openerp.tests.common.at_install(False)
diff --git a/addons/website_sale/tests/test_ui.py b/addons/website_sale/tests/test_ui.py
index 61b0e904abf..e242bb0b557 100644
--- a/addons/website_sale/tests/test_ui.py
+++ b/addons/website_sale/tests/test_ui.py
@@ -3,8 +3,8 @@ import os
import openerp.tests
inject = [
- ("openerp.website.Tour", os.path.join(os.path.dirname(__file__), '../../website/static/src/js/website.tour.js')),
- ("openerp.website.Tour.tours.shop_buy_product", os.path.join(os.path.dirname(__file__), "../static/src/js/website.tour.sale.js")),
+ os.path.join(os.path.dirname(__file__), '../../website/static/src/js/website.tour.js'),
+ os.path.join(os.path.dirname(__file__), "../static/src/js/website.tour.sale.js"),
]
@openerp.tests.common.at_install(False)
From b1bc68d8eb374f30173e03e8048d1c3588a00d4b Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Wed, 23 Apr 2014 17:45:30 +0200
Subject: [PATCH 25/26] [FIX] website: tour inject sale/event
bzr revid: chm@openerp.com-20140423154530-rfc3glnp5xk50xoc
---
addons/website_event_sale/tests/test_ui.py | 4 ++--
addons/website_sale/tests/test_ui.py | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/addons/website_event_sale/tests/test_ui.py b/addons/website_event_sale/tests/test_ui.py
index 9e0ae31484e..3c3e643912a 100644
--- a/addons/website_event_sale/tests/test_ui.py
+++ b/addons/website_event_sale/tests/test_ui.py
@@ -3,8 +3,8 @@ import os
import openerp.tests
inject = [
- os.path.join(os.path.dirname(__file__), '../../website/static/src/js/website.tour.js'),
- os.path.join(os.path.dirname(__file__), "../static/src/js/website.tour.event_sale.js"),
+ ("openerp.website.Tour", os.path.join(os.path.dirname(__file__), '../../website/static/src/js/website.tour.js')),
+ ("openerp.website.Tour.ShopTest", os.path.join(os.path.dirname(__file__), "../static/src/js/website.tour.event_sale.js")),
]
@openerp.tests.common.at_install(False)
diff --git a/addons/website_sale/tests/test_ui.py b/addons/website_sale/tests/test_ui.py
index e242bb0b557..33e3a3c2ae8 100644
--- a/addons/website_sale/tests/test_ui.py
+++ b/addons/website_sale/tests/test_ui.py
@@ -3,8 +3,8 @@ import os
import openerp.tests
inject = [
- os.path.join(os.path.dirname(__file__), '../../website/static/src/js/website.tour.js'),
- os.path.join(os.path.dirname(__file__), "../static/src/js/website.tour.sale.js"),
+ ("openerp.website.Tour", os.path.join(os.path.dirname(__file__), '../../website/static/src/js/website.tour.js')),
+ ("openerp.website.Tour.ShopTest", os.path.join(os.path.dirname(__file__), "../static/src/js/website.tour.sale.js")),
]
@openerp.tests.common.at_install(False)
From 90d0139ae1eee3ccd92140090847cb26dcd2aaa2 Mon Sep 17 00:00:00 2001
From: "chm@openerp.com" <>
Date: Thu, 24 Apr 2014 14:47:03 +0200
Subject: [PATCH 26/26] [FIX] website tour: must retry running tour because in
test mode some files are added after the first running try
bzr revid: chm@openerp.com-20140424124703-qeft3n8xjmb1mvxn
---
addons/website/static/src/js/website.tour.js | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js
index 03b449479c4..2a661b4cc9b 100644
--- a/addons/website/static/src/js/website.tour.js
+++ b/addons/website/static/src/js/website.tour.js
@@ -87,6 +87,7 @@ var localStorage = window.localStorage;
var T = website.Tour = {
tours: {},
defaultDelay: 50,
+ retryRunningDelay: 1000,
errorDelay: 5000,
state: null,
$element: null,
@@ -129,6 +130,7 @@ var T = website.Tour = {
step.waitFor = '.oe_overlay_options .oe_options:visible';
}
+
var snippet = step.element && step.element.match(/#oe_snippets (.*) \.oe_snippet_thumbnail/);
if (snippet) {
step.snippet = snippet[1];
@@ -145,6 +147,7 @@ var T = website.Tour = {
if (tour.steps[index-1] &&
tour.steps[index-1].popover && tour.steps[index-1].popover.next) {
var step = {
+ _title: "",
id: index,
waitNot: '.popover.tour.fade.in:visible'
};
@@ -310,11 +313,11 @@ var T = website.Tour = {
console.log("Tour Begin from url hash");
T.saveState(state.id, state.mode, state.step_id);
}
- if (!state.id || !T.tours[state.id]) {
+ if (!state.id) {
return;
}
state.tour = T.tours[state.id];
- state.step = state.tour.steps[state.step_id === -1 ? 0 : state.step_id];
+ state.step = state.tour && state.tour.steps[state.step_id === -1 ? 0 : state.step_id];
return state;
},
error: function (step, message) {
@@ -353,14 +356,17 @@ var T = website.Tour = {
clearTimeout(T.testtimer);
T.closePopover();
},
- testRunning: 0,
running: function () {
function run () {
var state = T.getState();
- if (state) {
+ if (!state) return;
+ if (state.tour) {
console.log("Tour '"+state.id+"' is running");
T.registerSteps(state.tour);
T.nextStep();
+ } else {
+ console.log("Tour '"+state.id+"' wait for running (tour undefined)");
+ setTimeout(T.running, state.mode === "test" ? T.defaultDelay : T.retryRunningDelay);
}
}
setTimeout(function () {