diff options
| author | chm@openerp.com <> | 2014-03-11 16:48:00 +0100 |
|---|---|---|
| committer | chm@openerp.com <> | 2014-03-11 16:48:00 +0100 |
| commit | 595c21fe5d6f908cd3db6cee4ea5b027da724859 (patch) | |
| tree | bc3c0571ed03a1dcdeb06ad80ee3b8f7e2dd0b59 /addons/website/static/src/js | |
| parent | 697b72befcc12081e5a1576a05d66948a976b3f2 (diff) | |
| parent | d504764eff52354d4993863d72d1342bcdf704fb (diff) | |
[MERGE] from trunk
bzr revid: chm@openerp.com-20140311154800-tdw1fcknbb42nvph
Diffstat (limited to 'addons/website/static/src/js')
| -rw-r--r-- | addons/website/static/src/js/website.ace.js | 17 | ||||
| -rw-r--r-- | addons/website/static/src/js/website.editor.js | 121 | ||||
| -rw-r--r-- | addons/website/static/src/js/website.js | 2 | ||||
| -rw-r--r-- | addons/website/static/src/js/website.mobile.js | 3 | ||||
| -rw-r--r-- | addons/website/static/src/js/website.snippets.animation.js | 4 | ||||
| -rw-r--r-- | addons/website/static/src/js/website.snippets.editor.js | 66 | ||||
| -rw-r--r-- | addons/website/static/src/js/website.tour.banner.js | 13 |
7 files changed, 185 insertions, 41 deletions
diff --git a/addons/website/static/src/js/website.ace.js b/addons/website/static/src/js/website.ace.js index ed7037e903c..a8af74bb52d 100644 --- a/addons/website/static/src/js/website.ace.js +++ b/addons/website/static/src/js/website.ace.js @@ -39,12 +39,17 @@ this.xml = text; }, isWellFormed: function () { + var error; if (document.implementation.createDocument) { - var dom = new DOMParser().parseFromString(this.xml, "text/xml"); - var error = dom.getElementsByTagName("parsererror"); - return error.length === 0 || error; - } else if (window.ActiveXObject) { - // TODO test in IE + // use try catch for ie + try { + var dom = new DOMParser().parseFromString(this.xml, "text/xml"); + error = dom.getElementsByTagName("parsererror"); + return error.length === 0 || $(error).text(); + } catch (e) {} + } + if (window.ActiveXObject) { + // IE var msDom = new ActiveXObject("Microsoft.XMLDOM"); msDom.async = false; msDom.loadXML(this.xml); @@ -284,7 +289,7 @@ def.reject("server", session, error); }); } else { - def.reject(null, session, $(isWellFormed).text()); + def.reject(null, session, isWellFormed); } return def; }, diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index dc82c0c17b9..a5cf89b3a4e 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -20,6 +20,10 @@ website.form(this.pathname, 'POST'); }); + $(document).on('click', '.cke_editable label', function (ev) { + ev.preventDefault(); + }); + $(document).on('submit', '.cke_editable form', function (ev) { // Disable form submition in editable mode ev.preventDefault(); @@ -66,8 +70,10 @@ // only enable editors manually CKEDITOR.disableAutoInline = true; // EDIT ALL THE THINGS - CKEDITOR.dtd.$editable = $.extend( - {}, CKEDITOR.dtd.$block, CKEDITOR.dtd.$inline); + CKEDITOR.dtd.$editable = _.omit( + $.extend({}, CKEDITOR.dtd.$block, CKEDITOR.dtd.$inline), + // well maybe not *all* the things + 'ul', 'ol', 'li', 'table', 'tr', 'th', 'td'); // Disable removal of empty elements on CKEDITOR activation. Empty // elements are used for e.g. support of FontAwesome icons CKEDITOR.dtd.$removeEmpty = {}; @@ -377,8 +383,7 @@ }); }, upcast: function (el) { - return el.attributes['class'] - && (/\bfa\b/.test(el.attributes['class'])); + return el.hasClass('fa'); } }); } @@ -625,11 +630,11 @@ var $link_button = this.make_hover_button(_t("Change"), function () { var sel = new CKEDITOR.dom.element(previous); editor.getSelection().selectElement(sel); - if (previous.tagName.toUpperCase() === 'A') { - link_dialog(editor); - } else if(sel.hasClass('fa')) { + if(sel.hasClass('fa')) { new website.editor.FontIconsDialog(editor, previous) .appendTo(document.body); + } else if (previous.tagName.toUpperCase() === 'A') { + link_dialog(editor); } $link_button.hide(); previous = null; @@ -650,6 +655,7 @@ if (previous && previous === this) { return; } var selected = new CKEDITOR.dom.element(this); + // FIXME: fa nodes may not be editable widgets (?) if (!is_editable_node(selected) && !selected.hasClass('fa')) { return; } @@ -837,7 +843,6 @@ document.execCommand("enableInlineTableEditing", false, "false"); } catch (e) {} - // detect & setup any CKEDITOR widget within a newly dropped // snippet. There does not seem to be a simple way to do it for // HTML not inserted via ckeditor APIs: @@ -1436,6 +1441,7 @@ this.page += $target.hasClass('previous') ? -1 : 1; this.display_attachments(); }, + 'click .existing-attachment-remove': 'try_remove', }), init: function (parent) { this.image = null; @@ -1458,7 +1464,7 @@ kwargs: { fields: ['name', 'website_url'], domain: [['res_model', '=', 'ir.ui.view']], - order: 'name', + order: 'id desc', context: website.get_context(), } }); @@ -1468,6 +1474,7 @@ this.display_attachments(); }, display_attachments: function () { + this.$('.help-block').empty(); var per_screen = IMAGES_PER_ROW * IMAGES_ROWS; var from = this.page * per_screen; @@ -1495,6 +1502,34 @@ } this.close() }, + + try_remove: function (e) { + var $help_block = this.$('.help-block').empty(); + var self = this; + var id = parseInt($(e.target).data('id'), 10); + var attachment = _.findWhere(this.records, {id: id}); + + return openerp.jsonRpc('/web/dataset/call_kw', 'call', { + model: 'ir.attachment', + method: 'try_remove', + args: [], + kwargs: { + ids: [id], + context: website.get_context() + } + }).then(function (prevented) { + if (_.isEmpty(prevented)) { + self.records = _.without(self.records, attachment); + self.display_attachments(); + return; + } + $help_block.replaceWith(openerp.qweb.render( + 'website.editor.dialog.image.existing.error', { + views: prevented[id] + } + )); + }); + }, }); function get_selected_link(editor) { @@ -1684,6 +1719,9 @@ // ignore mutation if the *only* change is .cke_focus return change.length !== 1 || change[0] === 'cke_focus'; case 'childList': + setTimeout(function () { + fixup_browser_crap(m.addedNodes); + }, 0); // Remove ignorable nodes from addedNodes or removedNodes, // if either set remains non-empty it's considered to be an // impactful change. Otherwise it's ignored. @@ -1721,4 +1759,69 @@ } return output; } + + var programmatic_styles = { + float: 1, + display: 1, + position: 1, + top: 1, + left: 1, + right: 1, + bottom: 1, + }; + function fixup_browser_crap(nodes) { + if (!nodes || !nodes.length) { return; } + /** + * Checks that the node only has a @style, not e.g. @class or whatever + */ + function has_only_style(node) { + for (var i = 0; i < node.attributes.length; i++) { + var attr = node.attributes[i]; + if (attr.attributeName !== 'style') { + return false; + } + } + return true; + } + function has_programmatic_style(node) { + for (var i = 0; i < node.style.length; i++) { + var style = node.style[i]; + if (programmatic_styles[style]) { + return true; + } + } + return false; + } + + for (var i=0; i<nodes.length; ++i) { + var node = nodes[i]; + if (node.nodeType !== document.ELEMENT_NODE) { continue; } + + if (node.nodeName === 'SPAN' + && has_only_style(node) + && !has_programmatic_style(node)) { + // On backspace, webkit browsers create a <span> with a bunch of + // inline styles "remembering" where they come from. Refs: + // http://www.neotericdesign.com/blog/2013/3/working-around-chrome-s-contenteditable-span-bug + // https://code.google.com/p/chromium/issues/detail?id=226941 + // https://bugs.webkit.org/show_bug.cgi?id=114791 + // http://dev.ckeditor.com/ticket/9998 + var child, parent = node.parentNode; + while (child = node.firstChild) { + parent.insertBefore(child, node); + } + parent.removeChild(node); + // chances are we had e.g. + // <p>foo</p> + // <p>bar</p> + // merged the lines getting this in webkit + // <p>foo<span>bar</span></p> + // after unwrapping the span, we have 2 text nodes + // <p>[foo][bar]</p> + // where we probably want only one. Normalize will merge + // adjacent text nodes. However, does not merge text and cdata + parent.normalize(); + } + } + } })(); diff --git a/addons/website/static/src/js/website.js b/addons/website/static/src/js/website.js index 671dfc14ee9..54ee4689814 100644 --- a/addons/website/static/src/js/website.js +++ b/addons/website/static/src/js/website.js @@ -69,6 +69,8 @@ website.is_editable = website.is_editable || $('html').data('editable'); website.is_editable_button= website.is_editable_button || $('html').data('editable'); dom_ready.resolve(); + // fix for ie + if($.fn.placeholder) $('input, textarea').placeholder(); }); website.init_kanban = function ($kanban) { diff --git a/addons/website/static/src/js/website.mobile.js b/addons/website/static/src/js/website.mobile.js index 4acf2d78db8..59c2328e09b 100644 --- a/addons/website/static/src/js/website.mobile.js +++ b/addons/website/static/src/js/website.mobile.js @@ -17,6 +17,9 @@ 'hidden.bs.modal': 'destroy' }, start: function () { + if (!window.location.origin) { // fix for ie9 + window.location.origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: '') + '/'; + } document.getElementById("mobile-viewport").src = window.location.origin + window.location.pathname + "#mobile-preview"; this.$el.modal(); }, diff --git a/addons/website/static/src/js/website.snippets.animation.js b/addons/website/static/src/js/website.snippets.animation.js index bc2ea064731..f1d19125a0c 100644 --- a/addons/website/static/src/js/website.snippets.animation.js +++ b/addons/website/static/src/js/website.snippets.animation.js @@ -64,6 +64,10 @@ start: function () { this.$target.carousel({interval: 10000}); }, + stop: function () { + this.$target.carousel('pause'); + this.$target.removeData("bs.carousel"); + }, }); website.snippet.animationRegistry.parallax = website.snippet.Animation.extend({ diff --git a/addons/website/static/src/js/website.snippets.editor.js b/addons/website/static/src/js/website.snippets.editor.js index 23c5956ebf4..ee07840b12d 100644 --- a/addons/website/static/src/js/website.snippets.editor.js +++ b/addons/website/static/src/js/website.snippets.editor.js @@ -19,13 +19,23 @@ edit: function () { var self = this; $("body").off('click'); + website.snippet.stop_animation(); window.snippets = this.snippets = new website.snippet.BuildingBlock(this); this.snippets.appendTo(this.$el); - this.on('rte:ready', this, function () { self.snippets.$button.removeClass("hidden"); - website.snippet.stop_animation(); website.snippet.start_animation(); + $(website.snippet.readyAnimation).each(function() { + var animation = $(this).data("snippet-view"); + if (animation) { + animation.$target.on('focus', '*', function(){ + animation.stop(); + }); + animation.$target.on('blur', '*', function(){ + animation.start(); + }); + } + }); }); return this._super.apply(this, arguments); @@ -190,13 +200,14 @@ var mt = parseInt($target.css("margin-top") || 0); var mb = parseInt($target.css("margin-bottom") || 0); $el.css({ - 'position': 'absolute', 'width': $target.outerWidth(), - 'height': $target.outerHeight() + mt + mb+1, - 'top': pos.top - mt, + 'top': pos.top - mt - 5, 'left': pos.left }); - $el.find(".oe_handle.size").css("bottom", (mb-7)+'px'); + $el.find(">.e,>.w").css({'height': $target.outerHeight() + mt + mb+1}); + $el.find(">.s").css({'top': $target.outerHeight() + mt + mb}); + $el.find(">.size").css({'top': $target.outerHeight() + mt}); + $el.find(">.s,>.n").css({'width': $target.outerWidth()-2}); }, show: function () { this.$el.removeClass("hidden"); @@ -213,14 +224,8 @@ bind_snippet_click_editor: function () { var self = this; - var snipped_event_flag = false; $("#wrapwrap").on('click', function (event) { - if (snipped_event_flag) { - return; - } - snipped_event_flag = true; - setTimeout(function () {snipped_event_flag = false;}, 0); - var $target = $(event.srcElement); + var $target = $(event.srcElement || event.target); if (!$target.attr("data-snippet-id")) { $target = $target.parents("[data-snippet-id]:first"); } @@ -421,7 +426,6 @@ $target.data("overlay").remove(); $target.removeData("overlay"); } - self.create_overlay($target); $target.find("[data-snippet-id]").each(function () { var $snippet = $(this); $snippet.removeData("snippet-editor"); @@ -429,10 +433,10 @@ $snippet.data("overlay").remove(); $snippet.removeData("overlay"); } - self.create_overlay($snippet); }); // end + self.create_overlay($target); self.make_active($target); },0); } else { @@ -577,6 +581,20 @@ var $target = $(this); if (!$target.data('overlay')) { var $zone = $(openerp.qweb.render('website.snippet_overlay')); + + // fix for pointer-events: none with ie9 + if (document.body && document.body.addEventListener) { + $zone.on("click mousedown mousedown", function passThrough(event) { + event.preventDefault(); + $target.each(function() { + // check if clicked point (taken from event) is inside element + event.srcElement = this; + $(this).trigger(event.type); + }); + return false; + }); + } + $zone.appendTo('#oe_manipulators'); $zone.data('target',$target); $target.data('overlay',$zone); @@ -789,6 +807,7 @@ this.parent = parent; this.$target = $(dom); this.$overlay = this.$target.data('overlay'); + this.$overlay.find('a[data-toggle="dropdown"]').dropdown(); this.snippet_id = this.$target.data("snippet-id"); this._readXMLData(); this.load_style_options(); @@ -1216,7 +1235,6 @@ on_clone: function () { var $clone = this.$target.clone(false); var _class = $clone.attr("class").replace(/\s*(col-lg-offset-|col-md-offset-)([0-9-]+)/g, ''); - _class += ' col-md-1'; $clone.attr("class", _class); this.$target.after($clone); this.hide_remove_button(); @@ -1264,6 +1282,11 @@ }); website.snippet.editorRegistry.slider = website.snippet.editorRegistry.resize.extend({ + getSize: function () { + this.grid = this._super(); + this.grid.size = 8; + return this.grid; + }, drop_and_build_snippet: function() { var id = $(".carousel").length; this.id = "myCarousel" + id; @@ -1299,7 +1322,6 @@ this.$editor.find(".js_add").on('click', function () {self.on_add_slide(); return false;}); this.$editor.find(".js_remove").on('click', function () {self.on_remove_slide(); return false;}); - this.$target.carousel('pause'); this.rebind_event(); }, on_add_slide: function () { @@ -1352,11 +1374,6 @@ }); website.snippet.editorRegistry.carousel = website.snippet.editorRegistry.slider.extend({ - getSize: function () { - this.grid = this._super(); - this.grid.size = 8; - return this.grid; - }, clean_for_save: function () { this._super(); this.$target.css("background-image", ""); @@ -1442,7 +1459,10 @@ self.$target.data("snippet-view").set_values(); }); this.$target.attr('contentEditable', 'false'); - this.$target.find('> div > .oe_structure').attr('contentEditable', 'true'); + + this.$target.find('> div > .oe_structure').attr('contentEditable', 'true'); // saas-3 retro-compatibility + + this.$target.find('> div > div:not(.oe_structure) > .oe_structure').attr('contentEditable', 'true'); }, scroll: function () { var self = this; diff --git a/addons/website/static/src/js/website.tour.banner.js b/addons/website/static/src/js/website.tour.banner.js index 1d4a0c0f752..40730e5dc09 100644 --- a/addons/website/static/src/js/website.tour.banner.js +++ b/addons/website/static/src/js/website.tour.banner.js @@ -47,10 +47,10 @@ }, { waitFor: '.oe_overlay_options .oe_options:visible', - element: '#wrap [data-snippet-id=carousel]:first .carousel-caption', + element: '#wrap [data-snippet-id=carousel]:first .carousel-caption > div', placement: 'top', - title: _("Customize banner's text"), - content: _("Click in the text and start editing it."), + title: _t("Customize banner's text"), + content: _t("Click in the text and start editing it."), popover: { next: _t("Continue") }, }, { @@ -69,6 +69,13 @@ popover: { fixed: true }, }, { + element: 'a[href="#snippet_feature"]', + placement: 'bottom', + title: _t("Feature blocks list"), + content: _t("Click on 'Features' to see the feature blocks list."), + popover: { fixed: true }, + }, + { snippet: 'features', placement: 'bottom', title: _t("Drag & Drop This Block"), |
