diff options
| author | Xavier Morel <xmo@openerp.com> | 2013-10-14 10:54:59 +0200 |
|---|---|---|
| committer | Xavier Morel <xmo@openerp.com> | 2013-10-14 10:54:59 +0200 |
| commit | 2e352ce187d2685df64ebd36f669a8abd88d5f65 (patch) | |
| tree | 529af9c967929ca13896e8464abdc8fe9d02710c /addons/website/static/src/js | |
| parent | 3e349a2bf7c76f5136935b531c5b3fb65833e8be (diff) | |
| parent | 063a698313e522596a0f784206a9d17b9f31dafa (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.js | 28 | ||||
| -rw-r--r-- | addons/website/static/src/js/website.seo.js | 2 | ||||
| -rw-r--r-- | addons/website/static/src/js/website.snippets.js | 216 | ||||
| -rw-r--r-- | addons/website/static/src/js/website.tour.js | 256 |
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(); + }, + }); + +}()); |
