diff options
Diffstat (limited to 'addons/website/static/src/js/website.editor.js')
| -rw-r--r-- | addons/website/static/src/js/website.editor.js | 121 |
1 files changed, 112 insertions, 9 deletions
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(); + } + } + } })(); |
