summaryrefslogtreecommitdiff
path: root/addons/website/static/src/js
diff options
context:
space:
mode:
authorXavier Morel <xmo@openerp.com>2013-10-14 10:54:59 +0200
committerXavier Morel <xmo@openerp.com>2013-10-14 10:54:59 +0200
commit2e352ce187d2685df64ebd36f669a8abd88d5f65 (patch)
tree529af9c967929ca13896e8464abdc8fe9d02710c /addons/website/static/src/js
parent3e349a2bf7c76f5136935b531c5b3fb65833e8be (diff)
parent063a698313e522596a0f784206a9d17b9f31dafa (diff)
[MERGE] from trunk
bzr revid: xmo@openerp.com-20131014085459-dhbypq0hg3lzzf3j
Diffstat (limited to 'addons/website/static/src/js')
-rw-r--r--addons/website/static/src/js/website.editor.js28
-rw-r--r--addons/website/static/src/js/website.seo.js2
-rw-r--r--addons/website/static/src/js/website.snippets.js216
-rw-r--r--addons/website/static/src/js/website.tour.js256
4 files changed, 393 insertions, 109 deletions
diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js
index 30514b25780..ffb0f9b86a3 100644
--- a/addons/website/static/src/js/website.editor.js
+++ b/addons/website/static/src/js/website.editor.js
@@ -3,13 +3,12 @@
var website = openerp.website;
// $.fn.data automatically parses value, '0'|'1' -> 0|1
- website.is_editable = $(document.documentElement).data('editable');
website.templates.push('/website/static/src/xml/website.editor.xml');
website.dom_ready.done(function () {
var is_smartphone = $(document.body)[0].clientWidth < 767;
- if (website.is_editable && !is_smartphone) {
+ if (!is_smartphone) {
website.ready().then(website.init_editor);
}
});
@@ -21,16 +20,15 @@
return new website.editor.RTEImageDialog(editor).appendTo(document.body);
}
- if (website.is_editable) {
- // only enable editors manually
- CKEDITOR.disableAutoInline = true;
- // EDIT ALL THE THINGS
- CKEDITOR.dtd.$editable = $.extend(
- {}, CKEDITOR.dtd.$block, CKEDITOR.dtd.$inline);
- // Disable removal of empty elements on CKEDITOR activation. Empty
- // elements are used for e.g. support of FontAwesome icons
- CKEDITOR.dtd.$removeEmpty = {};
- }
+ // only enable editors manually
+ CKEDITOR.disableAutoInline = true;
+ // EDIT ALL THE THINGS
+ CKEDITOR.dtd.$editable = $.extend(
+ {}, CKEDITOR.dtd.$block, CKEDITOR.dtd.$inline);
+ // Disable removal of empty elements on CKEDITOR activation. Empty
+ // elements are used for e.g. support of FontAwesome icons
+ CKEDITOR.dtd.$removeEmpty = {};
+
website.init_editor = function () {
CKEDITOR.plugins.add('customdialogs', {
// requires: 'link,image',
@@ -211,8 +209,9 @@
}
});
// Adding Static Menus
- menu.append('<li class="divider"></li><li><a href="/page/website.themes">Change Theme</a></li>');
+ menu.append('<li class="divider"></li><li class="js_change_theme"><a href="/page/website.themes">Change Theme</a></li>');
menu.append('<li class="divider"></li><li><a data-action="ace" href="#">Advanced view editor</a></li>');
+ self.trigger('rte:customize_menu_ready');
}
);
});
@@ -616,7 +615,7 @@
} else if ($e.hasClass('pages')) {
// Create the page, get the URL back
done = $.get(_.str.sprintf(
- '/pagenew/%s?noredirect', encodeURIComponent(val)))
+ '/pagenew/%s?noredirect', encodeURI(val)))
.then(function (response) {
self.make_link(response, false, val);
});
@@ -813,6 +812,7 @@
var element, editor = this.editor;
if (!(element = this.element)) {
element = editor.document.createElement('img');
+ element.addClass('img');
// focus event handler interactions between bootstrap (modal)
// and ckeditor (RTE) lead to blowing the stack in Safari and
// Chrome (but not FF) when this is done synchronously =>
diff --git a/addons/website/static/src/js/website.seo.js b/addons/website/static/src/js/website.seo.js
index 635b80bb192..945b0ed353d 100644
--- a/addons/website/static/src/js/website.seo.js
+++ b/addons/website/static/src/js/website.seo.js
@@ -1,6 +1,6 @@
(function () {
'use strict';
-
+
var website = openerp.website;
website.templates.push('/website/static/src/xml/website.seo.xml');
diff --git a/addons/website/static/src/js/website.snippets.js b/addons/website/static/src/js/website.snippets.js
index d85b2a814eb..96f153bf86e 100644
--- a/addons/website/static/src/js/website.snippets.js
+++ b/addons/website/static/src/js/website.snippets.js
@@ -243,12 +243,10 @@
// activate drag and drop for the snippets in the snippet toolbar
make_snippet_draggable: function($snippets){
var self = this;
- var $toInsert = false;
var $tumb = $snippets.find(".oe_snippet_thumbnail:first");
var left = $tumb.outerWidth()/2;
var top = $tumb.outerHeight()/2;
- var dropped = false;
- var $snippet = false;
+ var $toInsert, dropped, $snippet, action, snipped_id;
$snippets.draggable({
greedy: true,
@@ -265,8 +263,8 @@
self.hide();
dropped = false;
$snippet = $(this);
- var snipped_id = $snippet.data('snippet-id');
- var action = $snippet.find('.oe_snippet_body').size() ? 'insert' : 'mutate';
+ snipped_id = $snippet.data('snippet-id');
+ action = $snippet.find('.oe_snippet_body').size() ? 'insert' : 'mutate';
if( action === 'insert'){
if (!$snippet.data('selector-siblings') && !$snippet.data('selector-children') && !$snippet.data('selector-vertical-children')) {
console.debug($snippet.data("snippet-id") + " have oe_snippet_body class and have not for insert action"+
@@ -312,38 +310,46 @@
},
drop: function(){
dropped = true;
+ },
+ });
+ },
+ stop: function(ev, ui){
+ if (action === 'insert' && ! dropped) {
+ var el = $('.oe_drop_zone').nearest({x: ui.position.left, y: ui.position.top}).first()
+ if (el) {
+ el.after($toInsert)
+ dropped = true;
+ }
+ }
- var $target = false;
- if(action === 'insert'){
- $target = $toInsert;
+ $('.oe_drop_zone').droppable('destroy').remove();
+ if (dropped) {
+ var $target = false;
+ if(action === 'insert'){
+ $target = $toInsert;
- if (website.snippet.animationRegistry[snipped_id]) {
- new website.snippet.animationRegistry[snipped_id]($target);
- }
+ if (website.snippet.animationRegistry[snipped_id]) {
+ new website.snippet.animationRegistry[snipped_id]($target);
+ }
- self.create_overlay($target);
- $target.data("snippet-editor").build_snippet($target);
+ self.create_overlay($target);
+ $target.data("snippet-editor").build_snippet($target);
- } else {
- $target = $(this).data('target');
+ } else {
+ $target = $(this).data('target');
- self.create_overlay($target);
- if (website.snippet.editorRegistry[snipped_id]) {
- var snippet = new website.snippet.editorRegistry[snipped_id](self, $target);
- snippet.build_snippet($target);
- }
+ self.create_overlay($target);
+ if (website.snippet.editorRegistry[snipped_id]) {
+ var snippet = new website.snippet.editorRegistry[snipped_id](self, $target);
+ snippet.build_snippet($target);
}
-
- $('.oe_drop_zone').remove();
-
- setTimeout(function () {self.make_active($target);},0);
- },
- });
- },
- stop: function(){
- $('.oe_drop_zone').droppable('destroy').remove();
- if (!dropped && self.$modal.find('input:not(:checked)').length) {
- self.$modal.modal('toggle');
+ }
+ setTimeout(function () {self.make_active($target);},0);
+ } else {
+ $toInsert.remove();
+ if (self.$modal.find('input:not(:checked)').length) {
+ self.$modal.modal('toggle');
+ }
}
},
});
@@ -488,7 +494,6 @@
$zone.appendTo('#oe_manipulators');
$zone.data('target',$target);
$target.data('overlay',$zone);
- console.log($target[0], $zone);
$target.on("DOMNodeInserted DOMNodeRemoved DOMSubtreeModified", function () {
self.cover_target($zone, $target);
@@ -746,16 +751,8 @@
change_background: function (bg, ul_options) {
var self = this;
+ this.set_options_background(bg, ul_options);
var $ul = this.$editor.find(ul_options);
- var bg_value = (typeof bg === 'string' ? self.$target.find(bg) : $(bg)).css("background-image").replace(/url\(['"]*|['"]*\)/g, "");
-
- // select in ul options
- $ul.find("li").removeClass("active");
- var selected = $ul.find('[data-value="' + bg_value + '"], [data-value="' + bg_value.replace(/.*:\/\/[^\/]+/, '') + '"]');
- selected.addClass('active');
- if (!selected.length) {
- $ul.find('.oe_custom_bg b').html(bg_value);
- }
// bind envent on options
var $li = $ul.find("li");
@@ -787,6 +784,19 @@
$bg.css("background-image", "url(" + src + ")");
});
},
+
+ set_options_background: function (bg, ul_options) {
+ var $ul = this.$editor.find(ul_options);
+ var bg_value = (typeof bg === 'string' ? this.$target.find(bg) : $(bg)).css("background-image").replace(/url\(['"]*|['"]*\)/g, "");
+
+ // select in ul options
+ $ul.find("li").removeClass("active");
+ var selected = $ul.find('[data-value="' + bg_value + '"], [data-value="' + bg_value.replace(/.*:\/\/[^\/]+/, '') + '"]');
+ selected.addClass('active');
+ if (!selected.length) {
+ $ul.find('.oe_custom_bg b').html(bg_value);
+ }
+ },
});
@@ -974,50 +984,95 @@
});
website.snippet.editorRegistry.carousel = website.snippet.editorRegistry.resize.extend({
- build_snippet: function($target) {
- var id = "myCarousel" + $("body .carousel").length;
- $target.attr("id", id);
- $target.find(".carousel-control").attr("href", "#"+id);
+ build_snippet: function() {
+ var id = 0;
+ $("body .carousel").each(function () {
+ var _id = +$(this).attr("id").replace(/^myCarousel/, '');
+ if (id <= _id) {
+ id = _id + 1;
+ }
+ });
+ this.$target.attr("id", "myCarousel" + id);
+ this.$target.find(".carousel-control").attr("href", "#myCarousel" + id);
+ this.$target.find("[data-target='#myCarousel']").attr("data-target", "#myCarousel" + id);
+ this.rebind_event();
+ },
+ onFocus: function () {
+ this._super();
+ this.$target.carousel('pause');
+ },
+ onBlur: function () {
+ this._super();
+ this.$target.carousel('cycle');
},
start : function () {
this._super();
+ this.id = this.$target.attr("id");
+
+ this.$inner = this.$target.find('.carousel-inner');
+ this.$indicators = this.$target.find('.carousel-indicators');
+
this.$editor.find(".js_add").on('click', _.bind(this.on_add, this));
this.$editor.find(".js_remove").on('click', _.bind(this.on_remove, this));
this.change_background(".item.active", 'ul[name="carousel-background"]');
this.change_style();
- this.set_options_style();
this.change_size();
+ this.set_options_style();
+ this.$target.carousel();
+
+ var self = this;
+ this.$target.on('slide.bs.carousel', function () {
+ self.set_options_style();
+ self.set_options_background(".item.active", 'ul[name="carousel-background"]');
+ self.$target.carousel();
+ });
+
+ this.rebind_event();
+ },
+ // rebind event to active carousel on edit mode
+ rebind_event: function () {
+ var self = this;
+ this.$target.on('click', '.carousel-control', function () {
+ self.$target.carousel($(this).data('slide')); });
+ this.$target.on('click', '.carousel-indicators [data-target]', function () {
+ self.$target.carousel(+$(this).data('slide-to')); });
},
on_add: function (e) {
e.preventDefault();
- this.$target.find('.carousel-control').removeClass("hidden");
- var $inner = this.$target.find('.carousel-inner');
- var cycle = $inner.find('.item').length;
- $inner.find('.item.active').clone().removeClass('active').appendTo($inner);
- this.$target.carousel(cycle);
- this.set_options_background();
- this.set_options_style();
+ var cycle = this.$inner.find('.item').length;
+ var $active = this.$inner.find('.item.active');
+ var index = $active.index();
+ this.$target.find('.carousel-control, .carousel-indicators').removeClass("hidden");
+ this.$indicators.append('<li data-target="#' + this.id + '" data-slide-to="' + cycle + '"></li>');
+ $active.clone().removeClass('active').insertAfter($active);
+ this.$target.carousel().carousel(++index);
},
on_remove: function (e) {
e.preventDefault();
- var $inner = this.$target.find('.carousel-inner');
- var nb = $inner.find('.item').length;
- if (nb > 1) {
- $inner
- .find('.item.active').remove().end()
- .find('.item:first').addClass('active');
- this.$target.carousel(0);
- this.set_options_style();
- }
- if (nb <= 1) {
- this.$target.find('.carousel-control').addClass("hidden");
+ var self = this;
+ var new_index = 0;
+ var cycle = this.$inner.find('.item').length - 1;
+ var index = this.$inner.find('.item.active').index();
+ if (cycle > 0) {
+ this.$inner.find('.item.active').fadeOut(1000, function () {
+ $(this).remove();
+ self.$indicators.find('[data-target]:last').remove();
+ self.$indicators.find("[data-slide-to]").removeClass("active");
+ self.$indicators.find("[data-slide-to='" + new_index + "']").addClass("active");
+ });
+ setTimeout(function () {
+ new_index = index % cycle;
+ self.$target.carousel( new_index + 1 );
+ }, 500);
+ } else {
+ this.$target.find('.carousel-control, .carousel-indicators').addClass("hidden");
}
},
set_options_style: function () {
var style = false;
- var $el = this.$target.find('.carousel-inner .item.active');
+ var $el = this.$inner.find('.item.active');
var $ul = this.$editor.find('ul[name="carousel-style"]');
var $li = $ul.find("li");
@@ -1040,12 +1095,12 @@
$(this).addClass("active");
})
.on('mouseover', function (event) {
- var $el = self.$target.find('.carousel-inner .item.active');
+ var $el = self.$inner.find('.item.active');
$el.removeClass('image_text text_image text_only');
$el.addClass($(event.currentTarget).data("value"));
})
.on('mouseout', function (event) {
- var $el = self.$target.find('.carousel-inner .item.active');
+ var $el = self.$inner.find('.item.active');
$el.removeClass('image_text text_image text_only');
$el.addClass($ul.find('li.active').data("value"));
});
@@ -1087,33 +1142,6 @@
},
});
- website.snippet.animationRegistry.surprise = website.snippet.Animation.extend({
- start: function() {
- this._super();
- var hue=0;
- var beat = false;
- var self = this;
- self.$target.append('<iframe width="1px" height="1px" src="http://www.youtube.com/embed/WY24YNsOefk?autoplay=1" frameborder="0"></iframe>');
-
- var a = setInterval(function(){
- self.$target.next().css({'-webkit-filter':'hue-rotate('+hue+'deg)'});
- self.$target.prev().css({'-webkit-filter':'hue-rotate('+(-hue)+'deg)'});
- hue -= 5;
- }, 10);
-
- setTimeout(function(){
- clearInterval(a);
- setInterval(function(){
- var filter = 'hue-rotate('+hue+'deg)'+ (beat ? ' invert()' : '');
- $(document.documentElement).css({'-webkit-filter': filter}); hue += 5;
- if(hue % 35 === 0){
- beat = !beat;
- }
- }, 10);
- },5000);
- }
- });
-
/*
* data-snippet-id automatically setted
* Don't need to add data-snippet-id="..." into the views
diff --git a/addons/website/static/src/js/website.tour.js b/addons/website/static/src/js/website.tour.js
new file mode 100644
index 00000000000..09e222acf64
--- /dev/null
+++ b/addons/website/static/src/js/website.tour.js
@@ -0,0 +1,256 @@
+(function () {
+ 'use strict';
+
+ var website = openerp.website;
+ website.templates.push('/website/static/src/xml/website.tour.xml');
+
+ function render (template, dict) {
+ return openerp.qweb.render(template, dict);
+ }
+
+ website.EditorTour = openerp.Class.extend({
+ tour: undefined,
+ steps: [],
+ tourStorage: window.localStorage,
+ init: function () {
+ this.tour = new Tour({
+ name: this.id,
+ storage: this.tourStorage,
+ keyboard: false,
+ });
+ this.tour.addSteps(_.map(this.steps, function (step) {
+ step.title = render('website.tour_popover_title', { title: step.title });
+ return step;
+ }));
+ this.monkeyPatchTour();
+ },
+ monkeyPatchTour: function () {
+ var self = this;
+ // showStep should wait for 'element' to appear instead of moving to the next step
+ self.tour.showStep = function (i) {
+ var step = self.tour.getStep(i);
+ return (function proceed () {
+ if (step.orphan || $(step.element).length > 0) {
+ return Tour.prototype.showStep.call(self.tour, i);
+ } else {
+ setTimeout(proceed, 50);
+ }
+ }());
+ };
+ },
+ reset: function () {
+ this.tourStorage.removeItem(this.id+'_current_step');
+ this.tourStorage.removeItem(this.id+'_end');
+ this.tour._current = 0;
+ $('.popover.tour').remove();
+ },
+ start: function () {
+ if (this.canResume()) {
+ this.tour.start();
+ }
+ },
+ canResume: function () {
+ return (this.currentStepIndex() === 0) && !this.tour.ended();
+ },
+ currentStepIndex: function () {
+ var index = this.tourStorage.getItem(this.id+'_current_step') || 0;
+ return parseInt(index, 10);
+ },
+ indexOfStep: function (stepId) {
+ var index = -1;
+ _.each(this.steps, function (step, i) {
+ if (step.stepId === stepId) {
+ index = i;
+ }
+ });
+ return index;
+ },
+ movetoStep: function (stepId) {
+ $('.popover.tour').remove();
+ var index = this.indexOfStep(stepId);
+ if (index > -1) {
+ this.tour.goto(index);
+ }
+ },
+ saveStep: function (stepId) {
+ var index = this.indexOfStep(stepId);
+ this.tourStorage.setItem(this.id+'_current_step', index);
+ },
+ stop: function () {
+ this.tour.end();
+ },
+ });
+
+ website.EditorBasicTour = website.EditorTour.extend({
+ id: 'add_banner_tour',
+ name: "Insert a banner",
+ init: function (editor) {
+ var self = this;
+ self.steps = [
+ {
+ stepId: 'welcome',
+ orphan: true,
+ backdrop: true,
+ title: "Welcome to your website!",
+ content: "This tutorial will guide you to build your first page. We will start by adding a banner.",
+ template: render('website.tour_popover', { next: "Start Tutorial", end: "Skip It" }),
+ },
+ {
+ stepId: 'edit-page',
+ element: 'button[data-action=edit]',
+ placement: 'bottom',
+ reflex: true,
+ title: "Edit this page",
+ content: "Every page of your website can be modified through the <i>Edit</i> button.",
+ template: render('website.tour_popover'),
+ },
+ {
+ stepId: 'add-block',
+ element: 'button[data-action=snippet]',
+ placement: 'bottom',
+ title: "Insert building blocks",
+ content: "To add content in a page, you can insert building blocks.",
+ template: render('website.tour_popover'),
+ onShow: function () {
+ function refreshAddBlockStep () {
+ self.tour.showStep(self.indexOfStep('add-block'));
+ editor.off('rte:ready', editor, refreshAddBlockStep);
+ }
+ editor.on('rte:ready', editor, refreshAddBlockStep);
+ $('button[data-action=snippet]').click(function () {
+ self.movetoStep('drag-banner');
+ });
+ }
+ },
+ {
+ stepId: 'drag-banner',
+ element: '#website-top-navbar [data-snippet-id=carousel]',
+ placement: 'bottom',
+ title: "Drag & Drop a Banner",
+ content: "Drag the <em>Banner</em> block and drop it in your page. <p class='text-muted'>Tip: release the mouse button when you are in a valid zone, with a preview of the banner.</p>",
+ template: render('website.tour_popover'),
+ onShow: function () {
+ function beginDrag () {
+ $('.popover.tour').remove();
+ $('body').off('mousedown', beginDrag);
+ function goToNextStep () {
+ $('#oe_snippets').hide();
+ self.movetoStep('edit-title');
+ $('body').off('mouseup', goToNextStep);
+ }
+ $('body').on('mouseup', goToNextStep);
+ }
+ $('body').on('mousedown', beginDrag);
+ },
+ },
+ {
+ stepId: 'edit-title',
+ element: '#wrap [data-snippet-id=carousel]:first .carousel-caption',
+ placement: 'left',
+ title: "Customize banner's text",
+ content: "Click in the text and start editing it. Click continue once it's done.",
+ template: render('website.tour_popover', { next: "Continue" }),
+ onHide: function () {
+ var $banner = $("#wrap [data-snippet-id=carousel]:first");
+ if ($banner.length) {
+ $banner.click();
+ }
+ },
+ },
+ {
+ stepId: 'customize-banner',
+ element: '.oe_overlay_options .oe_options',
+ placement: 'left',
+ title: "Customize the banner",
+ content: "You can customize components of your page through the <em>Customize</em> menu. Try to change the background of your banner.",
+ template: render('website.tour_popover', { next: "Continue" }),
+ onShow: function () {
+ $('.dropdown-menu [name=carousel-background]').click(function () {
+ self.movetoStep('save-changes');
+ });
+ },
+ },
+ {
+ stepId: 'save-changes',
+ element: 'button[data-action=save]',
+ placement: 'right',
+ reflex: true,
+ title: "Save your modifications",
+ content: "Once you click on save, your website page is updated.",
+ template: render('website.tour_popover'),
+ onHide: function () {
+ self.saveStep('part-2');
+ },
+
+ },
+ {
+ stepId: 'part-2',
+ orphan: true,
+ title: "Congratulation!",
+ content: "Your homepage have been updated. Now, we suggest you to insert others building blocks like texts and images to structure your page.",
+ template: render('website.tour_popover', { next: "Continue" }),
+ },
+ {
+ stepId: 'show-tutorials',
+ element: '#help-menu-button',
+ placement: 'left',
+ title: "Help is always available",
+ content: "But you can always click here if you want more tutorials.",
+ template: render('website.tour_popover', { end: "Close" }),
+ },
+ ];
+ return this._super();
+ },
+ startOfPart2: function () {
+ var currentStepIndex = this.currentStepIndex();
+ var secondPartIndex = this.indexOfStep('part-2');
+ var showTutorialsIndex = this.indexOfStep('show-tutorials');
+ return (currentStepIndex === secondPartIndex || currentStepIndex === showTutorialsIndex) && !this.tour.ended();
+ },
+ canResume: function () {
+ return this.startOfPart2() || this._super();
+ },
+ });
+
+ website.UrlParser = openerp.Class.extend({
+ init: function (url) {
+ var a = document.createElement('a');
+ a.href = url;
+ this.href = a.href;
+ this.host = a.host;
+ this.protocol = a.protocol;
+ this.port = a.port;
+ this.hostname = a.hostname;
+ this.pathname = a.pathname;
+ this.origin = a.origin;
+ this.search = a.search;
+ },
+ });
+
+ website.EditorBar.include({
+ start: function () {
+ website.tutorials = {
+ basic: new website.EditorBasicTour(this),
+ };
+ var menu = $('#help-menu');
+ _.each(website.tutorials, function (tutorial) {
+ var $menuItem = $($.parseHTML('<li><a href="#">'+tutorial.name+'</a></li>'));
+ $menuItem.click(function () {
+ tutorial.reset();
+ tutorial.start();
+ })
+ menu.append($menuItem);
+ });
+ var url = new website.UrlParser(window.location.href);
+ if (url.search.indexOf('?tutorial=true') === 0 || website.tutorials.basic.startOfPart2()) {
+ website.tutorials.basic.start();
+ }
+ $('.tour-backdrop').click(function (e) {
+ e.stopImmediatePropagation();
+ e.preventDefault();
+ });
+ return this._super();
+ },
+ });
+
+}());