From 796dcee2c3b082eba4819bf95e501c3604431da8 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 29 Aug 2013 12:29:56 +0200 Subject: [IMP] split out website.js bzr revid: xmo@openerp.com-20130829102956-prfe9t5308m6y0vn --- addons/website/static/src/js/website.editor.js | 292 +++++++++++++++++++++++++ 1 file changed, 292 insertions(+) create mode 100644 addons/website/static/src/js/website.editor.js (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js new file mode 100644 index 00000000000..047a5b17557 --- /dev/null +++ b/addons/website/static/src/js/website.editor.js @@ -0,0 +1,292 @@ +(function () { + 'use strict'; + + var website = openerp.website; + + website.init_editor = function () { + var editor = new website.EditorBar(); + var $body = $(document.body); + editor.prependTo($body); + $body.css('padding-top', '50px'); // Not working properly: editor.$el.outerHeight()); + }; + /* ----- TOP EDITOR BAR FOR ADMIN ---- */ + website.EditorBar = openerp.Widget.extend({ + template: 'website.editorbar', + events: { + 'click button[data-action=edit]': 'edit', + 'click button[data-action=save]': 'save', + 'click button[data-action=cancel]': 'cancel', + }, + container: 'body', + customize_setup: function() { + var self = this; + var view_name = $(document.documentElement).data('view-xmlid'); + var menu = $('#customize-menu'); + this.$('#customize-menu-button').click(function(event) { + menu.empty(); + openerp.jsonRpc('/website/customize_template_get', 'call', { 'xml_id': view_name }).then( + function(result) { + _.each(result, function (item) { + if (item.header) { + menu.append(''); + } else { + menu.append(_.str.sprintf('
  • %s
  • ', + item.id, item.active ? '' : '-empty', item.name)); + } + }); + // Adding Static Menus + menu.append('
  • Change Theme
  • '); + } + ); + }); + menu.on('click', 'a', function (event) { + var view_id = $(event.target).data('view-id'); + openerp.jsonRpc('/website/customize_template_toggle', 'call', { + 'view_id': view_id + }).then( function(result) { + window.location.reload(); + }); + }); + }, + start: function() { + var self = this; + + this.saving_mutex = new openerp.Mutex(); + + this.$('#website-top-edit').hide(); + this.$('#website-top-view').show(); + + $('.dropdown-toggle').dropdown(); + this.customize_setup(); + + this.$buttons = { + edit: this.$('button[data-action=edit]'), + save: this.$('button[data-action=save]'), + cancel: this.$('button[data-action=cancel]'), + }; + + this.rte = new website.RTE(this); + this.rte.on('change', this, this.proxy('rte_changed')); + + return $.when( + this._super.apply(this, arguments), + this.rte.prependTo(this.$('#website-top-edit .nav.pull-right')) + ); + }, + edit: function () { + this.$buttons.edit.prop('disabled', true); + this.$('#website-top-view').hide(); + this.$('#website-top-edit').show(); + + // this.$buttons.cancel.add(this.$buttons.snippet).prop('disabled', false) + // .add(this.$buttons.save) + // .parent().show(); + // + // TODO: span edition changing edition state (save button) + var $editables = $('[data-oe-model]') + .not('link, script') + // FIXME: propagation should make "meta" blocks non-editable in the first place... + .not('.oe_snippets,.oe_snippet, .oe_snippet *') + .prop('contentEditable', true) + .addClass('oe_editable'); + var $rte_ables = $editables.not('[data-oe-type]'); + var $raw_editables = $editables.not($rte_ables); + + // temporary fix until we fix ckeditor + $raw_editables.each(function () { + $(this).parents().add($(this).find('*')).on('click', function(ev) { + ev.preventDefault(); + ev.stopPropagation(); + }); + }); + + this.rte.start_edition($rte_ables); + $raw_editables.on('keydown keypress cut paste', function (e) { + var $target = $(e.target); + if ($target.hasClass('oe_dirty')) { + return; + } + + $target.addClass('oe_dirty'); + this.$buttons.save.prop('disabled', false); + }.bind(this)); + }, + rte_changed: function () { + this.$buttons.save.prop('disabled', false); + }, + save: function () { + var self = this; + var defs = []; + observer.disconnect(); + $('.oe_dirty').each(function (i, v) { + var $el = $(this); + // TODO: Add a queue with concurrency limit in webclient + // https://github.com/medikoo/deferred/blob/master/lib/ext/function/gate.js + var def = self.saving_mutex.exec(function () { + return self.saveElement($el).then(function () { + $el.removeClass('oe_dirty'); + }).fail(function () { + var data = $el.data(); + console.error(_.str.sprintf('Could not save %s#%d#%s', data.oeModel, data.oeId, data.oeField)); + }); + }); + defs.push(def); + }); + return $.when.apply(null, defs).then(function () { + window.location.reload(); + }); + }, + saveElement: function ($el) { + var data = $el.data(); + var html = $el.html(); + var xpath = data.oeXpath; + if (xpath) { + var $w = $el.clone(); + $w.removeClass('oe_dirty'); + _.each(['model', 'id', 'field', 'xpath'], function(d) {$w.removeAttr('data-oe-' + d);}); + $w + .removeClass('oe_editable') + .prop('contentEditable', false); + html = $w.wrap('
    ').parent().html(); + } + return openerp.jsonRpc('/web/dataset/call', 'call', { + model: 'ir.ui.view', + method: 'save', + args: [data.oeModel, data.oeId, data.oeField, html, xpath] + }); + }, + cancel: function () { + window.location.reload(); + }, + }); + + /* ----- RICH TEXT EDITOR ---- */ + website.RTE = openerp.Widget.extend({ + tagName: 'li', + id: 'oe_rte_toolbar', + className: 'oe_right oe_rte_toolbar', + // editor.ui.items -> possible commands &al + // editor.applyStyle(new CKEDITOR.style({element: "span",styles: {color: "#(color)"},overrides: [{element: "font",attributes: {color: null}}]}, {color: '#ff0000'})); + + start_edition: function ($elements) { + var self = this; + $elements + .not('span, [data-oe-type]') + .each(function () { + var node = this; + var $node = $(node); + var editor = CKEDITOR.inline(this, self._config()); + editor.on('instanceReady', function () { + observer.observe(node, { + childList: true, + attributes: true, + characterData: true, + subtree: true + }); + }); + $node.one('content_changed', function () { + $node.addClass('oe_dirty'); + self.trigger('change'); + }); + }); + }, + + _current_editor: function () { + return CKEDITOR.currentInstance; + }, + _config: function () { + var removed_plugins = [ + // remove custom context menu + 'contextmenu,tabletools,liststyle', + // magicline captures mousein/mouseout => draggable does not work + 'magicline' + ]; + return { + // Disable auto-generated titles + // FIXME: accessibility, need to generate user-sensible title, used for @title and @aria-label + title: false, + removePlugins: removed_plugins.join(','), + uiColor: '', + // Ensure no config file is loaded + customConfig: '', + // Disable ACF + allowedContent: true, + // Don't insert paragraphs around content in e.g.
  • + autoParagraph: false, + filebrowserImageUploadUrl: "/website/attach", + // Support for sharedSpaces in 4.x + extraPlugins: 'sharedspace', + // Place toolbar in controlled location + sharedSpaces: { top: 'oe_rte_toolbar' }, + toolbar: [ + {name: 'basicstyles', items: [ + "Bold", "Italic", "Underline", "Strike", "Subscript", + "Superscript", "TextColor", "BGColor", "RemoveFormat" + ]},{ + name: 'span', items: [ + "Link", "Unlink", "Blockquote", "BulletedList", + "NumberedList", "Indent", "Outdent" + ]},{ + name: 'justify', items: [ + "JustifyLeft", "JustifyCenter", "JustifyRight", "JustifyBlock" + ]},{ + name: 'special', items: [ + "Image", "Table" + ]},{ + name: 'styles', items: [ + "Format", "Styles" + ]} + ], + // styles dropdown in toolbar + stylesSet: [ + // emphasis + {name: "Muted", element: 'span', attributes: {'class': 'text-muted'}}, + {name: "Primary", element: 'span', attributes: {'class': 'text-primary'}}, + {name: "Warning", element: 'span', attributes: {'class': 'text-warning'}}, + {name: "Danger", element: 'span', attributes: {'class': 'text-danger'}}, + {name: "Success", element: 'span', attributes: {'class': 'text-success'}}, + {name: "Info", element: 'span', attributes: {'class': 'text-info'}} + ], + }; + }, + }); + + + var Observer = window.MutationObserver || window.WebkitMutationObserver || window.JsMutationObserver; + var observer = new Observer(function (mutations) { + _(mutations).chain() + .filter(function (m) { + switch(m.type) { + case 'attributes': + // ignore cke_focus being added & removed from RTE root + // FIXME: what if snippets are configured by adding/removing classes on their root element? + return !$(m.target).hasClass('oe_editable'); + case 'childList': + //
    appears when focusing RTE in FF, ignore + return m.addedNodes.length !== 1 || m.addedNodes[0].nodeName !== 'BR'; + default: + return true; + } + }) + .map(function (m) { + var node = m.target; + while (node && !$(node).hasClass('oe_editable')) { + node = node.parentNode; + } + return node; + }) + .compact() + .uniq() + .each(function (node) { $(node).trigger('content_changed'); }) + }); + + website.dom_ready.done(function () { + // $.fn.data automatically parses value, '0'|'1' -> 0|1 + website.is_editable = $(document.documentElement).data('editable'); + var is_smartphone = $(document.body)[0].clientWidth < 767; + + if (website.is_editable && !is_smartphone) { + website.ready().then(website.init_editor); + } + }); +})(); -- cgit v1.2.3 From 0d64c9037dcf27d8a32515e5150e96e16ef8a75e Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 29 Aug 2013 17:34:41 +0200 Subject: [IMP] Implement custom bootstrap dialog for links. Dialog doesn't work right as it's a bootstrap 3-ish dialog, not 2, so none of the classes works correctly. Also moved editor templates outside of main website template file. bzr revid: xmo@openerp.com-20130829153441-w51n3hxxikyti0xj --- addons/website/static/src/js/website.editor.js | 210 +++++++++++++++++++++++-- 1 file changed, 199 insertions(+), 11 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 047a5b17557..fa8dc60c251 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -3,7 +3,53 @@ var website = openerp.website; + website.templates.push('/website/static/src/xml/website.editor.xml'); + website.dom_ready.done(function () { + // $.fn.data automatically parses value, '0'|'1' -> 0|1 + website.is_editable = $(document.documentElement).data('editable'); + var is_smartphone = $(document.body)[0].clientWidth < 767; + + if (website.is_editable && !is_smartphone) { + website.ready().then(website.init_editor); + } + }); + + function link_dialog(editor) { + return new website.editor.LinkDialog(editor).appendTo(document.body); + } + website.init_editor = function () { + CKEDITOR.plugins.add('customdialogs', { + requires: 'link,image', + init: function (editor) { + editor.on('doubleclick', function (evt) { + if (evt.data.dialog === 'link' || evt.data.dialog === 'image') { + delete evt.data.dialog; + link_dialog(editor); + } + // priority should be smaller than dialog (999) but bigger + // than link or image (default=10) + }, null, null, 500); + + editor.addCommand('link', { + exec: function (editor, data) { + link_dialog(editor); + return true; + }, + canUndo: false, + editorFocus: true, + }); + editor.addCommand('image', { + exec: function (editor, data) { + console.log('image', editor, data); + return true; + }, + canUndo: false, + editorFocus: true, + }); + + } + }); var editor = new website.EditorBar(); var $body = $(document.body); editor.prependTo($body); @@ -215,7 +261,7 @@ autoParagraph: false, filebrowserImageUploadUrl: "/website/attach", // Support for sharedSpaces in 4.x - extraPlugins: 'sharedspace', + extraPlugins: 'sharedspace,customdialogs', // Place toolbar in controlled location sharedSpaces: { top: 'oe_rte_toolbar' }, toolbar: [ @@ -251,6 +297,158 @@ }, }); + website.editor = { }; + website.editor.Dialog = openerp.Widget.extend({ + events: { + 'hidden': 'destroy', + }, + init: function (editor) { + this._super(); + this.editor = editor; + }, + start: function () { + var sup = this._super(); + this.$el.modal(); + return sup; + }, + }); + + website.editor.LinkDialog = website.editor.Dialog.extend({ + template: 'website.editor.dialog.link', + events: _.extend({}, website.editor.Dialog.prototype.events, { + 'click button.btn-primary': 'save', + 'change .url-source': function (e) { this.changed($(e.target)); }, + }), + init: function (editor) { + this._super(editor); + this.pages = Object.create(null); + }, + start: function () { + var element; + if ((element = this.get_selected_link()) && element.hasAttribute('href')) { + this.editor.getSelection().selectElement(element); + } + this.element = element; + + return $.when( + this.fetch_pages().done(this.proxy('fill_pages')), + this._super() + ).done(this.proxy('bind_data')); + }, + /** + * Greatly simplified version of CKEDITOR's + * plugins.link.dialogs.link.onOk. + * + * @param {String} url + * @param {Boolean} [new_window=false] + * @param {String} [label=null] + */ + make_link: function (url, new_window, label) { + var attributes = {href: url, 'data-cke-saved-href': url}; + var to_remove = []; + if (new_window) { + attributes['target'] = '_blank'; + } else { + to_remove.push('target'); + } + + if (this.element) { + this.element.setAttributes(attributes); + this.element.removeAttributes(to_remove); + } else { + var selection = this.editor.getSelection(); + var range = selection.getRanges(true)[0]; + + if (range.collapsed) { + var text = new CKEDITOR.dom.text(label || url); + range.insertNode(text); + range.selectNodeContents(text); + } + + new CKEDITOR.style({ + type: CKEDITOR.STYLE_INLINE, + element: 'a', + attributes: attributes, + }).applyToRange(range); + // blows up the call stack, not sure why as original version + // seems to work OK + // range.select(); + } + }, + save: function () { + var $e = this.$('.url-source').filter(function () { return !!this.value; }); + + var val = $e.val(); + if ($e.hasClass('email-address')) { + this.make_link('mailto:' + val, false, val); + } else if ($e.hasClass('pages')) { + this.make_link(val, false, $e.find('option:selected').text()); + } else { + this.make_link(val, this.$('input.window-new').prop('checked')); + } + this.$el.modal('hide'); + }, + bind_data: function () { + var href = this.element && (this.element.data( 'cke-saved-href') + || this.element.getAttribute('href')); + if (!href) { return; } + + var match, $control; + if (match = /(mailto):(.+)/.exec(href)) { + $control = this.$('input.email-address').val(match[2]); + } else if(href in this.pages) { + $control = this.$('select.pages').val(href); + } + if (!$control) { + $control = this.$('input.url').val(href); + } + + this.changed($control); + + this.$('input.window-new').prop( + 'checked', this.element.getAttribute('target') === '_blank'); + }, + changed: function ($e) { + $e.closest('li.list-group-item').addClass('active') + .siblings().removeClass('active'); + this.$('.url-source').not($e).val(''); + }, + /** + * CKEDITOR.plugins.link.getSelectedLink ignores the editor's root, + * if the editor is set directly on a link it will thus not work. + */ + get_selected_link: function () { + var sel = this.editor.getSelection(), + el = sel.getSelectedElement(); + if (el && el.is('a')) { return el; } + + var range = sel.getRanges(true)[0]; + if (!range) { return null; } + + range.shrink(CKEDITOR.SHRINK_TEXT); + return this.editor.elementPath(range.getCommonAncestor()) + .contains('a'); + + }, + fetch_pages: function () { + return openerp.jsonRpc('/web/dataset/call_kw', 'call', { + model: 'website', + method: 'list_pages', + args: [], + kwargs: {} + }); + }, + fill_pages: function (results) { + var self = this; + var $select = this.$('select'); + $select.append(new Option()); + _(results).each(function (result) { + self.pages[result.url] = true; + $select.append(new Option(result.name, result.url)); + }); + }, + }); + var Observer = window.MutationObserver || window.WebkitMutationObserver || window.JsMutationObserver; var observer = new Observer(function (mutations) { @@ -279,14 +477,4 @@ .uniq() .each(function (node) { $(node).trigger('content_changed'); }) }); - - website.dom_ready.done(function () { - // $.fn.data automatically parses value, '0'|'1' -> 0|1 - website.is_editable = $(document.documentElement).data('editable'); - var is_smartphone = $(document.body)[0].clientWidth < 767; - - if (website.is_editable && !is_smartphone) { - website.ready().then(website.init_editor); - } - }); })(); -- cgit v1.2.3 From b49504a7942cd6d1be31715793b82e21de3c502a Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 30 Aug 2013 11:32:11 +0200 Subject: [FIX] bootstrap 3 events bzr revid: xmo@openerp.com-20130830093211-s7bt1bawl1eftti5 --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 93d239492c6..ae5b9e95e29 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -300,7 +300,7 @@ website.editor = { }; website.editor.Dialog = openerp.Widget.extend({ events: { - 'hidden': 'destroy', + 'hidden.bs.modal': 'destroy', }, init: function (editor) { this._super(); -- cgit v1.2.3 From 1916b769ac64d99e200f4ed597444b1c0e585f02 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 2 Sep 2013 09:52:16 +0200 Subject: [ADD] bootstrap image dialog, behavior missing bzr revid: xmo@openerp.com-20130902075216-4y83ed2r19z2fgha --- addons/website/static/src/js/website.editor.js | 65 ++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 9 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index ae5b9e95e29..5562bf2ca66 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -17,15 +17,21 @@ function link_dialog(editor) { return new website.editor.LinkDialog(editor).appendTo(document.body); } + function image_dialog(editor) { + return new website.editor.ImageDialog(editor).appendTo(document.body); + } website.init_editor = function () { CKEDITOR.plugins.add('customdialogs', { requires: 'link,image', init: function (editor) { editor.on('doubleclick', function (evt) { - if (evt.data.dialog === 'link' || evt.data.dialog === 'image') { + if (evt.data.dialog === 'link') { delete evt.data.dialog; link_dialog(editor); + } else if(evt.data.dialog === 'image') { + delete evt.data.dialog; + image_dialog(editor); } // priority should be smaller than dialog (999) but bigger // than link or image (default=10) @@ -41,7 +47,7 @@ }); editor.addCommand('image', { exec: function (editor, data) { - console.log('image', editor, data); + image_dialog(editor); return true; }, canUndo: false, @@ -138,13 +144,17 @@ var $rte_ables = $editables.not('[data-oe-type]'); var $raw_editables = $editables.not($rte_ables); - // temporary fix until we fix ckeditor - $raw_editables.each(function () { - $(this).parents().add($(this).find('*')).on('click', function(ev) { - ev.preventDefault(); - ev.stopPropagation(); + // temporary: on raw editables, links are still active so an + // editable link, containing a link or within a link becomes very + // hard to edit. Disable linking for these. + $raw_editables.parents('a') + .add($raw_editables.find('a')) + .on('click', function (e) { + // Don't alter bubbling events not coming from links + if (e.target === e.currentTarget) { + e.preventDefault(); + } }); - }); this.rte.start_edition($rte_ables); $raw_editables.on('keydown keypress cut paste', function (e) { @@ -301,6 +311,7 @@ website.editor.Dialog = openerp.Widget.extend({ events: { 'hidden.bs.modal': 'destroy', + 'click button.save': 'save', }, init: function (editor) { this._super(); @@ -311,6 +322,9 @@ this.$el.modal(); return sup; }, + save: function () { + this.$el.modal('hide'); + }, }); website.editor.LinkDialog = website.editor.Dialog.extend({ @@ -386,7 +400,7 @@ } else { this.make_link(val, this.$('input.window-new').prop('checked')); } - this.$el.modal('hide'); + this._super(); }, bind_data: function () { var href = this.element && (this.element.data( 'cke-saved-href') @@ -448,6 +462,39 @@ }); }, }); + website.editor.ImageDialog = website.editor.Dialog.extend({ + template: 'website.editor.dialog.image', + events: _.extend({}, website.editor.Dialog.prototype.events, { + 'change .url-source': function (e) { this.changed($(e.target)); }, + 'click button.filepicker': function () { + this.$('input[type=file]').click(); + }, + 'change input[type=file]': 'file_selection', + }), + + file_selection: function (e) { + this.$('button.filepicker').removeClass('btn-danger btn-success'); + + var self = this; + var callback = _.uniqueId('func_'); + this.$('input[name=func]').val(callback); + + window[callback] = function (url, error) { + delete window[callback]; + self.file_selected(url, error); + }; + this.$('form').submit(); + }, + file_selected: function(url, error) { + var $button = this.$('button.filepicker'); + if (error) { + $button.addClass('btn-danger'); + return; + } + $button.addClass('btn-success'); + this.$('input.url').val(url); + }, + }); var Observer = window.MutationObserver || window.WebkitMutationObserver || window.JsMutationObserver; -- cgit v1.2.3 From 2f97feb322221dc047004af0b9f28bb592b760f3 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 2 Sep 2013 12:54:11 +0200 Subject: [ADD] interaction between RTE and bootstrap image modal bzr revid: xmo@openerp.com-20130902105411-ni3klun0k8v1tmjg --- addons/website/static/src/js/website.editor.js | 28 ++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 5562bf2ca66..ee14b113e8e 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -471,6 +471,34 @@ }, 'change input[type=file]': 'file_selection', }), + start: function () { + var selection = this.editor.getSelection(); + var el = selection && selection.getSelectedElement(); + this.element = null; + if (el && el.is('img')) { + this.element = el; + this.$('input.url').val(el.getAttribute('src')); + } + + return this._super(); + }, + save: function () { + var url = this.$('input.url').val(); + var element, editor = this.editor; + if (!(element = this.element)) { + element = editor.document.createElement('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 => + // defer insertion so modal has been hidden & destroyed before + // it happens + setTimeout(function () { + editor.insertElement(element); + }, 0); + } + element.setAttribute('src', url); + this._super(); + }, file_selection: function (e) { this.$('button.filepicker').removeClass('btn-danger btn-success'); -- cgit v1.2.3 From 9733c396fe1ca31f584b2775a7ff59ae7b2b4914 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 2 Sep 2013 12:56:37 +0200 Subject: [FIX] correctly select range after inserting a link in the document Apparently same issue as noted in xmo@openerp.com-20130902105411-ni3klun0k8v1tmjg, RTE and bootstrap modal fight for focus (oddly not in Firefox), leading to the callstack blowing up (after a fraction of a second of browser freezing). Use same remedy, defer focus-manipulating operation to after the dialog has been removed and destroyed in order to avoid focus fight. bzr revid: xmo@openerp.com-20130902105637-1y9aogm1yx9z81jt --- addons/website/static/src/js/website.editor.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index ee14b113e8e..912d3705286 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -384,9 +384,12 @@ element: 'a', attributes: attributes, }).applyToRange(range); - // blows up the call stack, not sure why as original version - // seems to work OK - // range.select(); + + // focus dance between RTE & dialog blow up the stack in Safari + // and Chrome, so defer select() until dialog has been closed + setTimeout(function () { + range.select(); + }, 0); } }, save: function () { -- cgit v1.2.3 From 00c898378b72f1cef7da99143e36ae6dc15a9923 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Mon, 2 Sep 2013 17:11:40 +0200 Subject: [FIX] website.editor.js: customize click event bzr revid: chm@openerp.com-20130902151140-jmhcyuuzoxbhlilo --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 912d3705286..5ad17451bac 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -92,7 +92,7 @@ ); }); menu.on('click', 'a', function (event) { - var view_id = $(event.target).data('view-id'); + var view_id = $(event.currentTarget).data('view-id'); openerp.jsonRpc('/website/customize_template_toggle', 'call', { 'view_id': view_id }).then( function(result) { -- cgit v1.2.3 From cf9ab25816b47a2e501f5cb4b155441c45212ab2 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 2 Sep 2013 15:49:20 +0200 Subject: [ADD] image preview to dialog bzr revid: xmo@openerp.com-20130902134920-um72bldsv19mf5ij --- addons/website/static/src/js/website.editor.js | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 5ad17451bac..158aafd06f6 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -473,6 +473,7 @@ this.$('input[type=file]').click(); }, 'change input[type=file]': 'file_selection', + 'change input.url': 'preview_image', }), start: function () { var selection = this.editor.getSelection(); @@ -481,6 +482,7 @@ if (el && el.is('img')) { this.element = el; this.$('input.url').val(el.getAttribute('src')); + this.preview_image(); } return this._super(); @@ -524,6 +526,13 @@ } $button.addClass('btn-success'); this.$('input.url').val(url); + this.preview_image(); + }, + preview_image: function () { + var image = this.$('input.url').val(); + if (!image) { return; } + + this.$('img').attr('src', image); }, }); -- cgit v1.2.3 From c89d31ca95ab311d720b4754b624bd887d77016d Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 3 Sep 2013 16:32:37 +0200 Subject: [ADD] creation of new page from link dialog * Replace select by input with dropdown * Add random crap to /pagenew so it does not blow up when a butterfly flaps its wings, also so it's possible to call it through xhr and get something out of it * Fix duplicated save() call in link dialog widget thing bzr revid: xmo@openerp.com-20130903143237-6pwsbqzc02bv3mri --- addons/website/static/src/js/website.editor.js | 47 +++++++++++++++++++++----- 1 file changed, 38 insertions(+), 9 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 158aafd06f6..5c8f1605415 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -330,12 +330,15 @@ website.editor.LinkDialog = website.editor.Dialog.extend({ template: 'website.editor.dialog.link', events: _.extend({}, website.editor.Dialog.prototype.events, { - 'click button.btn-primary': 'save', 'change .url-source': function (e) { this.changed($(e.target)); }, + 'click div.existing a': 'select_page', }), init: function (editor) { this._super(editor); + // url -> name mapping for existing pages this.pages = Object.create(null); + // name -> url mapping for the same + this.pages_by_name = Object.create(null); }, start: function () { var element; @@ -393,17 +396,30 @@ } }, save: function () { + var self = this, _super = this._super.bind(this); var $e = this.$('.url-source').filter(function () { return !!this.value; }); - var val = $e.val(); + var val = $e.val(), done = $.when(); if ($e.hasClass('email-address')) { this.make_link('mailto:' + val, false, val); } else if ($e.hasClass('pages')) { - this.make_link(val, false, $e.find('option:selected').text()); + // ``val`` is the *name* of the page + var url = this.pages_by_name[val]; + if (!url) { + // Create the page, get the URL back + done = $.get(_.str.sprintf( + '/pagenew/%s?noredirect', encodeURIComponent(val))) + .then(function (response) { + url = response; + }); + } + done.then(function () { + self.make_link(url, false, val); + }); } else { this.make_link(val, this.$('input.window-new').prop('checked')); } - this._super(); + done.then(_super); }, bind_data: function () { var href = this.element && (this.element.data( 'cke-saved-href') @@ -414,7 +430,7 @@ if (match = /(mailto):(.+)/.exec(href)) { $control = this.$('input.email-address').val(match[2]); } else if(href in this.pages) { - $control = this.$('select.pages').val(href); + $control = this.$('input.pages').val(this.pages[href]); } if (!$control) { $control = this.$('input.url').val(href); @@ -430,6 +446,18 @@ .siblings().removeClass('active'); this.$('.url-source').not($e).val(''); }, + /** + * Selected an existing page in dropdown + */ + select_page: function (e) { + e.preventDefault(); + e.stopPropagation(); + var $target = $(e.target); + this.$('input.pages').val($target.text()).change(); + // No #dropdown('close'), and using #dropdown('toggle') sur + // #closest('.dropdown') makes the dropdown not work correctly + $target.closest('.open').removeClass('open') + }, /** * CKEDITOR.plugins.link.getSelectedLink ignores the editor's root, * if the editor is set directly on a link it will thus not work. @@ -457,11 +485,12 @@ }, fill_pages: function (results) { var self = this; - var $select = this.$('select'); - $select.append(new Option()); + var $pages = this.$('div.existing ul').empty(); _(results).each(function (result) { - self.pages[result.url] = true; - $select.append(new Option(result.name, result.url)); + self.pages[result.url] = result.name; + self.pages_by_name[result.name] = result.url; + var $link = $('').attr('href', result.url).text(result.name); + $('
  • ').append($link).appendTo($pages); }); }, }); -- cgit v1.2.3 From 7704ce7e03b0fb6d27f24873739190a10086d26d Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 4 Sep 2013 10:49:58 +0200 Subject: [IMP] website_sale: add product in website bzr revid: chm@openerp.com-20130904084958-6rq5xu0xjwzcv399 --- addons/website/static/src/js/website.editor.js | 1 + 1 file changed, 1 insertion(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 5c8f1605415..941a0f7cd69 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -129,6 +129,7 @@ this.$buttons.edit.prop('disabled', true); this.$('#website-top-view').hide(); this.$('#website-top-edit').show(); + $('.css_non_editable_mode_hidden').removeClass("css_non_editable_mode_hidden"); // this.$buttons.cancel.add(this.$buttons.snippet).prop('disabled', false) // .add(this.$buttons.save) -- cgit v1.2.3 From 4932521377aa38891617c3bd4add15473b996a0c Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 4 Sep 2013 13:32:22 +0200 Subject: [ADD] selection of existing image in image dialog bzr revid: xmo@openerp.com-20130904113222-xync5o48nwngvtj4 --- addons/website/static/src/js/website.editor.js | 55 ++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 7 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 941a0f7cd69..42e35ea0d65 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -504,6 +504,7 @@ }, 'change input[type=file]': 'file_selection', 'change input.url': 'preview_image', + 'click .existing-attachments a': 'select_existing', }), start: function () { var selection = this.editor.getSelection(); @@ -511,11 +512,12 @@ this.element = null; if (el && el.is('img')) { this.element = el; - this.$('input.url').val(el.getAttribute('src')); - this.preview_image(); + this.set_image(el.getAttribute('src')); } - return this._super(); + return $.when( + this._super(), + this.fetch_existing().then(this.proxy('fetched_existing'))); }, save: function () { var url = this.$('input.url').val(); @@ -535,6 +537,15 @@ this._super(); }, + /** + * Sets the provided image url as the dialog's value-to-save and + * refreshes the preview element to use it. + */ + set_image: function (url) { + this.$('input.url').val(url); + this.preview_image(); + }, + file_selection: function (e) { this.$('button.filepicker').removeClass('btn-danger btn-success'); @@ -555,22 +566,52 @@ return; } $button.addClass('btn-success'); - this.$('input.url').val(url); - this.preview_image(); + this.set_image(url); }, preview_image: function () { var image = this.$('input.url').val(); if (!image) { return; } - this.$('img').attr('src', image); + this.$('img.image-preview').attr('src', image); + }, + + fetch_existing: function () { + // FIXME: lazy load attachments? + return openerp.jsonRpc('/web/dataset/call_kw', 'call', { + model: 'ir.attachment', + method: 'search_read', + args: [], + kwargs: { + fields: ['name'], + domain: [['res_model', '=', 'ir.ui.view']], + order: 'name', + } + }); + }, + fetched_existing: function (records) { + // Create rows of 3 records + var rows = _(records).chain() + .groupBy(function (_, index) { return Math.floor(index / 3); }) + .values() + .value(); + this.$('.existing-attachments').replaceWith( + openerp.qweb.render('website.editor.dialog.image.existing', {rows: rows})); + }, + select_existing: function (e) { + e.preventDefault(); + this.set_image(e.currentTarget.getAttribute('href')); }, }); var Observer = window.MutationObserver || window.WebkitMutationObserver || window.JsMutationObserver; var observer = new Observer(function (mutations) { + // NOTE: Webkit does not fire DOMAttrModified => webkit browsers + // relying on JsMutationObserver shim (Chrome < 18, Safari < 6) + // will not mark dirty on attribute changes (@class, img/@src, + // a/@href, ...) _(mutations).chain() - .filter(function (m) { + .filter(function (m) { switch(m.type) { case 'attributes': // ignore cke_focus being added & removed from RTE root -- cgit v1.2.3 From b56cd5e2bec421ee34bcb561ede46cc5832a4cbb Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 4 Sep 2013 15:17:45 +0200 Subject: [IMP] merge Format and Styles dropdowns bzr revid: xmo@openerp.com-20130904131745-ro5c0c7myvyv98xw --- addons/website/static/src/js/website.editor.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 42e35ea0d65..0ac26fe91db 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -291,11 +291,20 @@ "Image", "Table" ]},{ name: 'styles', items: [ - "Format", "Styles" + "Styles" ]} ], // styles dropdown in toolbar stylesSet: [ + {name: "Normal", element: 'p'}, + {name: "Heading 1", element: 'h1'}, + {name: "Heading 2", element: 'h2'}, + {name: "Heading 3", element: 'h3'}, + {name: "Heading 4", element: 'h4'}, + {name: "Heading 5", element: 'h5'}, + {name: "Heading 6", element: 'h6'}, + {name: "Formatted", element: 'pre'}, + {name: "Address", element: 'address'}, // emphasis {name: "Muted", element: 'span', attributes: {'class': 'text-muted'}}, {name: "Primary", element: 'span', attributes: {'class': 'text-primary'}}, -- cgit v1.2.3 From cdffb9943f9a1f991cf6a5b097ec7085f4c66f0d Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 4 Sep 2013 16:07:44 +0200 Subject: [IMP] mutations filtering, only ignore cke_focus being removed, not all editor root changes bzr revid: xmo@openerp.com-20130904140744-5ytn6bwfxrv52g9f --- addons/website/static/src/js/website.editor.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 0ac26fe91db..493526d2b0c 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -238,7 +238,8 @@ childList: true, attributes: true, characterData: true, - subtree: true + subtree: true, + attributeOldValue: true, }); }); $node.one('content_changed', function () { @@ -622,10 +623,17 @@ _(mutations).chain() .filter(function (m) { switch(m.type) { - case 'attributes': - // ignore cke_focus being added & removed from RTE root - // FIXME: what if snippets are configured by adding/removing classes on their root element? - return !$(m.target).hasClass('oe_editable'); + case 'attributes': // ignore .cke_focus being added or removed + // if attribute is not a class, can't be .cke_focus change + if (m.attributeName !== 'class') { return true; } + + // find out what classes were added or removed + var oldClasses = m.oldValue.split(/\s+/); + var newClasses = m.target.className.split(/\s+/); + var change = _.union(_.difference(oldClasses, newClasses), + _.difference(newClasses, oldClasses)); + // ignore mutation if the *only* change is .cke_focus + return change.length !== 1 || change[0] === 'cke_focus'; case 'childList': //
    appears when focusing RTE in FF, ignore return m.addedNodes.length !== 1 || m.addedNodes[0].nodeName !== 'BR'; -- cgit v1.2.3 From 35fb66e8cfa829835659c98fbb271a42ad0308d0 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 4 Sep 2013 16:12:47 +0200 Subject: [IMP] use mutation observers on non-RTE editions bzr revid: xmo@openerp.com-20130904141247-0bjm69ooy310egoj --- addons/website/static/src/js/website.editor.js | 31 +++++++++++++------------- 1 file changed, 15 insertions(+), 16 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 493526d2b0c..8832d5cf1c8 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -126,6 +126,7 @@ ); }, edit: function () { + var self = this; this.$buttons.edit.prop('disabled', true); this.$('#website-top-view').hide(); this.$('#website-top-edit').show(); @@ -158,15 +159,12 @@ }); this.rte.start_edition($rte_ables); - $raw_editables.on('keydown keypress cut paste', function (e) { - var $target = $(e.target); - if ($target.hasClass('oe_dirty')) { - return; - } - - $target.addClass('oe_dirty'); - this.$buttons.save.prop('disabled', false); - }.bind(this)); + $raw_editables.each(function () { + observer.observe(this, OBSERVER_CONFIG); + }).one('content_changed', function () { + $(this).addClass('oe_dirty'); + self.rte_changed(); + }); }, rte_changed: function () { this.$buttons.save.prop('disabled', false); @@ -234,13 +232,7 @@ var $node = $(node); var editor = CKEDITOR.inline(this, self._config()); editor.on('instanceReady', function () { - observer.observe(node, { - childList: true, - attributes: true, - characterData: true, - subtree: true, - attributeOldValue: true, - }); + observer.observe(node, OBSERVER_CONFIG); }); $node.one('content_changed', function () { $node.addClass('oe_dirty'); @@ -615,6 +607,13 @@ var Observer = window.MutationObserver || window.WebkitMutationObserver || window.JsMutationObserver; + var OBSERVER_CONFIG = { + childList: true, + attributes: true, + characterData: true, + subtree: true, + attributeOldValue: true, + }; var observer = new Observer(function (mutations) { // NOTE: Webkit does not fire DOMAttrModified => webkit browsers // relying on JsMutationObserver shim (Chrome < 18, Safari < 6) -- cgit v1.2.3 From 43ca2585c58f78ec151c3915bac6bf0ee7dfda97 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 4 Sep 2013 17:10:21 +0200 Subject: [FIX] don't try to be brokenly clever about preventing click on links during edition bzr revid: xmo@openerp.com-20130904151021-otzw635in9lhh1e1 --- addons/website/static/src/js/website.editor.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 8832d5cf1c8..32e77acedab 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -152,10 +152,7 @@ $raw_editables.parents('a') .add($raw_editables.find('a')) .on('click', function (e) { - // Don't alter bubbling events not coming from links - if (e.target === e.currentTarget) { - e.preventDefault(); - } + e.preventDefault(); }); this.rte.start_edition($rte_ables); -- cgit v1.2.3 From e56953d94e71854ed57540743a6a00e6ceafe9ba Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 6 Sep 2013 10:50:45 +0200 Subject: [ADD] new table-creation button bzr revid: xmo@openerp.com-20130906085045-zpemzy2akh3bz7q3 --- addons/website/static/src/js/website.editor.js | 64 +++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 32e77acedab..3ccd331cc48 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -53,9 +53,69 @@ canUndo: false, editorFocus: true, }); + } + }); + CKEDITOR.plugins.add( 'tablebutton', { + requires: 'panelbutton,floatpanel', + init: function( editor ) { + var label = "Table"; + + editor.ui.add('TableButton', CKEDITOR.UI_PANELBUTTON, { + label: label, + title: label, + // use existing 'table' icon + icon: 'table', + modes: { wysiwyg: true }, + editorFocus: true, + // panel opens in iframe, @css is CSS file -ed within + // frame document, @attributes are set on iframe itself. + panel: { + css: '/website/static/src/css/editor.css', + attributes: { 'role': 'listbox', 'aria-label': label, }, + }, + onBlock: function (panel, block) { + block.autoSize = true; + block.element.setHtml(openerp.qweb.render('website.editor.table.panel', { + rows: 5, + cols: 5, + })); + + var $table = $(block.element.$).on('mouseenter', 'td', function (e) { + var $e = $(e.target); + var y = $e.index() + 1; + var x = $e.closest('tr').index() + 1; + + $table + .find('td').removeClass('selected').end() + .find('tr:lt(' + String(x) + ')') + .children().filter(function () { return $(this).index() < y; }) + .addClass('selected'); + }).on('click', 'td', function (e) { + var $e = $(e.target); + + var table = new CKEDITOR.dom.element( + $(openerp.qweb.render('website.editor.table', { + rows: $e.closest('tr').index() + 1, + cols: $e.index() + 1, + }))[0]); + + editor.insertElement(table); + setTimeout(function () { + var firstCell = new CKEDITOR.dom.element(table.$.rows[0].cells[0]); + var range = editor.createRange(); + range.moveToPosition(firstCell, CKEDITOR.POSITION_AFTER_START); + range.select(); + }, 0); + }); + + block.element.getDocument().getBody().setStyle('overflow', 'hidden'); + CKEDITOR.ui.fire('ready', this); + }, + }); } }); + var editor = new website.EditorBar(); var $body = $(document.body); editor.prependTo($body); @@ -262,7 +322,7 @@ autoParagraph: false, filebrowserImageUploadUrl: "/website/attach", // Support for sharedSpaces in 4.x - extraPlugins: 'sharedspace,customdialogs', + extraPlugins: 'sharedspace,customdialogs,tablebutton', // Place toolbar in controlled location sharedSpaces: { top: 'oe_rte_toolbar' }, toolbar: [ @@ -278,7 +338,7 @@ "JustifyLeft", "JustifyCenter", "JustifyRight", "JustifyBlock" ]},{ name: 'special', items: [ - "Image", "Table" + "Image", "TableButton" ]},{ name: 'styles', items: [ "Styles" -- cgit v1.2.3 From 81118812a89091b7dfcabcf24a86ca4bf92a38ca Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 6 Sep 2013 15:09:16 +0200 Subject: [ADD] moved view.save method from server bzr revid: xmo@openerp.com-20130906130916-txj4mwhulb89kpov --- addons/website/static/src/js/website.editor.js | 5 ----- 1 file changed, 5 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 3ccd331cc48..a98376ae30f 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -192,11 +192,6 @@ this.$('#website-top-edit').show(); $('.css_non_editable_mode_hidden').removeClass("css_non_editable_mode_hidden"); - // this.$buttons.cancel.add(this.$buttons.snippet).prop('disabled', false) - // .add(this.$buttons.save) - // .parent().show(); - // - // TODO: span edition changing edition state (save button) var $editables = $('[data-oe-model]') .not('link, script') // FIXME: propagation should make "meta" blocks non-editable in the first place... -- cgit v1.2.3 From 4d1cc6a4ed499ddd8541fb37810a6728da66f9d1 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Fri, 6 Sep 2013 17:04:08 +0200 Subject: [WIP] website: snippets bzr revid: chm@openerp.com-20130906150408-81qzb2492lwqf7lb --- addons/website/static/src/js/website.editor.js | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 32e77acedab..b4c35042350 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -220,6 +220,11 @@ // editor.ui.items -> possible commands &al // editor.applyStyle(new CKEDITOR.style({element: "span",styles: {color: "#(color)"},overrides: [{element: "font",attributes: {color: null}}]}, {color: '#ff0000'})); + init: function (EditorBar) { + this.EditorBar = EditorBar; + this._super.apply(this, arguments); + }, + start_edition: function ($elements) { var self = this; $elements @@ -229,6 +234,7 @@ var $node = $(node); var editor = CKEDITOR.inline(this, self._config()); editor.on('instanceReady', function () { + self.trigger('instanceReady'); observer.observe(node, OBSERVER_CONFIG); }); $node.one('content_changed', function () { -- cgit v1.2.3 From 19c8912cb30b4b4c4147830f50764505c0f240dc Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 9 Sep 2013 11:51:12 +0200 Subject: [FIX] updated save, save RPC call bzr revid: xmo@openerp.com-20130909095112-yihzl1oyop9641uj --- addons/website/static/src/js/website.editor.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index f1fffd495b0..238e89b0f7c 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -266,10 +266,10 @@ .removeClass('oe_editable') .removeAttribute('contentEditable'); var data = element.getOuterHtml(); - return new openerp.web.Model('ir.ui.view').call('save', { - res_id: element.data('oe-id'), - xpath: element.data('oe-xpath'), - value: data, + return openerp.jsonRpc('/web/dataset/call', 'call', { + model: 'ir.ui.view', + method: 'save', + args: [element.data('oe-id'), element.data('oe-xpath'), data], }); }, cancel: function () { -- cgit v1.2.3 From 55a84256a3143f811f22f94902fdf7b554eab854 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 9 Sep 2013 12:42:38 +0200 Subject: [FIX] make RTE activate again bzr revid: xmo@openerp.com-20130909104238-6deglc3axbu8zsez --- addons/website/static/src/js/website.editor.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 238e89b0f7c..ab9a0ce9f08 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -37,6 +37,7 @@ // than link or image (default=10) }, null, null, 500); + //noinspection JSValidateTypes editor.addCommand('link', { exec: function (editor, data) { link_dialog(editor); @@ -45,6 +46,7 @@ canUndo: false, editorFocus: true, }); + //noinspection JSValidateTypes editor.addCommand('image', { exec: function (editor, data) { image_dialog(editor); @@ -94,6 +96,7 @@ }).on('click', 'td', function (e) { var $e = $(e.target); + //noinspection JSPotentiallyInvalidConstructorUsage var table = new CKEDITOR.dom.element( $(openerp.qweb.render('website.editor.table', { rows: $e.closest('tr').index() + 1, @@ -102,6 +105,7 @@ editor.insertElement(table); setTimeout(function () { + //noinspection JSPotentiallyInvalidConstructorUsage var firstCell = new CKEDITOR.dom.element(table.$.rows[0].cells[0]); var range = editor.createRange(); range.moveToPosition(firstCell, CKEDITOR.POSITION_AFTER_START); @@ -318,8 +322,9 @@ title: false, removePlugins: removed_plugins.join(','), uiColor: '', - // Ensure no config file is loaded - customConfig: '', + // FIXME: currently breaks RTE? +// // Ensure no config file is loaded +// customConfig: '', // Disable ACF allowedContent: true, // Don't insert paragraphs around content in e.g.
  • @@ -441,11 +446,13 @@ var range = selection.getRanges(true)[0]; if (range.collapsed) { + //noinspection JSPotentiallyInvalidConstructorUsage var text = new CKEDITOR.dom.text(label || url); range.insertNode(text); range.selectNodeContents(text); } + //noinspection JSPotentiallyInvalidConstructorUsage new CKEDITOR.style({ type: CKEDITOR.STYLE_INLINE, element: 'a', @@ -681,7 +688,7 @@ // will not mark dirty on attribute changes (@class, img/@src, // a/@href, ...) _(mutations).chain() - .filter(function (m) { + .filter(function (m) { switch(m.type) { case 'attributes': // ignore .cke_focus being added or removed // if attribute is not a class, can't be .cke_focus change -- cgit v1.2.3 From 2cbfb88437797c4d5d83df8ec12c8d15f1bfc619 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 9 Sep 2013 13:10:40 +0200 Subject: [FIX] order parameter in view.save call bzr revid: xmo@openerp.com-20130909111040-ijffmxt8i81h5ynq --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index ab9a0ce9f08..6607118ea6b 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -273,7 +273,7 @@ return openerp.jsonRpc('/web/dataset/call', 'call', { model: 'ir.ui.view', method: 'save', - args: [element.data('oe-id'), element.data('oe-xpath'), data], + args: [element.data('oe-id'), data, element.data('oe-xpath')], }); }, cancel: function () { -- cgit v1.2.3 From 0b199c50e5ee2a85a4a4826b033fecc013bb0e70 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Mon, 9 Sep 2013 15:28:00 +0200 Subject: [WIP] website: snippets: box snippet widget with resize options on click bzr revid: chm@openerp.com-20130909132800-au0lgkf8thirsv8r --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index b4c35042350..8274be4acff 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -462,7 +462,7 @@ this.$('input.pages').val($target.text()).change(); // No #dropdown('close'), and using #dropdown('toggle') sur // #closest('.dropdown') makes the dropdown not work correctly - $target.closest('.open').removeClass('open') + $target.closest('.open').removeClass('open'); }, /** * CKEDITOR.plugins.link.getSelectedLink ignores the editor's root, -- cgit v1.2.3 From ca40afd144b58afee97cf88f7adf22872a37dc6e Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 9 Sep 2013 17:23:12 +0200 Subject: [FIX] necessary widget implementation ``inline`` is now automatically inferred on a per-widget basis if not specified. ``inline`` true|false tells the widget whether it should work on inlines (e.g. span) or blocks (e.g. p). Specifying the wrong one blows up because the wrapper is incorrect (inline==false on an inline element will wrap it in a div and add linefeeds, inline==true on a block element will wrap it in a span which will automatically split up in multiple elements leading to downcast blowing up because the wrong wrapper will be selected). Since last time, inline inference was added: if *unspecified* widget will check what type of object it's called on (using ``CKEDITOR.dtd.$inline``) and generate the correct wrapper for that type. => fix misbehavior by removing explicit inline spec. Also remove unused init and data methods. bzr revid: xmo@openerp.com-20130909152312-1m5kwvgw04gcrfkv --- addons/website/static/src/js/website.editor.js | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 6607118ea6b..e1ff19c505b 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -125,24 +125,8 @@ init: function (editor) { editor.widgets.add('oeref', { - inline: true, - // dialog: 'oeref', - allowedContent: '[data-oe-type]', editables: { text: '*' }, - init: function () { - var element = this.element; - this.setData({ - model: element.data('oe-model'), - id: parseInt(element.data('oe-id'), 10), - field: element.data('oe-field'), - }); - }, - data: function () { - this.element.data('oe-model', this.data.model); - this.element.data('oe-id', this.data.id); - this.element.data('oe-field', this.data.field); - }, upcast: function (el) { return el.attributes['data-oe-type']; }, -- cgit v1.2.3 From 7c45e5976e6caf3d7b9eb508f728062704232261 Mon Sep 17 00:00:00 2001 From: ddm Date: Mon, 9 Sep 2013 23:46:26 +0200 Subject: CMS basic view editing bzr revid: ddm@openerp.com-20130909214626-51zfydwbw624heqz --- addons/website/static/src/js/website.editor.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index a98376ae30f..c3f590c98d0 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -148,10 +148,11 @@ }); // Adding Static Menus menu.append('
  • Change Theme
  • '); + menu.append('
  • Ace
  • '); } ); }); - menu.on('click', 'a', function (event) { + menu.on('click', 'a[data-action!=ace]', function (event) { var view_id = $(event.currentTarget).data('view-id'); openerp.jsonRpc('/website/customize_template_toggle', 'call', { 'view_id': view_id -- cgit v1.2.3 From 35a0a0b5ea4055875509d7c620775cd311cec9be Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 10 Sep 2013 08:57:56 +0200 Subject: [FIX] default plugins changes? Explicitly configure CKEDITOR plugins from now on bzr revid: xmo@openerp.com-20130910065756-99kz2z4kddt4f7bo --- addons/website/static/src/js/website.editor.js | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index e1ff19c505b..1ea1c35e8b2 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -294,21 +294,29 @@ return CKEDITOR.currentInstance; }, _config: function () { - var removed_plugins = [ - // remove custom context menu - 'contextmenu,tabletools,liststyle', - // magicline captures mousein/mouseout => draggable does not work - 'magicline' + // base plugins minus + // - magicline (captures mousein/mouseout -> breaks draggable) + // - contextmenu & tabletools (disable contextual menu) + // - bunch of unused plugins + var plugins = [ + 'a11yhelp', 'basicstyles', 'bidi', 'blockquote', + 'clipboard', 'colorbutton', 'colordialog', 'dialogadvtab', + 'elementspath', 'enterkey', 'entities', 'filebrowser', + 'find', 'floatingspace','format', 'htmlwriter', 'iframe', + 'image', 'indentblock', 'indentlist', 'justify', 'link', + 'list', 'pastefromword', 'pastetext', 'preview', + 'removeformat', 'resize', 'save', 'selectall', 'stylescombo', + 'tab', 'table', 'templates', 'toolbar', 'undo', 'wysiwygarea' ]; return { // Disable auto-generated titles // FIXME: accessibility, need to generate user-sensible title, used for @title and @aria-label title: false, - removePlugins: removed_plugins.join(','), + plugins: plugins.join(','), uiColor: '', // FIXME: currently breaks RTE? -// // Ensure no config file is loaded -// customConfig: '', + // Ensure no config file is loaded + customConfig: '', // Disable ACF allowedContent: true, // Don't insert paragraphs around content in e.g.
  • -- cgit v1.2.3 From 44e75d37b196b6d33b95e87a4f254d59d828b4f5 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 10 Sep 2013 09:31:12 +0200 Subject: [FIX] markup cleanup: don't forget to remove oe_dirty flag class bzr revid: xmo@openerp.com-20130910073112-nibl2n2qo3adkppe --- addons/website/static/src/js/website.editor.js | 1 + 1 file changed, 1 insertion(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 1ea1c35e8b2..c7464de128a 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -251,6 +251,7 @@ var element = editor.element; editor.destroy(); element.removeClass('cke_focus') + .removeClass('oe_dirty') .removeClass('oe_editable') .removeAttribute('contentEditable'); var data = element.getOuterHtml(); -- cgit v1.2.3 From 8356560144d931c9df22e30a5b178379c11dc9cc Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 10 Sep 2013 10:56:04 +0200 Subject: [IMP] move global CKEDITOR configuration to JS code bzr revid: xmo@openerp.com-20130910085604-pye2vm3wo8qev11d --- addons/website/static/src/js/website.editor.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index c7464de128a..efcd1e31925 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -2,11 +2,11 @@ 'use strict'; 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 () { - // $.fn.data automatically parses value, '0'|'1' -> 0|1 - website.is_editable = $(document.documentElement).data('editable'); var is_smartphone = $(document.body)[0].clientWidth < 767; if (website.is_editable && !is_smartphone) { @@ -21,6 +21,13 @@ return new website.editor.ImageDialog(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); + } website.init_editor = function () { CKEDITOR.plugins.add('customdialogs', { requires: 'link,image', -- cgit v1.2.3 From 688cd146eff19f7b646ce09c86840cebb32aeef9 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 10 Sep 2013 11:02:32 +0200 Subject: [FIX] disable removal of empty elements in ckeditor we use empty elements for fontawesome icons, ckeditor removing them is unexpected and bad nogood. bzr revid: xmo@openerp.com-20130910090232-p6t5qaveo2q2nyth --- addons/website/static/src/js/website.editor.js | 3 +++ 1 file changed, 3 insertions(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index efcd1e31925..867cef2ed13 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -27,6 +27,9 @@ // 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', { -- cgit v1.2.3 From a109098cb782aa8d44d4091035e6707b4161a70d Mon Sep 17 00:00:00 2001 From: ddm Date: Tue, 10 Sep 2013 12:01:27 +0200 Subject: [FIX] Proper editor sizing bzr revid: ddm@openerp.com-20130910100127-98zjbitry2xhqld2 --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index c3f590c98d0..993038347bf 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -148,7 +148,7 @@ }); // Adding Static Menus menu.append('
  • Change Theme
  • '); - menu.append('
  • Ace
  • '); + menu.append('
  • Advanced view editor
  • '); } ); }); -- cgit v1.2.3 From f61e65539eadd44be7894395d0b50cc97a73d0f9 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 10 Sep 2013 14:26:46 +0200 Subject: [IMP] website: auto open editor when create new product (use ?unable_editor in url) bzr revid: chm@openerp.com-20130910122646-ug8dn61rqgbm3eq3 --- addons/website/static/src/js/website.editor.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 8056998eef9..dff61f1dd4a 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -118,7 +118,11 @@ var editor = new website.EditorBar(); var $body = $(document.body); - editor.prependTo($body); + editor.prependTo($body).then(function () { + if (location.search.indexOf("unable_editor") >= 0) { + editor.edit(); + } + }); $body.css('padding-top', '50px'); // Not working properly: editor.$el.outerHeight()); }; /* ----- TOP EDITOR BAR FOR ADMIN ---- */ @@ -240,7 +244,7 @@ defs.push(def); }); return $.when.apply(null, defs).then(function () { - window.location.reload(); + window.location.href = window.location.href.replace(/unable_editor(=[^&]*)?/, ''); }); }, saveElement: function ($el) { @@ -263,7 +267,7 @@ }); }, cancel: function () { - window.location.reload(); + window.location.href = window.location.href.replace(/unable_editor(=[^&]*)?/, ''); }, }); -- cgit v1.2.3 From 38387410701041f8221066b93ce5093ea45b37a5 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 11 Sep 2013 13:59:37 +0200 Subject: [ADD] undo button to RTE toolbar bzr revid: xmo@openerp.com-20130911115937-ifl5bg2n1rmr7i1n --- addons/website/static/src/js/website.editor.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 098a3927e10..4d6ec2520fd 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -331,8 +331,11 @@ extraPlugins: 'sharedspace,customdialogs,tablebutton', // Place toolbar in controlled location sharedSpaces: { top: 'oe_rte_toolbar' }, - toolbar: [ - {name: 'basicstyles', items: [ + toolbar: [{ + name: 'clipboard', items: [ + "Undo" + ]},{ + name: 'basicstyles', items: [ "Bold", "Italic", "Underline", "Strike", "Subscript", "Superscript", "TextColor", "BGColor", "RemoveFormat" ]},{ -- cgit v1.2.3 From 3f4d64b1f0507b8a13e712d48e54213de77a9002 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 11 Sep 2013 18:18:54 +0200 Subject: [IMP] Use context in website's js rpc calls bzr revid: fme@openerp.com-20130911161854-zhm53dugiisychfb --- addons/website/static/src/js/website.editor.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 4d6ec2520fd..58d25143b5c 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -264,7 +264,7 @@ return openerp.jsonRpc('/web/dataset/call', 'call', { model: 'ir.ui.view', method: 'save', - args: [data.oeModel, data.oeId, data.oeField, html, xpath] + args: [data.oeModel, data.oeId, data.oeField, html, xpath, website.get_context()] }); }, cancel: function () { @@ -549,7 +549,9 @@ model: 'website', method: 'list_pages', args: [], - kwargs: {} + kwargs: { + context: website.get_context() + }, }); }, fill_pages: function (results) { @@ -653,6 +655,7 @@ fields: ['name'], domain: [['res_model', '=', 'ir.ui.view']], order: 'name', + context: website.get_context(), } }); }, -- cgit v1.2.3 From 62fff458c57c85cf701d83840f8b85d13e33788c Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 12 Sep 2013 11:15:36 +0200 Subject: [IMP] tabify link dialog for simpler layout bzr revid: xmo@openerp.com-20130912091536-mx8dre2qyiz00h36 --- addons/website/static/src/js/website.editor.js | 69 +++++++++----------------- 1 file changed, 24 insertions(+), 45 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 58d25143b5c..a4160e1fffe 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -399,15 +399,11 @@ website.editor.LinkDialog = website.editor.Dialog.extend({ template: 'website.editor.dialog.link', events: _.extend({}, website.editor.Dialog.prototype.events, { - 'change .url-source': function (e) { this.changed($(e.target)); }, - 'click div.existing a': 'select_page', }), init: function (editor) { this._super(editor); // url -> name mapping for existing pages this.pages = Object.create(null); - // name -> url mapping for the same - this.pages_by_name = Object.create(null); }, start: function () { var element; @@ -466,24 +462,24 @@ }, save: function () { var self = this, _super = this._super.bind(this); - var $e = this.$('.url-source').filter(function () { return !!this.value; }); + var $active_tab = this.$('.tab-pane.active'); + + var $e = $active_tab.find('.url-source'); var val = $e.val(), done = $.when(); - if ($e.hasClass('email-address')) { + if ($active_tab.is('#link-email')) { this.make_link('mailto:' + val, false, val); - } else if ($e.hasClass('pages')) { - // ``val`` is the *name* of the page - var url = this.pages_by_name[val]; - if (!url) { - // Create the page, get the URL back - done = $.get(_.str.sprintf( - '/pagenew/%s?noredirect', encodeURIComponent(val))) - .then(function (response) { - url = response; - }); - } + } else if ($active_tab.is('#link-existing')) { + self.make_link(val, false, this.pages[val]); + } else if ($active_tab.is('#link-new')) { + // Create the page, get the URL back + done = $.get(_.str.sprintf( + '/pagenew/%s?noredirect', encodeURIComponent(val))) + .then(function (response) { + val = response; + }); done.then(function () { - self.make_link(url, false, val); + self.make_link(val, false); }); } else { this.make_link(val, this.$('input.window-new').prop('checked')); @@ -497,36 +493,19 @@ var match, $control; if (match = /(mailto):(.+)/.exec(href)) { - $control = this.$('input.email-address').val(match[2]); + $control = this.$('#link-email input').val(match[2]); } else if(href in this.pages) { - $control = this.$('input.pages').val(this.pages[href]); - } - if (!$control) { - $control = this.$('input.url').val(href); + $control = this.$('#link-existing select').val(href); + } else { + $control = this.$('#link-external input:first').val(href); } - this.changed($control); + var tab_name = $control.closest('.tab-pane').attr('id'); + this.$('.nav a[href="#' + tab_name + '"]').tab('show'); this.$('input.window-new').prop( 'checked', this.element.getAttribute('target') === '_blank'); }, - changed: function ($e) { - $e.closest('li.list-group-item').addClass('active') - .siblings().removeClass('active'); - this.$('.url-source').not($e).val(''); - }, - /** - * Selected an existing page in dropdown - */ - select_page: function (e) { - e.preventDefault(); - e.stopPropagation(); - var $target = $(e.target); - this.$('input.pages').val($target.text()).change(); - // No #dropdown('close'), and using #dropdown('toggle') sur - // #closest('.dropdown') makes the dropdown not work correctly - $target.closest('.open').removeClass('open'); - }, /** * CKEDITOR.plugins.link.getSelectedLink ignores the editor's root, * if the editor is set directly on a link it will thus not work. @@ -556,12 +535,12 @@ }, fill_pages: function (results) { var self = this; - var $pages = this.$('div.existing ul').empty(); + var pages = this.$('#link-existing-select')[0]; _(results).each(function (result) { self.pages[result.url] = result.name; - self.pages_by_name[result.name] = result.url; - var $link = $('').attr('href', result.url).text(result.name); - $('
  • ').append($link).appendTo($pages); + + pages.options[pages.options.length] = + new Option(result.name, result.url); }); }, }); -- cgit v1.2.3 From d124389fa314e57cb27d27ed4fe242322c597c6f Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 12 Sep 2013 12:37:52 +0200 Subject: [IMP] tabified image picker dialog bzr revid: xmo@openerp.com-20130912103752-sg9jmba0b061f7x9 --- addons/website/static/src/js/website.editor.js | 1 - 1 file changed, 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index a4160e1fffe..c3880385f09 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -547,7 +547,6 @@ website.editor.ImageDialog = website.editor.Dialog.extend({ template: 'website.editor.dialog.image', events: _.extend({}, website.editor.Dialog.prototype.events, { - 'change .url-source': function (e) { this.changed($(e.target)); }, 'click button.filepicker': function () { this.$('input[type=file]').click(); }, -- cgit v1.2.3 From 75977b4e43026d21ce691f30c0df1043485d83fe Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 12 Sep 2013 13:29:05 +0200 Subject: [ADD] selection of image style in dialog bzr revid: xmo@openerp.com-20130912112905-6skmq1umsyzcvthz --- addons/website/static/src/js/website.editor.js | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index c3880385f09..4bc6d290510 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -552,14 +552,26 @@ }, 'change input[type=file]': 'file_selection', 'change input.url': 'preview_image', + 'change select.image-style': 'preview_image', 'click .existing-attachments a': 'select_existing', }), start: function () { var selection = this.editor.getSelection(); var el = selection && selection.getSelectedElement(); this.element = null; + + var $select = this.$('.image-style'); + var $options = $select.children(); + this.image_styles = $options.map(function () { return this.value; }).get(); + if (el && el.is('img')) { this.element = el; + _(this.image_styles).each(function (style) { + if (el.hasClass(style)) { + $select.val(style); + } + }); + // set_image should follow setup of image style this.set_image(el.getAttribute('src')); } @@ -569,6 +581,7 @@ }, save: function () { var url = this.$('input.url').val(); + var style = this.$('.image-style').val(); var element, editor = this.editor; if (!(element = this.element)) { element = editor.document.createElement('img'); @@ -582,7 +595,10 @@ }, 0); } element.setAttribute('src', url); - this._super(); + $(element.$).removeClass(this.image_styles.join(' ')); + if (style) { element.addClass(style); } + + return this._super(); }, /** @@ -620,7 +636,10 @@ var image = this.$('input.url').val(); if (!image) { return; } - this.$('img.image-preview').attr('src', image); + this.$('img.image-preview') + .attr('src', image) + .removeClass(this.image_styles.join(' ')) + .addClass(this.$('select.image-style').val()); }, fetch_existing: function () { -- cgit v1.2.3 From 9b6760d1f6da37c8dbb71f145f417afd24ce0076 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Thu, 12 Sep 2013 13:51:30 +0200 Subject: [IMP] snippet colmd: resizing and add col inside a row bzr revid: chm@openerp.com-20130912115130-zvqo8nez77919eno --- addons/website/static/src/js/website.editor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 4bc6d290510..b323d4845a0 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -245,7 +245,7 @@ defs.push(def); }); return $.when.apply(null, defs).then(function () { - window.location.href = window.location.href.replace(/unable_editor(=[^&]*)?/, ''); + window.location.href = window.location.href.replace(/unable_editor(=[^&]*)?|#.*/g, ''); }); }, saveElement: function ($el) { @@ -268,7 +268,7 @@ }); }, cancel: function () { - window.location.href = window.location.href.replace(/unable_editor(=[^&]*)?/, ''); + window.location.href = window.location.href.replace(/unable_editor(=[^&]*)?|#.*/g, ''); }, }); -- cgit v1.2.3 From 451360357331a4c30e2a5843a0915ee2e93b9dc4 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 12 Sep 2013 17:49:57 +0200 Subject: [FIX] force ckeditor lang to en and replace en-gb localization file with en avoids automatic locale picking selecting something different than the one locale file currently provided and blowing up, preventing edition from working bzr revid: xmo@openerp.com-20130912154957-yod17u9xvw3r966i --- addons/website/static/src/js/website.editor.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index ebcfb98635d..ae66130f921 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -331,6 +331,8 @@ 'tab', 'table', 'templates', 'toolbar', 'undo', 'wysiwygarea' ]; return { + // FIXME + language: 'en', // Disable auto-generated titles // FIXME: accessibility, need to generate user-sensible title, used for @title and @aria-label title: false, -- cgit v1.2.3 From a793a8ff16cec0466a073e9cd9cf40e8fd8116ad Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 13 Sep 2013 10:40:13 +0200 Subject: [REV] tabification of link and image dialogs bzr revid: xmo@openerp.com-20130913084013-19zu9k9voxplwwhp --- addons/website/static/src/js/website.editor.js | 93 +++++++++++++------------- 1 file changed, 48 insertions(+), 45 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index b323d4845a0..0d6e7e7d843 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -399,11 +399,15 @@ website.editor.LinkDialog = website.editor.Dialog.extend({ template: 'website.editor.dialog.link', events: _.extend({}, website.editor.Dialog.prototype.events, { + 'change .url-source': function (e) { this.changed($(e.target)); }, + 'click div.existing a': 'select_page', }), init: function (editor) { this._super(editor); // url -> name mapping for existing pages this.pages = Object.create(null); + // name -> url mapping for the same + this.pages_by_name = Object.create(null); }, start: function () { var element; @@ -462,24 +466,24 @@ }, save: function () { var self = this, _super = this._super.bind(this); - var $active_tab = this.$('.tab-pane.active'); - - var $e = $active_tab.find('.url-source'); + var $e = this.$('.url-source').filter(function () { return !!this.value; }); var val = $e.val(), done = $.when(); - if ($active_tab.is('#link-email')) { + if ($e.hasClass('email-address')) { this.make_link('mailto:' + val, false, val); - } else if ($active_tab.is('#link-existing')) { - self.make_link(val, false, this.pages[val]); - } else if ($active_tab.is('#link-new')) { - // Create the page, get the URL back - done = $.get(_.str.sprintf( - '/pagenew/%s?noredirect', encodeURIComponent(val))) - .then(function (response) { - val = response; - }); + } else if ($e.hasClass('pages')) { + // ``val`` is the *name* of the page + var url = this.pages_by_name[val]; + if (!url) { + // Create the page, get the URL back + done = $.get(_.str.sprintf( + '/pagenew/%s?noredirect', encodeURIComponent(val))) + .then(function (response) { + url = response; + }); + } done.then(function () { - self.make_link(val, false); + self.make_link(url, false, val); }); } else { this.make_link(val, this.$('input.window-new').prop('checked')); @@ -493,19 +497,36 @@ var match, $control; if (match = /(mailto):(.+)/.exec(href)) { - $control = this.$('#link-email input').val(match[2]); + $control = this.$('input.email-address').val(match[2]); } else if(href in this.pages) { - $control = this.$('#link-existing select').val(href); - } else { - $control = this.$('#link-external input:first').val(href); + $control = this.$('input.pages').val(this.pages[href]); + } + if (!$control) { + $control = this.$('input.url').val(href); } - var tab_name = $control.closest('.tab-pane').attr('id'); - this.$('.nav a[href="#' + tab_name + '"]').tab('show'); + this.changed($control); this.$('input.window-new').prop( 'checked', this.element.getAttribute('target') === '_blank'); }, + changed: function ($e) { + $e.closest('li.list-group-item').addClass('active') + .siblings().removeClass('active'); + this.$('.url-source').not($e).val(''); + }, + /** + * Selected an existing page in dropdown + */ + select_page: function (e) { + e.preventDefault(); + e.stopPropagation(); + var $target = $(e.target); + this.$('input.pages').val($target.text()).change(); + // No #dropdown('close'), and using #dropdown('toggle') sur + // #closest('.dropdown') makes the dropdown not work correctly + $target.closest('.open').removeClass('open'); + }, /** * CKEDITOR.plugins.link.getSelectedLink ignores the editor's root, * if the editor is set directly on a link it will thus not work. @@ -535,43 +556,32 @@ }, fill_pages: function (results) { var self = this; - var pages = this.$('#link-existing-select')[0]; + var $pages = this.$('div.existing ul').empty(); _(results).each(function (result) { self.pages[result.url] = result.name; - - pages.options[pages.options.length] = - new Option(result.name, result.url); + self.pages_by_name[result.name] = result.url; + var $link = $('').attr('href', result.url).text(result.name); + $('
  • ').append($link).appendTo($pages); }); }, }); website.editor.ImageDialog = website.editor.Dialog.extend({ template: 'website.editor.dialog.image', events: _.extend({}, website.editor.Dialog.prototype.events, { + 'change .url-source': function (e) { this.changed($(e.target)); }, 'click button.filepicker': function () { this.$('input[type=file]').click(); }, 'change input[type=file]': 'file_selection', 'change input.url': 'preview_image', - 'change select.image-style': 'preview_image', 'click .existing-attachments a': 'select_existing', }), start: function () { var selection = this.editor.getSelection(); var el = selection && selection.getSelectedElement(); this.element = null; - - var $select = this.$('.image-style'); - var $options = $select.children(); - this.image_styles = $options.map(function () { return this.value; }).get(); - if (el && el.is('img')) { this.element = el; - _(this.image_styles).each(function (style) { - if (el.hasClass(style)) { - $select.val(style); - } - }); - // set_image should follow setup of image style this.set_image(el.getAttribute('src')); } @@ -581,7 +591,6 @@ }, save: function () { var url = this.$('input.url').val(); - var style = this.$('.image-style').val(); var element, editor = this.editor; if (!(element = this.element)) { element = editor.document.createElement('img'); @@ -595,10 +604,7 @@ }, 0); } element.setAttribute('src', url); - $(element.$).removeClass(this.image_styles.join(' ')); - if (style) { element.addClass(style); } - - return this._super(); + this._super(); }, /** @@ -636,10 +642,7 @@ var image = this.$('input.url').val(); if (!image) { return; } - this.$('img.image-preview') - .attr('src', image) - .removeClass(this.image_styles.join(' ')) - .addClass(this.$('select.image-style').val()); + this.$('img.image-preview').attr('src', image); }, fetch_existing: function () { -- cgit v1.2.3 From c52335de5a7c55cfe542105219f84ecf9ede0a41 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 13 Sep 2013 11:15:32 +0200 Subject: [IMP] split new page and existing page sections in link dialog + look fixes * select sections on click within section * validation in case no value provided for selected section on save bzr revid: xmo@openerp.com-20130913091532-i037z59odb4j52b7 --- addons/website/static/src/js/website.editor.js | 67 ++++++++++++-------------- 1 file changed, 31 insertions(+), 36 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 0d6e7e7d843..a6d29b62c63 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -400,14 +400,23 @@ template: 'website.editor.dialog.link', events: _.extend({}, website.editor.Dialog.prototype.events, { 'change .url-source': function (e) { this.changed($(e.target)); }, - 'click div.existing a': 'select_page', + 'mousedown': function (e) { + var $target = $(e.target).closest('.list-group-item'); + if (!$target.length || $target.hasClass('active')) { + // clicked outside groups, or clicked in active groups + return; + } + + $target + .addClass('active') + .siblings().removeClass('active') + .addBack().removeClass('has-error'); + } }), init: function (editor) { this._super(editor); // url -> name mapping for existing pages this.pages = Object.create(null); - // name -> url mapping for the same - this.pages_by_name = Object.create(null); }, start: function () { var element; @@ -466,25 +475,25 @@ }, save: function () { var self = this, _super = this._super.bind(this); - var $e = this.$('.url-source').filter(function () { return !!this.value; }); + var $e = this.$('.list-group-item.active .url-source'); + var val = $e.val(); + if (!val) { + $e.closest('.form-group').addClass('has-error'); + return; + } - var val = $e.val(), done = $.when(); + var done = $.when(); if ($e.hasClass('email-address')) { this.make_link('mailto:' + val, false, val); + } else if ($e.hasClass('existing')) { + self.make_link(val, false, this.pages[val]); } else if ($e.hasClass('pages')) { - // ``val`` is the *name* of the page - var url = this.pages_by_name[val]; - if (!url) { - // Create the page, get the URL back - done = $.get(_.str.sprintf( + // Create the page, get the URL back + done = $.get(_.str.sprintf( '/pagenew/%s?noredirect', encodeURIComponent(val))) - .then(function (response) { - url = response; - }); - } - done.then(function () { - self.make_link(url, false, val); - }); + .then(function (response) { + self.make_link(response, false, val); + }); } else { this.make_link(val, this.$('input.window-new').prop('checked')); } @@ -499,7 +508,7 @@ if (match = /(mailto):(.+)/.exec(href)) { $control = this.$('input.email-address').val(match[2]); } else if(href in this.pages) { - $control = this.$('input.pages').val(this.pages[href]); + $control = this.$('select.existing').val(href); } if (!$control) { $control = this.$('input.url').val(href); @@ -511,22 +520,8 @@ 'checked', this.element.getAttribute('target') === '_blank'); }, changed: function ($e) { - $e.closest('li.list-group-item').addClass('active') - .siblings().removeClass('active'); this.$('.url-source').not($e).val(''); }, - /** - * Selected an existing page in dropdown - */ - select_page: function (e) { - e.preventDefault(); - e.stopPropagation(); - var $target = $(e.target); - this.$('input.pages').val($target.text()).change(); - // No #dropdown('close'), and using #dropdown('toggle') sur - // #closest('.dropdown') makes the dropdown not work correctly - $target.closest('.open').removeClass('open'); - }, /** * CKEDITOR.plugins.link.getSelectedLink ignores the editor's root, * if the editor is set directly on a link it will thus not work. @@ -556,12 +551,12 @@ }, fill_pages: function (results) { var self = this; - var $pages = this.$('div.existing ul').empty(); + var pages = this.$('select.existing')[0]; _(results).each(function (result) { self.pages[result.url] = result.name; - self.pages_by_name[result.name] = result.url; - var $link = $('').attr('href', result.url).text(result.name); - $('
  • ').append($link).appendTo($pages); + + pages.options[pages.options.length] = + new Option(result.name, result.url); }); }, }); -- cgit v1.2.3 From aaa0f7eaca49d731987288a17bd38ff38984663f Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 13 Sep 2013 11:55:32 +0200 Subject: [ADD] 'remove link' feature to link dialog, remove icon from sidebar bzr revid: xmo@openerp.com-20130913095532-s6ex6kcqzqzlm8tc --- addons/website/static/src/js/website.editor.js | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index a6d29b62c63..5a8801bba38 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -340,7 +340,7 @@ "Superscript", "TextColor", "BGColor", "RemoveFormat" ]},{ name: 'span', items: [ - "Link", "Unlink", "Blockquote", "BulletedList", + "Link", "Blockquote", "BulletedList", "NumberedList", "Indent", "Outdent" ]},{ name: 'justify', items: [ @@ -392,6 +392,9 @@ return sup; }, save: function () { + this.close(); + }, + close: function () { this.$el.modal('hide'); }, }); @@ -411,7 +414,8 @@ .addClass('active') .siblings().removeClass('active') .addBack().removeClass('has-error'); - } + }, + 'click button.remove': 'remove_link', }), init: function (editor) { this._super(editor); @@ -424,12 +428,28 @@ this.editor.getSelection().selectElement(element); } this.element = element; + if (element) { + this.add_removal_button(); + } return $.when( this.fetch_pages().done(this.proxy('fill_pages')), this._super() ).done(this.proxy('bind_data')); }, + add_removal_button: function () { + this.$('.modal-footer').prepend( + openerp.qweb.render( + 'website.editor.dialog.link.footer-button')); + }, + remove_link: function () { + var editor = this.editor; + // same issue as in make_link + setTimeout(function () { + editor.execCommand('unlink'); + }, 0); + this.close(); + }, /** * Greatly simplified version of CKEDITOR's * plugins.link.dialogs.link.onOk. -- cgit v1.2.3 From f16b61cbe61a77cf331a54ea11520322e7730739 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 13 Sep 2013 13:41:43 +0200 Subject: [ADD] separate attachment dialog selector bzr revid: xmo@openerp.com-20130913114143-v799fvf08rpiox3r --- addons/website/static/src/js/website.editor.js | 43 ++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 6 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 5a8801bba38..77bed2f9215 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -589,7 +589,7 @@ }, 'change input[type=file]': 'file_selection', 'change input.url': 'preview_image', - 'click .existing-attachments a': 'select_existing', + 'click a[href=#existing]': 'browse_existing', }), start: function () { var selection = this.editor.getSelection(); @@ -600,9 +600,7 @@ this.set_image(el.getAttribute('src')); } - return $.when( - this._super(), - this.fetch_existing().then(this.proxy('fetched_existing'))); + return this._super(); }, save: function () { var url = this.$('input.url').val(); @@ -660,6 +658,29 @@ this.$('img.image-preview').attr('src', image); }, + browse_existing: function (e) { + e.preventDefault(); + new website.editor.ExistingImageDialog(this).appendTo(document.body); + }, + }); + + website.editor.ExistingImageDialog = website.editor.Dialog.extend({ + template: 'website.editor.dialog.image.existing', + events: _.extend({}, website.editor.Dialog.prototype.events, { + 'click .existing-attachments a': 'select_existing', + }), + init: function (parent) { + this.image = null; + this.parent = parent; + this._super(parent.editor); + }, + + start: function () { + return $.when( + this._super(), + this.fetch_existing().then(this.proxy('fetched_existing'))); + }, + fetch_existing: function () { // FIXME: lazy load attachments? return openerp.jsonRpc('/web/dataset/call_kw', 'call', { @@ -681,11 +702,21 @@ .values() .value(); this.$('.existing-attachments').replaceWith( - openerp.qweb.render('website.editor.dialog.image.existing', {rows: rows})); + openerp.qweb.render( + 'website.editor.dialog.image.existing.content', {rows: rows})); }, select_existing: function (e) { e.preventDefault(); - this.set_image(e.currentTarget.getAttribute('href')); + this.$('a.thumbnail.selected').removeClass('selected'); + + $(e.currentTarget).addClass('selected'); + }, + save: function () { + var link = this.$('a.thumbnail.selected').attr('href'); + if (link) { + this.parent.set_image(link); + } + this._super(); }, }); -- cgit v1.2.3 From ba99ab56c842542fdcf86daa05c3c2e13aaf3d2f Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 13 Sep 2013 15:55:32 +0200 Subject: [FIX] force ckeditor lang to en and replace en-gb localization file with en avoids automatic locale picking selecting something different than the one locale file currently provided and blowing up, preventing edition from working bzr revid: xmo@openerp.com-20130913135532-szra08zdge1ktmc7 --- addons/website/static/src/js/website.editor.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 5a8801bba38..e9ec06859d0 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -315,6 +315,8 @@ 'magicline' ]; return { + // FIXME + language: 'en', // Disable auto-generated titles // FIXME: accessibility, need to generate user-sensible title, used for @title and @aria-label title: false, -- cgit v1.2.3 From 243a9c559b7c603ee1cffb9a186401771e35c871 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 13 Sep 2013 17:13:16 +0200 Subject: [ADD] paginated images bzr revid: xmo@openerp.com-20130913151316-rzr3rcg1w7h3gw10 --- addons/website/static/src/js/website.editor.js | 30 ++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 6c14b29e3a9..c7e5155fcc9 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -666,13 +666,25 @@ }, }); + var IMAGES_PER_ROW = 3; + var IMAGES_ROWS = 3; website.editor.ExistingImageDialog = website.editor.Dialog.extend({ template: 'website.editor.dialog.image.existing', events: _.extend({}, website.editor.Dialog.prototype.events, { 'click .existing-attachments a': 'select_existing', + 'click .pager > li': function (e) { + e.preventDefault(); + var $target = $(e.currentTarget); + if ($target.hasClass('disabled')) { + return; + } + this.page += $target.hasClass('previous') ? -1 : 1; + this.display_attachments(); + }, }), init: function (parent) { this.image = null; + this.page = 0; this.parent = parent; this._super(parent.editor); }, @@ -684,7 +696,6 @@ }, fetch_existing: function () { - // FIXME: lazy load attachments? return openerp.jsonRpc('/web/dataset/call_kw', 'call', { model: 'ir.attachment', method: 'search_read', @@ -698,14 +709,29 @@ }); }, fetched_existing: function (records) { + this.records = records; + this.display_attachments(); + }, + display_attachments: function () { + var per_screen = IMAGES_PER_ROW * IMAGES_ROWS; + + var from = this.page * per_screen; + var records = this.records; + // Create rows of 3 records var rows = _(records).chain() - .groupBy(function (_, index) { return Math.floor(index / 3); }) + .slice(from, from + per_screen) + .groupBy(function (_, index) { return Math.floor(index / IMAGES_PER_ROW); }) .values() .value(); + this.$('.existing-attachments').replaceWith( openerp.qweb.render( 'website.editor.dialog.image.existing.content', {rows: rows})); + this.$('.pager') + .find('li.previous').toggleClass('disabled', (from === 0)).end() + .find('li.next').toggleClass('disabled', (from + per_screen >= records.length)); + }, select_existing: function (e) { e.preventDefault(); -- cgit v1.2.3 From 972f5029428a9b7fe023ef0ed08d462589e5594c Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 13 Sep 2013 17:23:08 +0200 Subject: [ADD] reintroduce image style selector bzr revid: xmo@openerp.com-20130913152308-j250t5ns7iaz6w2n --- addons/website/static/src/js/website.editor.js | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index c7e5155fcc9..1d63fc0c3bb 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -592,13 +592,25 @@ 'change input[type=file]': 'file_selection', 'change input.url': 'preview_image', 'click a[href=#existing]': 'browse_existing', + 'change select.image-style': 'preview_image', }), start: function () { var selection = this.editor.getSelection(); var el = selection && selection.getSelectedElement(); this.element = null; + + var $select = this.$('.image-style'); + var $options = $select.children(); + this.image_styles = $options.map(function () { return this.value; }).get(); + if (el && el.is('img')) { this.element = el; + _(this.image_styles).each(function (style) { + if (el.hasClass(style)) { + $select.val(style); + } + }); + // set_image must follow setup of image style this.set_image(el.getAttribute('src')); } @@ -606,6 +618,7 @@ }, save: function () { var url = this.$('input.url').val(); + var style = this.$('.image-style').val(); var element, editor = this.editor; if (!(element = this.element)) { element = editor.document.createElement('img'); @@ -619,7 +632,10 @@ }, 0); } element.setAttribute('src', url); - this._super(); + $(element.$).removeClass(this.image_styles.join(' ')); + if (style) { element.addClass(style); } + + return this._super(); }, /** @@ -657,7 +673,10 @@ var image = this.$('input.url').val(); if (!image) { return; } - this.$('img.image-preview').attr('src', image); + this.$('img.image-preview') + .attr('src', image) + .removeClass(this.image_styles.join(' ')) + .addClass(this.$('select.image-style').val()); }, browse_existing: function (e) { -- cgit v1.2.3 From 0c145b7577482633f67b21cb89625faea49e1f74 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 16 Sep 2013 11:03:53 +0200 Subject: [FIX] completely remove usages of link and image plugin and import missing pieces CKEDITOR plugins are not loaded in dependency order (see previous commits), and in the end the vast majority of the (used subpart of) link and image plugins were reimplemented to handle new dialogs. Bite the bullet, disable link and image and implement/import missing parts (link removal, doubleclick hooks & toolbar button definition). bzr revid: xmo@openerp.com-20130916090353-933av2nsrygxz64y --- addons/website/static/src/js/website.editor.js | 64 +++++++++++++++++--------- 1 file changed, 43 insertions(+), 21 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index a9d0061277c..deea0b52835 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -33,18 +33,20 @@ } website.init_editor = function () { CKEDITOR.plugins.add('customdialogs', { - requires: 'link,image', +// requires: 'link,image', init: function (editor) { editor.on('doubleclick', function (evt) { - if (evt.data.dialog === 'link') { - delete evt.data.dialog; - link_dialog(editor); - } else if(evt.data.dialog === 'image') { - delete evt.data.dialog; + var element = evt.data.element; + if (element.is('img') && !element.data( 'cke-realelement' ) && !element.isReadOnly()) { image_dialog(editor); + return; } - // priority should be smaller than dialog (999) but bigger - // than link or image (default=10) + + element = get_selected_link(editor) || evt.data.element; + if (element.isReadOnly() || !element.is('a')) { return; } + + editor.getSelection().selectElement(element); + link_dialog(editor); }, null, null, 500); //noinspection JSValidateTypes @@ -65,6 +67,19 @@ canUndo: false, editorFocus: true, }); + + editor.ui.addButton('Link', { + label: 'Link', + command: 'link', + toolbar: 'links,10', + icon: '/website/static/lib/ckeditor/plugins/link/icons/link.png', + }); + editor.ui.addButton('Image', { + label: 'Image', + command: 'image', + toolbar: 'insert,10', + icon: '/website/static/lib/ckeditor/plugins/image/icons/image.png', + }); } }); CKEDITOR.plugins.add( 'tablebutton', { @@ -325,7 +340,7 @@ 'clipboard', 'colorbutton', 'colordialog', 'dialogadvtab', 'elementspath', 'enterkey', 'entities', 'filebrowser', 'find', 'floatingspace','format', 'htmlwriter', 'iframe', - 'image', 'indentblock', 'indentlist', 'justify', 'link', + 'indentblock', 'indentlist', 'justify', 'list', 'pastefromword', 'pastetext', 'preview', 'removeformat', 'resize', 'save', 'selectall', 'stylescombo', 'tab', 'table', 'templates', 'toolbar', 'undo', 'wysiwygarea' @@ -465,7 +480,11 @@ var editor = this.editor; // same issue as in make_link setTimeout(function () { - editor.execCommand('unlink'); + editor.removeStyle(new CKEDITOR.style({ + element: 'a', + type: CKEDITOR.STYLE_INLINE, + alwaysRemoveElement: true, + })); }, 0); this.close(); }, @@ -568,17 +587,7 @@ * if the editor is set directly on a link it will thus not work. */ get_selected_link: function () { - var sel = this.editor.getSelection(), - el = sel.getSelectedElement(); - if (el && el.is('a')) { return el; } - - var range = sel.getRanges(true)[0]; - if (!range) { return null; } - - range.shrink(CKEDITOR.SHRINK_TEXT); - return this.editor.elementPath(range.getCommonAncestor()) - .contains('a'); - + return get_selected_link(this.editor); }, fetch_pages: function () { return openerp.jsonRpc('/web/dataset/call_kw', 'call', { @@ -710,6 +719,19 @@ }, }); + function get_selected_link(editor) { + var sel = editor.getSelection(), + el = sel.getSelectedElement(); + if (el && el.is('a')) { return el; } + + var range = sel.getRanges(true)[0]; + if (!range) { return null; } + + range.shrink(CKEDITOR.SHRINK_TEXT); + return editor.elementPath(range.getCommonAncestor()) + .contains('a'); + } + var Observer = window.MutationObserver || window.WebkitMutationObserver || window.JsMutationObserver; var OBSERVER_CONFIG = { -- cgit v1.2.3 From f3eec24a6fbe3f4cd74e90cbe59325e6afe5d352 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 16 Sep 2013 11:07:50 +0200 Subject: [ADD] link keyboard shortcut bzr revid: xmo@openerp.com-20130916090750-xs8dcrm3cp91fo8r --- addons/website/static/src/js/website.editor.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index deea0b52835..537c105861e 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -80,6 +80,8 @@ toolbar: 'insert,10', icon: '/website/static/lib/ckeditor/plugins/image/icons/image.png', }); + + editor.setKeystroke(CKEDITOR.CTRL + 76 /*L*/, 'link'); } }); CKEDITOR.plugins.add( 'tablebutton', { -- cgit v1.2.3 From 24a63ccea7bb9f2cf65afffcccd7c41fe3b91cc9 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Mon, 16 Sep 2013 16:42:35 +0200 Subject: [IMP] website snippet: add button 'insert block' on top bar bzr revid: chm@openerp.com-20130916144235-mxm63fikqlf0jv8s --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 1d63fc0c3bb..241280029a3 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -187,7 +187,7 @@ return $.when( this._super.apply(this, arguments), - this.rte.prependTo(this.$('#website-top-edit .nav.pull-right')) + this.rte.appendTo(this.$('#website-top-edit .nav.pull-right')) ); }, edit: function () { -- cgit v1.2.3 From 757a2dbc4e13a35302e328c559215b3c66a6d3bd Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 17 Sep 2013 10:57:53 +0200 Subject: [IMP] single whole-page editor, reinstate ability to save only an embedded field (not part of a view) bzr revid: xmo@openerp.com-20130917085753-aa32xxezhtrfaffj --- addons/website/static/src/js/website.editor.js | 89 +++++++++++++++++--------- 1 file changed, 60 insertions(+), 29 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 537c105861e..a9e279593dc 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -242,14 +242,7 @@ this.$('#website-top-edit').show(); $('.css_non_editable_mode_hidden').removeClass("css_non_editable_mode_hidden"); - var $editables = $('[data-oe-model][data-oe-xpath]') - // FIXME: propagation should make "meta" blocks non-editable in the first place... - .not('link, script') - .not('[data-oe-type]') - .not('.oe_snippet_editor') - .prop('contentEditable', true) - .addClass('oe_editable'); - this.rte.start_edition($editables); + this.rte.start_edition(); }, rte_changed: function () { this.$buttons.save.prop('disabled', false); @@ -258,20 +251,26 @@ var self = this; observer.disconnect(); - var defs = _(CKEDITOR.instances).chain() - .filter(function (editor) { return editor.element.hasClass('oe_dirty'); }) - .map(function (editor) { - var $el = $(editor.element.$); + var editor = this.rte.editor; + var root = editor.element.$; + editor.destroy(); + // FIXME: select editables then filter by dirty? + var defs = this.rte.fetch_editables(root) + .removeClass('oe_editable cke_focus') + .removeAttr('contentEditable') + .filter('.oe_dirty') + .map(function () { + var $el = $(this); // TODO: Add a queue with concurrency limit in webclient // https://github.com/medikoo/deferred/blob/master/lib/ext/function/gate.js return self.saving_mutex.exec(function () { - return self.saveEditor(editor) + return self.saveElement($el) .fail(function () { var data = $el.data(); console.error(_.str.sprintf('Could not save %s(%d).%s', data.oeModel, data.oeId, data.oeField)); }); }); - }).value(); + }).get(); return $.when.apply(null, defs).then(function () { window.location.href = window.location.href.replace(/unable_editor(=[^&]*)?|#.*/g, ''); }); @@ -279,18 +278,15 @@ /** * Saves an RTE content, which always corresponds to a view section (?). */ - saveEditor: function (editor) { - var element = editor.element; - editor.destroy(); - element.removeClass('cke_focus') - .removeClass('oe_dirty') - .removeClass('oe_editable') - .removeAttribute('contentEditable'); - var data = element.getOuterHtml(); + saveElement: function ($el) { + $el.removeClass('oe_dirty'); + var markup = $el.prop('outerHTML'); return openerp.jsonRpc('/web/dataset/call', 'call', { model: 'ir.ui.view', method: 'save', - args: [element.data('oe-id'), data, element.data('oe-xpath'), website.get_context()], + args: [$el.data('oe-id'), markup, + $el.data('oe-xpath') || null, + website.get_context()], }); }, cancel: function () { @@ -313,22 +309,57 @@ start_edition: function ($elements) { var self = this; - $elements + // create a single editor for the whole page + // FIXME: is not the whole page, ckeditor can't handle body + var root = document.getElementById('wrap'); + root.setAttribute('data-cke-editable', 'true'); + this.editor = CKEDITOR.inline(root, self._config()); + this.editor.on('instanceReady', function () { + // ckeditor set root to editable, disable it (only inner + // sections are editable) + // FIXME: are there cases where the whole editor is editable? + root.contentEditable = false; + + self.setup_editables(root); + }); + }, + + setup_editables: function (root) { + // selection of editable sub-items was previously in + // EditorBar#edit, but for some unknown reason the elements were + // apparently removed and recreated (?) at editor initalization, + // and observer setup was lost. + var self = this; + // setup dirty-marking for each editable element + this.fetch_editables(root) + .prop('contentEditable', true) + .addClass('oe_editable') .each(function () { var node = this; + observer.observe(node, OBSERVER_CONFIG); var $node = $(node); - var editor = CKEDITOR.inline(this, self._config()); - editor.on('instanceReady', function () { - self.trigger('instanceReady'); - observer.observe(node, OBSERVER_CONFIG); - }); $node.one('content_changed', function () { + console.log("!", $node) $node.addClass('oe_dirty'); self.trigger('change'); }); }); }, + fetch_editables: function (root) { + return $(root).find('[data-oe-model]') + // FIXME: propagation should make "meta" blocks non-editable in the first place... + .not('link, script') + .not('.oe_snippet_editor') + .filter(function () { + var $this = $(this); + // keep view sections and fields which are *not* in + // view sections for toplevel editables + return $this.data('oe-model') === 'ir.ui.view' + || !$this.closest('[data-oe-model = "ir.ui.view"]').length; + }); + }, + _current_editor: function () { return CKEDITOR.currentInstance; }, -- cgit v1.2.3 From e5c11a3aaa4d8dda76185fa8da0134030ac02637 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 17 Sep 2013 10:59:23 +0200 Subject: [FIX] forgot a console call bzr revid: xmo@openerp.com-20130917085923-0gsp3dfsqmocgimg --- addons/website/static/src/js/website.editor.js | 1 - 1 file changed, 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index a9e279593dc..84e2d1fa017 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -339,7 +339,6 @@ observer.observe(node, OBSERVER_CONFIG); var $node = $(node); $node.one('content_changed', function () { - console.log("!", $node) $node.addClass('oe_dirty'); self.trigger('change'); }); -- cgit v1.2.3 From e0662b11d094514711ef6ae4e7420f15d0cbb03d Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 18 Sep 2013 16:50:28 +0200 Subject: [FIX] wrap the wrapper in order to allow RTE on all of the page (except the toolbar) CKEditor does not work directly on body, and it's a bad idea anyway (editing the edition toolbar won't end well). A big wrapper around all of the page's content can be used as RTE hook to give access to the body as well as the header and footers. bzr revid: xmo@openerp.com-20130918145028-6ppi9sro2un0quh5 --- addons/website/static/src/js/website.editor.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 84e2d1fa017..512c374e8d4 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -310,8 +310,7 @@ start_edition: function ($elements) { var self = this; // create a single editor for the whole page - // FIXME: is not the whole page, ckeditor can't handle body - var root = document.getElementById('wrap'); + var root = document.getElementById('wrapwrap'); root.setAttribute('data-cke-editable', 'true'); this.editor = CKEDITOR.inline(root, self._config()); this.editor.on('instanceReady', function () { -- cgit v1.2.3 From 823cc5549d1333da16749d5957d20e8e1ceb76e2 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 18 Sep 2013 17:48:31 +0200 Subject: [IMP] website snippets: horizontal scolling bzr revid: chm@openerp.com-20130918154831-qiyin8xx07x20qj2 --- addons/website/static/src/js/website.editor.js | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 241280029a3..df7245a024f 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -184,6 +184,13 @@ this.rte = new website.RTE(this); this.rte.on('change', this, this.proxy('rte_changed')); + var instanceReady = false; + this.rte.on('instanceReady', this, function () { + clearTimeout(instanceReady); + instanceReady = setTimeout(function () { + self.trigger('rte:ready'); + }, 0); + }); return $.when( this._super.apply(this, arguments), -- cgit v1.2.3 From fbc2f1a3233e8156293938338130c751c4b77799 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 19 Sep 2013 17:20:39 +0200 Subject: [IMP] don't edit links in a non-editable section of the page if a link is outside a view section or is the root of the view section, its href can not be edited (either because it's completely non-editable or because it probably had a dynamically generated href via t-att*) bzr revid: xmo@openerp.com-20130919152039-5hpe8qdrvhhen5aw --- addons/website/static/src/js/website.editor.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 512c374e8d4..27e3bef89e0 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -759,8 +759,14 @@ if (!range) { return null; } range.shrink(CKEDITOR.SHRINK_TEXT); - return editor.elementPath(range.getCommonAncestor()) - .contains('a'); + var commonAncestor = range.getCommonAncestor(); + var viewRoot = editor.elementPath(commonAncestor).contains(function (element) { + return element.data('oe-model') === 'ir.ui.view' + }); + if (!viewRoot) { return null; } + // if viewRoot is the first link, don't edit it. + return new CKEDITOR.dom.elementPath(commonAncestor, viewRoot) + .contains('a', true); } -- cgit v1.2.3 From 744c0de0c7db8987495e10f091422be3efb00910 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 19 Sep 2013 17:23:18 +0200 Subject: [IMP] just in case, forbid the edition of images as root of view sections bzr revid: xmo@openerp.com-20130919152318-jq6ef1jhfs05b0ys --- addons/website/static/src/js/website.editor.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 27e3bef89e0..0f9715e41bb 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -37,7 +37,10 @@ init: function (editor) { editor.on('doubleclick', function (evt) { var element = evt.data.element; - if (element.is('img') && !element.data( 'cke-realelement' ) && !element.isReadOnly()) { + if (element.is('img') + && !element.data('cke-realelement') + && !element.isReadOnly() + && (element.data('oe-model') !== 'ir.ui.view')) { image_dialog(editor); return; } -- cgit v1.2.3 From 6b7e32155d948b6b01911514f996a3e098fd7364 Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Thu, 19 Sep 2013 18:48:55 +0200 Subject: [IMP] Image selector bzr revid: fp@tinyerp.com-20130919164855-0xmiofe2a2mkqmq2 --- addons/website/static/src/js/website.editor.js | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index df7245a024f..26c7de8d4e6 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -692,12 +692,12 @@ }, }); - var IMAGES_PER_ROW = 3; + var IMAGES_PER_ROW = 4; var IMAGES_ROWS = 3; website.editor.ExistingImageDialog = website.editor.Dialog.extend({ template: 'website.editor.dialog.image.existing', events: _.extend({}, website.editor.Dialog.prototype.events, { - 'click .existing-attachments a': 'select_existing', + 'click .existing-attachments img': 'select_existing', 'click .pager > li': function (e) { e.preventDefault(); var $target = $(e.currentTarget); @@ -760,17 +760,11 @@ }, select_existing: function (e) { - e.preventDefault(); - this.$('a.thumbnail.selected').removeClass('selected'); - - $(e.currentTarget).addClass('selected'); - }, - save: function () { - var link = this.$('a.thumbnail.selected').attr('href'); + var link = $(e.currentTarget).attr('src'); if (link) { this.parent.set_image(link); } - this._super(); + this.close() }, }); -- cgit v1.2.3 From 21b7b689c8d999b003250d805fb88256d1b1934a Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Thu, 19 Sep 2013 18:55:25 +0200 Subject: [IMP] more images on selector bzr revid: fp@tinyerp.com-20130919165525-3gaeb5s3iczfsvg6 --- addons/website/static/src/js/website.editor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 26c7de8d4e6..a28a3dc37d9 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -692,8 +692,8 @@ }, }); - var IMAGES_PER_ROW = 4; - var IMAGES_ROWS = 3; + var IMAGES_PER_ROW = 6; + var IMAGES_ROWS = 4; website.editor.ExistingImageDialog = website.editor.Dialog.extend({ template: 'website.editor.dialog.image.existing', events: _.extend({}, website.editor.Dialog.prototype.events, { -- cgit v1.2.3 From a71804b74d661d4d5b2a74c8dce2585aa4207fb7 Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Fri, 20 Sep 2013 07:10:29 +0200 Subject: [IMP] Attachments with default images bzr revid: fp@openerp.com-20130920051029-0t61gy4zz68dfckl --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index a28a3dc37d9..c2495e30d9c 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -727,7 +727,7 @@ method: 'search_read', args: [], kwargs: { - fields: ['name'], + fields: ['name', 'website_url'], domain: [['res_model', '=', 'ir.ui.view']], order: 'name', context: website.get_context(), -- cgit v1.2.3 From 2e4a052ac1ad6f4859254182b8224e3b0be1d6ed Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 20 Sep 2013 11:42:07 +0200 Subject: [FIX] link dialog popping up when double-clicking on field links not inside views bzr revid: xmo@openerp.com-20130920094207-rpt77gi0vypij1bx --- addons/website/static/src/js/website.editor.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 0f9715e41bb..bbc45d7d8bf 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -46,7 +46,11 @@ } element = get_selected_link(editor) || evt.data.element; - if (element.isReadOnly() || !element.is('a')) { return; } + if (element.isReadOnly() + || !element.is('a') + || element.data('oe-model')) { + return; + } editor.getSelection().selectElement(element); link_dialog(editor); -- cgit v1.2.3 From 999b1c6e4c72cf927efe187f738537a57ab87dbd Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 20 Sep 2013 12:36:22 +0200 Subject: [FIX] prevent dragging of images during edition bzr revid: xmo@openerp.com-20130920103622-h091gbp78fic85w0 --- addons/website/static/src/js/website.editor.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index bbc45d7d8bf..05911056d0d 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -318,7 +318,10 @@ var self = this; // create a single editor for the whole page var root = document.getElementById('wrapwrap'); - root.setAttribute('data-cke-editable', 'true'); + $(root).attr('data-cke-editable', 'true') + .on('dragstart', 'img', function (e) { + e.preventDefault(); + }); this.editor = CKEDITOR.inline(root, self._config()); this.editor.on('instanceReady', function () { // ckeditor set root to editable, disable it (only inner -- cgit v1.2.3 From 4b481b3509b8c3e71a60f87a15b3fc1b792bc5f9 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 23 Sep 2013 11:49:26 +0200 Subject: [IMP] page name validation on new page creation bzr revid: xmo@openerp.com-20130923094926-q2as7cn6etpp36la --- addons/website/static/src/js/website.editor.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 05911056d0d..ce78640a2d7 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -578,7 +578,8 @@ var self = this, _super = this._super.bind(this); var $e = this.$('.list-group-item.active .url-source'); var val = $e.val(); - if (!val) { + if (!val || !$e[0].checkValidity()) { + // FIXME: error message $e.closest('.form-group').addClass('has-error'); return; } -- cgit v1.2.3 From 3e336cda542eddea94d6ad61eb748536f17c9a5b Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 23 Sep 2013 12:02:41 +0200 Subject: [FIX] selection of default section on opening link dialog bzr revid: xmo@openerp.com-20130923100241-n42lczqdpupfiae4 --- addons/website/static/src/js/website.editor.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index ce78640a2d7..77e031d352e 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -485,10 +485,7 @@ return; } - $target - .addClass('active') - .siblings().removeClass('active') - .addBack().removeClass('has-error'); + this.changed($target.find('.url-source')); }, 'click button.remove': 'remove_link', }), @@ -623,6 +620,10 @@ }, changed: function ($e) { this.$('.url-source').not($e).val(''); + $e.closest('.list-group-item') + .addClass('active') + .siblings().removeClass('active') + .addBack().removeClass('has-error'); }, /** * CKEDITOR.plugins.link.getSelectedLink ignores the editor's root, -- cgit v1.2.3 From be4b1b9b599d2dea07f68908b56a2c84ab8e5e5f Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 23 Sep 2013 13:06:18 +0200 Subject: [FIX] matching of site page URLs With page urls not necessarily being full xmlids, match to result of list_pages needs to take that in account to correctly infer a url is a site page's. bzr revid: xmo@openerp.com-20130923110618-ckicw4a5bpvatzie --- addons/website/static/src/js/website.editor.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 77e031d352e..16443ac36c4 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -604,10 +604,15 @@ if (!href) { return; } var match, $control; - if (match = /(mailto):(.+)/.exec(href)) { - $control = this.$('input.email-address').val(match[2]); - } else if(href in this.pages) { + if (match = /mailto:(.+)/.exec(href)) { + $control = this.$('input.email-address').val(match[1]); + } else if (href in this.pages) { $control = this.$('select.existing').val(href); + } else if (match = /\/page\/(.+)/.exec(href)) { + var actual_href = '/page/website.' + match[1]; + if (actual_href in this.pages) { + $control = this.$('select.existing').val(actual_href); + } } if (!$control) { $control = this.$('input.url').val(href); -- cgit v1.2.3 From 59b46346b1e3d887cdccf50d183cea72541abef0 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 23 Sep 2013 15:03:21 +0200 Subject: [FIX] crappy snippets initialization signal bzr revid: xmo@openerp.com-20130923130321-lpbxy7qckcu0svrp --- addons/website/static/src/js/website.editor.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index b2a93b9cfd6..0c32cf40fb2 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -236,12 +236,8 @@ this.rte = new website.RTE(this); this.rte.on('change', this, this.proxy('rte_changed')); - var instanceReady = false; - this.rte.on('instanceReady', this, function () { - clearTimeout(instanceReady); - instanceReady = setTimeout(function () { - self.trigger('rte:ready'); - }, 0); + this.rte.on('rte:ready', this, function () { + self.trigger('rte:ready'); }); return $.when( @@ -337,6 +333,8 @@ root.contentEditable = false; self.setup_editables(root); + + self.trigger('rte:ready'); }); }, -- cgit v1.2.3 From f040cfc7b1b8cfcdaddc3c2ea36110e886a8e47d Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 23 Sep 2013 15:49:14 +0200 Subject: [FIX] placeholder image when edition starts it's apparently better when it's completely broken and can't be edited. YMMV bzr revid: xmo@openerp.com-20130923134914-1si4fz8fg72iktvw --- addons/website/static/src/js/website.editor.js | 3 +++ 1 file changed, 3 insertions(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 0c32cf40fb2..945164dfed8 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -406,6 +406,9 @@ allowedContent: true, // Don't insert paragraphs around content in e.g.
  • autoParagraph: false, + // Don't automatically add   or
    in empty block-level + // elements when edition starts + fillEmptyBlocks: false, filebrowserImageUploadUrl: "/website/attach", // Support for sharedSpaces in 4.x extraPlugins: 'sharedspace,customdialogs,tablebutton,oeref', -- cgit v1.2.3 From f420f98492c24c786e7cb3c47399f16603487ffc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 23 Sep 2013 16:35:34 +0200 Subject: [FIX] turns out a new mandatory positional argument blows things up a bit bzr revid: tde@openerp.com-20130923143534-qnab6bv6upw1vt70 --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 945164dfed8..b82f665c838 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -649,7 +649,7 @@ return openerp.jsonRpc('/web/dataset/call_kw', 'call', { model: 'website', method: 'list_pages', - args: [], + args: [null], kwargs: { context: website.get_context() }, -- cgit v1.2.3 From 7533fe77b44df28ccbe1708df6dbd36ce023ed48 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 24 Sep 2013 13:06:01 +0200 Subject: [FIX] paste in webkit-ish browsers clipboard plugin was getting lost due to method used to get a readonly toplevel editor with editable sub-sections in it. The clipboard plugin creates a hidden pasteboard element to safely get a the clipboard data before inserting it at paste point, this clipboard may have to be made @contenteditable if it's created in a readonly area. Which was the case here: the pasteboard was inserted at the root of the editor, which is not editable. But because of @data-cke-editable being explicitly set, ckeditor would believe it had inserted the pasteboard in an editable section and thus would *not* set its @contenteditable leading to a useless readonly pasteboard. The purpose of @data-cke-editable was to make the editor itself "editable" for cke (in order for the toolbar to not be disabled) while it would not actually be editable (@contenteditable) for users. This is better reimplemented by calling API methods to make the editor editable but its root element not editable, one of the improvements being that commands (and thus toolbar buttons) now switch state correctly based on context. bzr revid: xmo@openerp.com-20130924110601-gfvc395rsedpnoh3 --- addons/website/static/src/js/website.editor.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index b82f665c838..413d26bda3a 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -321,16 +321,16 @@ var self = this; // create a single editor for the whole page var root = document.getElementById('wrapwrap'); - $(root).attr('data-cke-editable', 'true') - .on('dragstart', 'img', function (e) { - e.preventDefault(); - }); - this.editor = CKEDITOR.inline(root, self._config()); - this.editor.on('instanceReady', function () { + $(root).on('dragstart', 'img', function (e) { + e.preventDefault(); + }); + var editor = this.editor = CKEDITOR.inline(root, self._config()); + editor.on('instanceReady', function () { + editor.setReadOnly(false); // ckeditor set root to editable, disable it (only inner // sections are editable) // FIXME: are there cases where the whole editor is editable? - root.contentEditable = false; + editor.editable().setReadOnly(true); self.setup_editables(root); -- cgit v1.2.3 From 2c4560aca631630237ace6a222ab4929d2fb3a20 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 24 Sep 2013 15:51:20 +0200 Subject: [ADD] edition of link labels via dialog bzr revid: xmo@openerp.com-20130924135120-epq1w7wb1a6jfxqn --- addons/website/static/src/js/website.editor.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 413d26bda3a..41280199e45 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -496,11 +496,15 @@ this.changed($target.find('.url-source')); }, 'click button.remove': 'remove_link', + 'change input#link-text': function (e) { + this.text = $(e.target).val() + }, }), init: function (editor) { this._super(editor); // url -> name mapping for existing pages this.pages = Object.create(null); + this.text = null; }, start: function () { var element; @@ -554,13 +558,15 @@ if (this.element) { this.element.setAttributes(attributes); this.element.removeAttributes(to_remove); + if (this.text) { this.element.setText(this.text); } } else { var selection = this.editor.getSelection(); var range = selection.getRanges(true)[0]; if (range.collapsed) { //noinspection JSPotentiallyInvalidConstructorUsage - var text = new CKEDITOR.dom.text(label || url); + var text = new CKEDITOR.dom.text( + this.text || label || url); range.insertNode(text); range.selectNodeContents(text); } @@ -628,6 +634,7 @@ this.changed($control); + this.$('input#link-text').val(this.element.getText()); this.$('input.window-new').prop( 'checked', this.element.getAttribute('target') === '_blank'); }, -- cgit v1.2.3 From 8c25a35cc6fc5380efa52ea0ec737883b63703e3 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Thu, 26 Sep 2013 15:17:08 +0200 Subject: [FIX] Save translations and t-fields bzr revid: fme@openerp.com-20130926131708-16xmpbrx0vxlgbtw --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 41280199e45..8b15422b90d 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -282,7 +282,7 @@ }); }).get(); return $.when.apply(null, defs).then(function () { - window.location.href = window.location.href.replace(/unable_editor(=[^&]*)?|#.*/g, ''); + website.reload(); }); }, /** -- cgit v1.2.3 From 36a10309a9d4e24438e9452ea89ef745cc55559e Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Mon, 30 Sep 2013 17:32:50 +0200 Subject: [IMP] website snippet: edit background and snippet image with rte editor, and reduce code bzr revid: chm@openerp.com-20130930153250-408yct764u9i6q3p --- addons/website/static/src/js/website.editor.js | 1 + 1 file changed, 1 insertion(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 8b15422b90d..b8140b5a1c1 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -911,6 +911,7 @@ while (node && !$(node).hasClass('oe_editable')) { node = node.parentNode; } + $(m.target).trigger('node_changed'); return node; }) .compact() -- cgit v1.2.3 From f4980e1d3b74b9b3a2cbecdc706b516b78fb664f Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 1 Oct 2013 12:00:45 +0200 Subject: [IMP] split out CKE-specific stuff from ImageDialog bzr revid: xmo@openerp.com-20131001100045-0pp4ii11zuldiyun --- addons/website/static/src/js/website.editor.js | 116 +++++++++++++++++-------- 1 file changed, 79 insertions(+), 37 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index b8140b5a1c1..c91c1c6920a 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -18,7 +18,7 @@ return new website.editor.LinkDialog(editor).appendTo(document.body); } function image_dialog(editor) { - return new website.editor.ImageDialog(editor).appendTo(document.body); + return new website.editor.RTEImageDialog(editor).appendTo(document.body); } if (website.is_editable) { @@ -673,6 +673,23 @@ }); }, }); + /** + * ImageDialog widget. Lets users change an image, including uploading a + * new image in OpenERP or selecting the image style (if supported by + * the caller). + * + * Initialized as usual, but the caller can hook into two events: + * + * @event start({url, style}) called during dialog initialization and + * opening, the handler can *set* the ``url`` + * and ``style`` properties on its parameter + * to provide these as default values to the + * dialog + * @event save({url, style}) called during dialog finalization, the handler + * is provided with the image url and style + * selected by the users (or possibly the ones + * originally passed in) + */ website.editor.ImageDialog = website.editor.Dialog.extend({ template: 'website.editor.dialog.image', events: _.extend({}, website.editor.Dialog.prototype.events, { @@ -685,47 +702,27 @@ 'click a[href=#existing]': 'browse_existing', 'change select.image-style': 'preview_image', }), - start: function () { - var selection = this.editor.getSelection(); - var el = selection && selection.getSelectedElement(); - this.element = null; - var $select = this.$('.image-style'); - var $options = $select.children(); - this.image_styles = $options.map(function () { return this.value; }).get(); - - if (el && el.is('img')) { - this.element = el; - _(this.image_styles).each(function (style) { - if (el.hasClass(style)) { - $select.val(style); - } - }); - // set_image must follow setup of image style - this.set_image(el.getAttribute('src')); + start: function () { + var o = { url: null, style: null, }; + // avoid typos, prevent addition of new properties to the object + Object.preventExtensions(o); + this.trigger('start', o); + + if (o.url) { + if (o.style) { + this.$('.image-style').val(o.style) + } + this.set_image(o.url); } return this._super(); }, save: function () { - var url = this.$('input.url').val(); - var style = this.$('.image-style').val(); - var element, editor = this.editor; - if (!(element = this.element)) { - element = editor.document.createElement('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 => - // defer insertion so modal has been hidden & destroyed before - // it happens - setTimeout(function () { - editor.insertElement(element); - }, 0); - } - element.setAttribute('src', url); - $(element.$).removeClass(this.image_styles.join(' ')); - if (style) { element.addClass(style); } - + this.trigger('save', { + url: this.$('input.url').val(), + style: this.$('.image-style').val(), + }); return this._super(); }, @@ -769,12 +766,57 @@ .removeClass(this.image_styles.join(' ')) .addClass(this.$('select.image-style').val()); }, - browse_existing: function (e) { e.preventDefault(); new website.editor.ExistingImageDialog(this).appendTo(document.body); }, }); + website.editor.RTEImageDialog = website.editor.ImageDialog.extend({ + init: function () { + this._super.apply(this, arguments); + + this.on('start', this, this.proxy('started')); + this.on('save', this, this.proxy('saved')); + }, + started: function (holder) { + var selection = this.editor.getSelection(); + var el = selection && selection.getSelectedElement(); + this.element = null; + + var $select = this.$('.image-style'); + var $options = $select.children(); + this.image_styles = $options.map(function () { return this.value; }).get(); + + if (el && el.is('img')) { + this.element = el; + _(this.image_styles).each(function (style) { + if (el.hasClass(style)) { + holder.style = style; + } + }); + holder.url = el.getAttribute('src'); + } + }, + saved: function (data) { + var element, editor = this.editor; + if (!(element = this.element)) { + element = editor.document.createElement('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 => + // defer insertion so modal has been hidden & destroyed before + // it happens + setTimeout(function () { + editor.insertElement(element); + }, 0); + } + + var style = data.style; + element.setAttribute('src', data.url); + $(element.$).removeClass(this.image_styles.join(' ')); + if (style) { element.addClass(style); } + }, + }); var IMAGES_PER_ROW = 6; var IMAGES_ROWS = 4; -- cgit v1.2.3 From ddb65ce339a8bc9145bb9a2d999ea6350ab28d8c Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 1 Oct 2013 13:34:29 +0200 Subject: [FIX] forgot to move image_style initialization bzr revid: xmo@openerp.com-20131001113429-tc6qgigsxvgbtxnc --- addons/website/static/src/js/website.editor.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index c91c1c6920a..091ad933e74 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -704,6 +704,9 @@ }), start: function () { + var $options = this.$('.image-style').children(); + this.image_styles = $options.map(function () { return this.value; }).get(); + var o = { url: null, style: null, }; // avoid typos, prevent addition of new properties to the object Object.preventExtensions(o); @@ -783,10 +786,6 @@ var el = selection && selection.getSelectedElement(); this.element = null; - var $select = this.$('.image-style'); - var $options = $select.children(); - this.image_styles = $options.map(function () { return this.value; }).get(); - if (el && el.is('img')) { this.element = el; _(this.image_styles).each(function (style) { -- cgit v1.2.3 From aea15f9f6fbced625eab8d110f3b81c244b6700c Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 1 Oct 2013 14:03:35 +0200 Subject: [IMP] website snippet: new change background bzr revid: chm@openerp.com-20131001120335-kwyyodiwturplyfy --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 091ad933e74..c16574eacc0 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -714,7 +714,7 @@ if (o.url) { if (o.style) { - this.$('.image-style').val(o.style) + this.$('.image-style').val(o.style); } this.set_image(o.url); } -- cgit v1.2.3 From 5e472dd71a82272c1e920079785dbd7b29a501f4 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 1 Oct 2013 16:19:30 +0200 Subject: [FIX] website: some fixes for firefox bzr revid: chm@openerp.com-20131001141930-hrfij6qcc2mz7rv3 --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index c16574eacc0..f40ccea715b 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -934,7 +934,7 @@ if (m.attributeName !== 'class') { return true; } // find out what classes were added or removed - var oldClasses = m.oldValue.split(/\s+/); + var oldClasses = (m.oldValue || '').split(/\s+/); var newClasses = m.target.className.split(/\s+/); var change = _.union(_.difference(oldClasses, newClasses), _.difference(newClasses, oldClasses)); -- cgit v1.2.3 From 5a3036a6cd055dfb6ac02201d2341fad6d0fd2a7 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 9 Oct 2013 15:55:04 +0200 Subject: [IMP] Remove ununsed code and dom attributes bzr revid: fme@openerp.com-20131009135504-5cqnbiuxqn4m6if3 --- addons/website/static/src/js/website.editor.js | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index f40ccea715b..54121ca5018 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', -- cgit v1.2.3 From 9ba56d0d71a931f30040f63d3094daaa28606dbf Mon Sep 17 00:00:00 2001 From: ddm Date: Wed, 9 Oct 2013 18:09:49 +0200 Subject: [IMP] Finish tour according to kanban task bzr revid: ddm@openerp.com-20131009160949-ma5e3a13qchzq4vy --- addons/website/static/src/js/website.editor.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index f40ccea715b..7d3ebc74321 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -203,8 +203,9 @@ } }); // Adding Static Menus - menu.append('
  • Change Theme
  • '); + menu.append('
  • Change Theme
  • '); menu.append('
  • Advanced view editor
  • '); + self.trigger('rte:customize_menu_ready'); } ); }); -- cgit v1.2.3 From fc012b1c9ca07203f96afb1038250e129e1635d9 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 10 Oct 2013 09:28:09 +0200 Subject: [IMP] slugify page names on creation bzr revid: xmo@openerp.com-20131010072809-p8f5j9bcnnfnkhtj --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 2c72b4114f3..ecb3c6c4d83 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -602,7 +602,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); }); -- cgit v1.2.3 From eb2709ffc649d65ab97b3c137e9055b8c2921085 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 10 Oct 2013 09:29:19 +0200 Subject: [ADD] apparently I'm supposed to add the img class to images bzr revid: xmo@openerp.com-20131010072919-t1vc7l5t5c3wh9kt --- addons/website/static/src/js/website.editor.js | 1 + 1 file changed, 1 insertion(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index ecb3c6c4d83..d839252bc58 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -799,6 +799,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 => -- cgit v1.2.3 From 9cdbe94ce5006e5a2184941d8d31c1e808a02bcf Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 10 Oct 2013 12:30:05 +0200 Subject: [ADD] saving of image fields bzr revid: xmo@openerp.com-20131010103005-mp0afaps3ssqacm8 --- addons/website/static/src/js/website.editor.js | 1 + 1 file changed, 1 insertion(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index f40ccea715b..217d7fd24ee 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -812,6 +812,7 @@ var style = data.style; element.setAttribute('src', data.url); + element.removeAttribute('data-cke-saved-src'); $(element.$).removeClass(this.image_styles.join(' ')); if (style) { element.addClass(style); } }, -- cgit v1.2.3 From 8a10e6a688219534d07beadc30cd51e6cbef3020 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 11 Oct 2013 15:56:16 +0200 Subject: [IMP] add a cke widget for monetary fields to make the currency symbol non-editable bzr revid: xmo@openerp.com-20131011135616-3zfvuhoxjzoce78q --- addons/website/static/src/js/website.editor.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 217d7fd24ee..30514b25780 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -162,9 +162,17 @@ editables: { text: '*' }, upcast: function (el) { - return el.attributes['data-oe-type']; + return el.attributes['data-oe-type'] + && el.attributes['data-oe-type'] !== 'monetary'; }, }); + editor.widgets.add('monetary', { + editables: { text: 'span.oe_currency_value' }, + + upcast: function (el) { + return el.attributes['data-oe-type'] === 'monetary'; + } + }); } }); @@ -346,12 +354,17 @@ var self = this; // setup dirty-marking for each editable element this.fetch_editables(root) - .prop('contentEditable', true) .addClass('oe_editable') .each(function () { var node = this; - observer.observe(node, OBSERVER_CONFIG); var $node = $(node); + // only explicitly set contenteditable on view sections, + // cke widgets system will do the widgets themselves + if ($node.data('oe-model') === 'ir.ui.view') { + node.contentEditable = true; + } + + observer.observe(node, OBSERVER_CONFIG); $node.one('content_changed', function () { $node.addClass('oe_dirty'); self.trigger('change'); -- cgit v1.2.3 From c81bf938cf5c03901f9019feb5bc01a460792d02 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 14 Oct 2013 12:09:44 +0200 Subject: [FIX] don't close editor dialogs on click *around* the dialog APR double-clicks images in the image sub-popup (browse existing), if an image on a side (outside the initial dialog's rect) is picked the first click will select it and close the dialog, and the second one will land on the base dialog's backdrop, cancelling & closing it. bzr revid: xmo@openerp.com-20131014100944-3xtbiyj063fmzhko --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index ffb0f9b86a3..81fe087a59e 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -483,7 +483,7 @@ }, start: function () { var sup = this._super(); - this.$el.modal(); + this.$el.modal({backdrop: 'static'}); return sup; }, save: function () { -- cgit v1.2.3 From 7c0da590e19e3f0b942c6442b2d50c9ab1ef65de Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 16 Oct 2013 12:45:45 +0200 Subject: [IMP] website: after save reload page with the same scrolling bzr revid: chm@openerp.com-20131016104545-e415ixicw2crci2w --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 81fe087a59e..aef390027c5 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -307,7 +307,7 @@ }); }, cancel: function () { - window.location.href = window.location.href.replace(/unable_editor(=[^&]*)?|#.*/g, ''); + website.reload(); }, }); -- cgit v1.2.3 From 57c5f11aaeabd86f7bf9a94f33a06d01b82e3a60 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 16 Oct 2013 14:37:08 +0200 Subject: [FIX] don't use mutation events if unnecessary Mutation events are synchronous and one is triggered per observed alteration (they're not batched). When doing lots of modifications to the DOM tree, they will add a lot of overhead as (in this case) the event handler will run for *each* added node and it will run during (and slow down) node insertion rather than afterwards. bzr revid: xmo@openerp.com-20131016123708-lx389x0g6xs6zu10 --- addons/website/static/src/js/website.editor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index aef390027c5..a1b8ffdb9ee 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -927,7 +927,7 @@ } - var Observer = window.MutationObserver || window.WebkitMutationObserver || window.JsMutationObserver; + website.Observer = window.MutationObserver || window.WebkitMutationObserver || window.JsMutationObserver; var OBSERVER_CONFIG = { childList: true, attributes: true, @@ -935,7 +935,7 @@ subtree: true, attributeOldValue: true, }; - var observer = new Observer(function (mutations) { + var observer = new website.Observer(function (mutations) { // NOTE: Webkit does not fire DOMAttrModified => webkit browsers // relying on JsMutationObserver shim (Chrome < 18, Safari < 6) // will not mark dirty on attribute changes (@class, img/@src, -- cgit v1.2.3 From 9949aa626c3decc26d9f776198838c2a63699adc Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 16 Oct 2013 15:34:32 +0200 Subject: [IMP] remove bidi plugin its isReadOnly() calls generates quite a bunch of timeline events bzr revid: xmo@openerp.com-20131016133432-4aq30rd8szbs2bef --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index a1b8ffdb9ee..485ba48e35b 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -394,7 +394,7 @@ // - contextmenu & tabletools (disable contextual menu) // - bunch of unused plugins var plugins = [ - 'a11yhelp', 'basicstyles', 'bidi', 'blockquote', + 'a11yhelp', 'basicstyles', 'blockquote', 'clipboard', 'colorbutton', 'colordialog', 'dialogadvtab', 'elementspath', 'enterkey', 'entities', 'filebrowser', 'find', 'floatingspace','format', 'htmlwriter', 'iframe', -- cgit v1.2.3 From 3b578cd3731edded4387ff141c655db8a5f3d25f Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 17 Oct 2013 15:31:33 +0200 Subject: [IMP] take over triple-click behavior in webkit to avoid breaking snippets and the like bzr revid: xmo@openerp.com-20131017133133-uebgw7m3fo9as38s --- addons/website/static/src/js/website.editor.js | 38 ++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 485ba48e35b..ff9f82b0f8e 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -311,6 +311,7 @@ }, }); + var blocks_selector = _.keys(CKEDITOR.dtd.$block).join(','); /* ----- RICH TEXT EDITOR ---- */ website.RTE = openerp.Widget.extend({ tagName: 'li', @@ -324,6 +325,42 @@ this._super.apply(this, arguments); }, + /** + * In Webkit-based browsers, triple-click will select a paragraph up to + * the start of the next "paragraph" including any empty space + * inbetween. When said paragraph is removed or altered, it nukes + * the empty space and brings part of the content of the next + * "paragraph" (which may well be e.g. an image) into the current one, + * completely fucking up layouts and breaking snippets. + * + * Try to fuck around with selections on triple-click to attempt to + * fix this garbage behavior. + * + * Note: for consistent behavior we may actually want to take over + * triple-clicks, in all browsers in order to ensure consistent cross- + * platform behavior instead of being at the mercy of rendering engines + * & platform selection quirks? + */ + webkitSelectionFixer: function (root) { + root.addEventListener('click', function (e) { + // only webkit seems to have a fucked up behavior, ignore others + // FIXME: $.browser goes away in jquery 1.9... + if (!$.browser.webkit) { return; } + // http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-eventgroupings-mouseevents + // The detail attribute indicates the number of times a mouse button has been pressed + // we just want the triple click + if (e.detail !== 3) { return; } + + // Get closest block-level element to the triple-clicked + // element (using ckeditor's block list because why not) + var $closest_block = $(e.target).closest(blocks_selector); + + // manually set selection range to the content of the + // triple-clicked block-level element, to avoid crossing over + // between block-level elements + document.getSelection().selectAllChildren($closest_block[0]); + }); + }, start_edition: function ($elements) { var self = this; // create a single editor for the whole page @@ -331,6 +368,7 @@ $(root).on('dragstart', 'img', function (e) { e.preventDefault(); }); + this.webkitSelectionFixer(root); var editor = this.editor = CKEDITOR.inline(root, self._config()); editor.on('instanceReady', function () { editor.setReadOnly(false); -- cgit v1.2.3 From 855944498693f606ee1952ce5d8c0fd8cf0c3bc1 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 18 Oct 2013 12:35:40 +0200 Subject: [FIX] tab handling in tables CKEditor's tab plugin can't deal with a non-editable editor root (editor.editable().hasFocus returns false and disables it), so reimplement the behavior. For some reason, ckeditor's selection API also does not seem to work correctly in table cells in Firefox, so use the browser's native API instead. Tab goes to the next cell, shift-tab goes to the previous cell, shift-tab from the first table cell is ignored and tab from the last table cell creates a new row and sets focus in the new row's first cell. These behaviors seem to more or less match Word and OpenOffice Writer's. bzr revid: xmo@openerp.com-20131018103540-12p8j18ypte8dr9u --- addons/website/static/src/js/website.editor.js | 68 +++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index ff9f82b0f8e..c1f05d9b661 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -361,6 +361,67 @@ document.getSelection().selectAllChildren($closest_block[0]); }); }, + tableNavigation: function (root) { + var self = this; + $(root).on('keydown', function (e) { + // ignore non-TAB + if (e.which !== 9) { return; } + + if (self.handleTab(e)) { + e.preventDefault(); + } + }); + }, + /** + * Performs whatever operation is necessary on a [TAB] hit, returns + * ``true`` if the event's default should be cancelled (if the TAB was + * handled by the function) + */ + handleTab: function (event) { + var forward = !event.shiftKey; + + var root = window.getSelection().getRangeAt(0).commonAncestorContainer; + var $cell = $(root).closest('td,th'); + + if (!$cell.length) { return false; } + + var cell = $cell[0]; + + // find cell in same row + var row = cell.parentNode; + var sibling = row.cells[cell.cellIndex + (forward ? 1 : -1)]; + if (sibling) { + document.getSelection().selectAllChildren(sibling); + return true; + } + + // find cell in previous/next row + var table = row.parentNode; + var sibling_row = table.rows[row.rowIndex + (forward ? 1 : -1)]; + if (sibling_row) { + var new_cell = sibling_row.cells[forward ? 0 : sibling_row.cells.length - 1]; + document.getSelection().selectAllChildren(new_cell); + return true; + } + + // at edge cells, copy word/openoffice behavior: if going backwards + // from first cell do nothing, if going forwards from last cell add + // a row + if (forward) { + var row_size = row.cells.length; + var new_row = document.createElement('tr'); + while(row_size--) { + var newcell = document.createElement('td'); + // zero-width space + newcell.textContent = '\u200B'; + new_row.appendChild(newcell); + } + table.appendChild(new_row); + document.getSelection().selectAllChildren(new_row.cells[0]); + } + + return true; + }, start_edition: function ($elements) { var self = this; // create a single editor for the whole page @@ -369,6 +430,7 @@ e.preventDefault(); }); this.webkitSelectionFixer(root); + this.tableNavigation(root); var editor = this.editor = CKEDITOR.inline(root, self._config()); editor.on('instanceReady', function () { editor.setReadOnly(false); @@ -379,6 +441,10 @@ self.setup_editables(root); + // disable firefox's broken table resizing thing + document.execCommand("enableObjectResizing", false, "false"); + document.execCommand("enableInlineTableEditing", false, "false"); + self.trigger('rte:ready'); }); }, @@ -439,7 +505,7 @@ 'indentblock', 'indentlist', 'justify', 'list', 'pastefromword', 'pastetext', 'preview', 'removeformat', 'resize', 'save', 'selectall', 'stylescombo', - 'tab', 'table', 'templates', 'toolbar', 'undo', 'wysiwygarea' + 'table', 'templates', 'toolbar', 'undo', 'wysiwygarea' ]; return { // FIXME -- cgit v1.2.3 From 58f1b5ad021f7149317f69bcbfab890bf43d3a83 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 22 Oct 2013 13:00:15 +0200 Subject: [IMP] prevent default on triple-click interrupt bzr revid: xmo@openerp.com-20131022110015-iewvo1x0jdogswus --- addons/website/static/src/js/website.editor.js | 1 + 1 file changed, 1 insertion(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index c1f05d9b661..59b8ec4fe0f 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -350,6 +350,7 @@ // The detail attribute indicates the number of times a mouse button has been pressed // we just want the triple click if (e.detail !== 3) { return; } + e.preventDefault(); // Get closest block-level element to the triple-clicked // element (using ckeditor's block list because why not) -- cgit v1.2.3 From 3655f43e42475da4be76c5d2f51facfdd8274b52 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 22 Oct 2013 17:11:44 +0200 Subject: [IMP] warnings and shit bzr revid: xmo@openerp.com-20131022151144-tblwba9rf77iuidl --- addons/website/static/src/js/website.editor.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 59b8ec4fe0f..8b3a73a06a3 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -56,7 +56,7 @@ //noinspection JSValidateTypes editor.addCommand('link', { - exec: function (editor, data) { + exec: function (editor) { link_dialog(editor); return true; }, @@ -65,7 +65,7 @@ }); //noinspection JSValidateTypes editor.addCommand('image', { - exec: function (editor, data) { + exec: function (editor) { image_dialog(editor); return true; }, @@ -219,7 +219,7 @@ var view_id = $(event.currentTarget).data('view-id'); openerp.jsonRpc('/website/customize_template_toggle', 'call', { 'view_id': view_id - }).then( function(result) { + }).then( function() { window.location.reload(); }); }); @@ -253,7 +253,6 @@ ); }, edit: function () { - var self = this; this.$buttons.edit.prop('disabled', true); this.$('#website-top-view').hide(); this.$('#website-top-edit').show(); @@ -423,7 +422,7 @@ return true; }, - start_edition: function ($elements) { + start_edition: function () { var self = this; // create a single editor for the whole page var root = document.getElementById('wrapwrap'); @@ -484,7 +483,7 @@ .filter(function () { var $this = $(this); // keep view sections and fields which are *not* in - // view sections for toplevel editables + // view sections for top-level editables return $this.data('oe-model') === 'ir.ui.view' || !$this.closest('[data-oe-model = "ir.ui.view"]').length; }); @@ -855,7 +854,7 @@ this.preview_image(); }, - file_selection: function (e) { + file_selection: function () { this.$('button.filepicker').removeClass('btn-danger btn-success'); var self = this; -- cgit v1.2.3 From 7dd1934585ed85b925def0a686df04aa3990c5f5 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 23 Oct 2013 11:11:52 +0200 Subject: [FIX] option typo: unable_editor -> enable_editor bzr revid: fme@openerp.com-20131023091152-h0hxw47hzfor2al8 --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 8b3a73a06a3..2249de2a24d 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -177,7 +177,7 @@ var editor = new website.EditorBar(); var $body = $(document.body); editor.prependTo($body).then(function () { - if (location.search.indexOf("unable_editor") >= 0) { + if (location.search.indexOf("enable_editor") >= 0) { editor.edit(); } }); -- cgit v1.2.3 From 1ce3230d135b03be09406e7c587ae3477eafb44b Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 23 Oct 2013 15:09:18 +0200 Subject: [IMP] don't completely wedge the RTE in case save fails. This may well break snippets entirely in case of save failure. bzr revid: xmo@openerp.com-20131023130918-j5s81t0j60gitr1t --- addons/website/static/src/js/website.editor.js | 64 +++++++++++++++++++++----- 1 file changed, 52 insertions(+), 12 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 2249de2a24d..f9d2aef339b 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -272,30 +272,58 @@ editor.destroy(); // FIXME: select editables then filter by dirty? var defs = this.rte.fetch_editables(root) - .removeClass('oe_editable cke_focus') - .removeAttr('contentEditable') .filter('.oe_dirty') + .removeAttr('contentEditable') + .removeClass('oe_dirty oe_editable cke_focus oe_carlos_danger') .map(function () { var $el = $(this); // TODO: Add a queue with concurrency limit in webclient // https://github.com/medikoo/deferred/blob/master/lib/ext/function/gate.js return self.saving_mutex.exec(function () { return self.saveElement($el) - .fail(function () { - var data = $el.data(); - console.error(_.str.sprintf('Could not save %s(%d).%s', data.oeModel, data.oeId, data.oeField)); + .then(undefined, function (thing, response) { + // because ckeditor regenerates all the dom, + // we can't just setup the popover here as + // everything will be destroyed by the DOM + // regeneration. Add markings instead, and + // returns a new rejection with all relevant + // info + var id = _.uniqueId('carlos_danger_'); + $el.addClass('oe_dirty oe_carlos_danger'); + $el.addClass(id); + return $.Deferred().reject({ + id: id, + error: response.data, + }); }); }); }).get(); return $.when.apply(null, defs).then(function () { website.reload(); + }, function (failed) { + // If there were errors, re-enable edition + self.rte.start_edition(true).then(function () { + // jquery's deferred being a pain in the ass + if (!_.isArray(failed)) { failed = [failed]; } + + _(failed).each(function (failure) { + $(root).find('.' + failure.id) + .removeClass(failure.id) + .popover({ + trigger: 'hover', + content: failure.error.message, + placement: 'auto top', + }) + // Force-show popovers so users will notice them. + .popover('show'); + }) + }); }); }, /** * Saves an RTE content, which always corresponds to a view section (?). */ saveElement: function ($el) { - $el.removeClass('oe_dirty'); var markup = $el.prop('outerHTML'); return openerp.jsonRpc('/web/dataset/call', 'call', { model: 'ir.ui.view', @@ -422,15 +450,25 @@ return true; }, - start_edition: function () { + /** + * Makes the page editable + * + * @param {Boolean} [restart=false] in case the edition was already set + * up once and is being re-enabled. + * @returns {$.Deferred} deferred indicating when the RTE is ready + */ + start_edition: function (restart) { var self = this; // create a single editor for the whole page var root = document.getElementById('wrapwrap'); - $(root).on('dragstart', 'img', function (e) { - e.preventDefault(); - }); - this.webkitSelectionFixer(root); - this.tableNavigation(root); + if (!restart) { + $(root).on('dragstart', 'img', function (e) { + e.preventDefault(); + }); + this.webkitSelectionFixer(root); + this.tableNavigation(root); + } + var def = $.Deferred(); var editor = this.editor = CKEDITOR.inline(root, self._config()); editor.on('instanceReady', function () { editor.setReadOnly(false); @@ -446,7 +484,9 @@ document.execCommand("enableInlineTableEditing", false, "false"); self.trigger('rte:ready'); + def.resolve(); }); + return def; }, setup_editables: function (root) { -- cgit v1.2.3 From 4c88701f3dbf12414540db95d98b18ab628ff142 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 25 Oct 2013 11:59:52 +0200 Subject: [FIX] change access rights for customize_template_* bzr revid: xmo@openerp.com-20131025095952-9ditm4q3fwr9auto --- addons/website/static/src/js/website.editor.js | 1 - 1 file changed, 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index f9d2aef339b..6fb0f459a22 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -517,7 +517,6 @@ fetch_editables: function (root) { return $(root).find('[data-oe-model]') - // FIXME: propagation should make "meta" blocks non-editable in the first place... .not('link, script') .not('.oe_snippet_editor') .filter(function () { -- cgit v1.2.3 From eb7b1362cdaeb7a2221e542f1dad1ea483305477 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Fri, 25 Oct 2013 17:24:46 +0200 Subject: [WIP] Menu working from database (not yet multi-website) bzr revid: fme@openerp.com-20131025152446-si9gsjujzcn40hip --- addons/website/static/src/js/website.editor.js | 38 ++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index f9d2aef339b..826c2e39091 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -674,6 +674,7 @@ return $.when( this.fetch_pages().done(this.proxy('fill_pages')), + this.fetch_menus().done(this.proxy('fill_menus')), this._super() ).done(this.proxy('bind_data')); }, @@ -762,6 +763,23 @@ '/pagenew/%s?noredirect', encodeURI(val))) .then(function (response) { self.make_link(response, false, val); + var parent_id = self.$('.add-to-menu').val(); + if (parent_id) { + return openerp.jsonRpc('/web/dataset/call_kw', 'call', { + model: 'website.menu', + method: 'create', + args: [{ + 'name': val, + 'url': response, + 'sequence': 0, // TODO: better tree widget + 'website_id': website.id, + 'parent_id': parent_id|0, + }], + kwargs: { + context: website.get_context() + }, + }); + } }); } else { this.make_link(val, this.$('input.window-new').prop('checked')); @@ -828,6 +846,26 @@ new Option(result.name, result.url); }); }, + fetch_menus: function () { + var context = website.get_context(); + return openerp.jsonRpc('/web/dataset/call_kw', 'call', { + model: 'website.menu', + method: 'get_list', + args: [[context.website_id]], + kwargs: { + context: context + }, + }); + }, + fill_menus: function (results) { + var self = this; + var menus = this.$('select.add-to-menu')[0]; + _(results).each(function (result) { + var name = (new Array(result.level).join('|-')) + ' ' + result.name; + menus.options[menus.options.length] = + new Option(name, result.id || 0); + }); + }, }); /** * ImageDialog widget. Lets users change an image, including uploading a -- cgit v1.2.3 From 26e62b0e0eb9210bb3b152279766d80aa67ae403 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Mon, 28 Oct 2013 12:23:50 +0100 Subject: [IMP] Menu tree from client side bzr revid: fme@openerp.com-20131028112350-9or1z3e3ndgk4mfg --- addons/website/static/src/js/website.editor.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index aa1ab86b330..25453bde0d6 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -849,21 +849,24 @@ var context = website.get_context(); return openerp.jsonRpc('/web/dataset/call_kw', 'call', { model: 'website.menu', - method: 'get_list', + method: 'get_tree', args: [[context.website_id]], kwargs: { context: context }, }); }, - fill_menus: function (results) { + fill_menus: function (tree) { var self = this; var menus = this.$('select.add-to-menu')[0]; - _(results).each(function (result) { - var name = (new Array(result.level).join('|-')) + ' ' + result.name; - menus.options[menus.options.length] = - new Option(name, result.id || 0); - }); + var process_tree = function(node) { + var name = (new Array(node.level + 1).join('|-')) + ' ' + node.name; + menus.options[menus.options.length] = new Option(name, node.id); + node.children.forEach(function (child) { + process_tree(child); + }); + }; + process_tree(tree); }, }); /** -- cgit v1.2.3 From 0db0f20bda410bd6601c266026363fc95b21c9c4 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 28 Oct 2013 16:23:42 +0100 Subject: [ADD] WIP link combo bzr revid: xmo@openerp.com-20131028152342-5clhbwwwfcdxxxq0 --- addons/website/static/src/js/website.editor.js | 164 +++++++++++++++++++++++-- 1 file changed, 154 insertions(+), 10 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 6fb0f459a22..b6102de0fd3 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -174,6 +174,157 @@ } }); + CKEDITOR.plugins.add('bootstrapcombo', { + requires: 'richcombo', + + init: function (editor) { + var config = editor.config; + + editor.ui.addRichCombo('BootstrapLinkCombo', { + // default title + label: "Links", + // hover + title: "Link styling", + toolbar: 'styles,10', + allowedContent: ['a'], + + panel: { + css: [ + '/website/static/lib/bootstrap/css/bootstrap.css', + CKEDITOR.skin.getPath( 'editor' ) + ].concat( config.contentsCss ), + multiSelect: true, + }, + + types: { + 'basic': 'btn-default', + 'primary': 'btn-primary', + 'success': 'btn-success', + 'info': 'btn-info', + 'warning': 'btn-warning', + 'danger': 'btn-danger', + }, + + sizes: { + 'large': 'btn-lg', + 'default': '', + 'small': 'btn-sm', + 'extra small': 'btn-xs', + }, + + init: function () { + this.add('', 'Reset'); + this.startGroup("Types"); + for(var type in this.types) { + if (!this.types.hasOwnProperty(type)) { continue; } + var cls = this.types[type]; + var el = _.str.sprintf( + '%s', + cls, type); + this.add(type, el); + } + this.startGroup("Sizes"); + for (var size in this.sizes) { + if (!this.sizes.hasOwnProperty(size)) { continue; } + cls = this.sizes[size]; + + el = _.str.sprintf( + '%s', + cls, size); + this.add(size, el); + } + this.commit(); + }, + onRender: function () { + var self = this; + editor.on('selectionChange', function (e) { + var path = e.data.path, el; + + if (!(el = path.contains('a'))) { + self.element = null; + self.disable(); + return; + } + + self.enable(); + // This is crap, but getting the currently selected + // element from within onOpen absolutely does not + // work, so store the "current" element in the + // widget instead + self.element = el; + }); + setTimeout(function () { + // Because I can't find any normal hook where the + // bloody button's bloody element is available + self.disable(); + }, 0); + }, + onOpen: function () { + this.showAll(); + this.unmarkAll(); + + for(var val in this.types) { + if (!this.types.hasOwnProperty(val)) { continue; } + var cls = this.types[val]; + if (!this.element.hasClass(cls)) { continue; } + + this.mark(val); + break; + } + + var found; + for(val in this.sizes) { + if (!this.sizes.hasOwnProperty(val)) { continue; } + cls = this.sizes[val]; + if (!cls || !this.element.hasClass(cls)) { continue; } + + found = true; + this.mark(val); + break; + } + if (!found && this.element.hasClass('btn')) { + this.mark('default'); + } + }, + onClick: function (value) { + editor.focus(); + editor.fire('saveShapshot'); + + // basic btn setup + var el = this.element; + if (!el.hasClass('btn')) { + el.addClass('btn'); + el.addClass('btn-default'); + } + + if (!value) { + this.setClass(this.types); + this.setClass(this.sizes); + el.removeClass('btn'); + } else if (value in this.types) { + this.setClass(this.types, value); + } else if (value in this.sizes) { + this.setClass(this.sizes, value); + } + + editor.fire('saveShapshot'); + }, + setClass: function (classMap, value) { + var element = this.element; + _(classMap).each(function (cls) { + if (!cls) { return; } + element.removeClass(cls); + }.bind(this)); + + var cls = classMap[value]; + if (cls) { + element.addClass(cls); + } + } + }); + }, + }); + var editor = new website.EditorBar(); var $body = $(document.body); editor.prependTo($body).then(function () { @@ -566,7 +717,7 @@ fillEmptyBlocks: false, filebrowserImageUploadUrl: "/website/attach", // Support for sharedSpaces in 4.x - extraPlugins: 'sharedspace,customdialogs,tablebutton,oeref', + extraPlugins: 'sharedspace,customdialogs,tablebutton,oeref,bootstrapcombo', // Place toolbar in controlled location sharedSpaces: { top: 'oe_rte_toolbar' }, toolbar: [{ @@ -588,7 +739,7 @@ "Image", "TableButton" ]},{ name: 'styles', items: [ - "Styles" + "Styles", "BootstrapLinkCombo" ]} ], // styles dropdown in toolbar @@ -601,14 +752,7 @@ {name: "Heading 5", element: 'h5'}, {name: "Heading 6", element: 'h6'}, {name: "Formatted", element: 'pre'}, - {name: "Address", element: 'address'}, - // emphasis - {name: "Muted", element: 'span', attributes: {'class': 'text-muted'}}, - {name: "Primary", element: 'span', attributes: {'class': 'text-primary'}}, - {name: "Warning", element: 'span', attributes: {'class': 'text-warning'}}, - {name: "Danger", element: 'span', attributes: {'class': 'text-danger'}}, - {name: "Success", element: 'span', attributes: {'class': 'text-success'}}, - {name: "Info", element: 'span', attributes: {'class': 'text-info'}} + {name: "Address", element: 'address'} ], }; }, -- cgit v1.2.3 From 82c749c91d472f5e85693bbbcd823ec6f3b259c5 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Mon, 28 Oct 2013 17:26:23 +0100 Subject: [IMP] Refactor LinkDialog -> RTELinkDialog bzr revid: fme@openerp.com-20131028162623-i2a4cixspm8q1crx --- addons/website/static/src/js/website.editor.js | 170 +++++++++++++------------ 1 file changed, 89 insertions(+), 81 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 25453bde0d6..b3c568c16fc 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -14,7 +14,7 @@ }); function link_dialog(editor) { - return new website.editor.LinkDialog(editor).appendTo(document.body); + return new website.editor.RTELinkDialog(editor).appendTo(document.body); } function image_dialog(editor) { return new website.editor.RTEImageDialog(editor).appendTo(document.body); @@ -662,85 +662,12 @@ this.text = null; }, start: function () { - var element; - if ((element = this.get_selected_link()) && element.hasAttribute('href')) { - this.editor.getSelection().selectElement(element); - } - this.element = element; - if (element) { - this.add_removal_button(); - } - return $.when( this.fetch_pages().done(this.proxy('fill_pages')), this.fetch_menus().done(this.proxy('fill_menus')), this._super() ).done(this.proxy('bind_data')); }, - add_removal_button: function () { - this.$('.modal-footer').prepend( - openerp.qweb.render( - 'website.editor.dialog.link.footer-button')); - }, - remove_link: function () { - var editor = this.editor; - // same issue as in make_link - setTimeout(function () { - editor.removeStyle(new CKEDITOR.style({ - element: 'a', - type: CKEDITOR.STYLE_INLINE, - alwaysRemoveElement: true, - })); - }, 0); - this.close(); - }, - /** - * Greatly simplified version of CKEDITOR's - * plugins.link.dialogs.link.onOk. - * - * @param {String} url - * @param {Boolean} [new_window=false] - * @param {String} [label=null] - */ - make_link: function (url, new_window, label) { - var attributes = {href: url, 'data-cke-saved-href': url}; - var to_remove = []; - if (new_window) { - attributes['target'] = '_blank'; - } else { - to_remove.push('target'); - } - - if (this.element) { - this.element.setAttributes(attributes); - this.element.removeAttributes(to_remove); - if (this.text) { this.element.setText(this.text); } - } else { - var selection = this.editor.getSelection(); - var range = selection.getRanges(true)[0]; - - if (range.collapsed) { - //noinspection JSPotentiallyInvalidConstructorUsage - var text = new CKEDITOR.dom.text( - this.text || label || url); - range.insertNode(text); - range.selectNodeContents(text); - } - - //noinspection JSPotentiallyInvalidConstructorUsage - new CKEDITOR.style({ - type: CKEDITOR.STYLE_INLINE, - element: 'a', - attributes: attributes, - }).applyToRange(range); - - // focus dance between RTE & dialog blow up the stack in Safari - // and Chrome, so defer select() until dialog has been closed - setTimeout(function () { - range.select(); - }, 0); - } - }, save: function () { var self = this, _super = this._super.bind(this); var $e = this.$('.list-group-item.active .url-source'); @@ -785,6 +712,8 @@ } done.then(_super); }, + make_link: function (url, new_window, label) { + }, bind_data: function () { var href = this.element && (this.element.data( 'cke-saved-href') || this.element.getAttribute('href')); @@ -818,13 +747,6 @@ .siblings().removeClass('active') .addBack().removeClass('has-error'); }, - /** - * CKEDITOR.plugins.link.getSelectedLink ignores the editor's root, - * if the editor is set directly on a link it will thus not work. - */ - get_selected_link: function () { - return get_selected_link(this.editor); - }, fetch_pages: function () { return openerp.jsonRpc('/web/dataset/call_kw', 'call', { model: 'website', @@ -869,6 +791,92 @@ process_tree(tree); }, }); + website.editor.RTELinkDialog = website.editor.LinkDialog.extend({ + start: function () { + var element; + if ((element = this.get_selected_link()) && element.hasAttribute('href')) { + this.editor.getSelection().selectElement(element); + } + this.element = element; + if (element) { + this.add_removal_button(); + } + + return this._super(); + }, + add_removal_button: function () { + this.$('.modal-footer').prepend( + openerp.qweb.render( + 'website.editor.dialog.link.footer-button')); + }, + remove_link: function () { + var editor = this.editor; + // same issue as in make_link + setTimeout(function () { + editor.removeStyle(new CKEDITOR.style({ + element: 'a', + type: CKEDITOR.STYLE_INLINE, + alwaysRemoveElement: true, + })); + }, 0); + this.close(); + }, + /** + * Greatly simplified version of CKEDITOR's + * plugins.link.dialogs.link.onOk. + * + * @param {String} url + * @param {Boolean} [new_window=false] + * @param {String} [label=null] + */ + make_link: function (url, new_window, label) { + var attributes = {href: url, 'data-cke-saved-href': url}; + var to_remove = []; + if (new_window) { + attributes['target'] = '_blank'; + } else { + to_remove.push('target'); + } + + if (this.element) { + this.element.setAttributes(attributes); + this.element.removeAttributes(to_remove); + if (this.text) { this.element.setText(this.text); } + } else { + var selection = this.editor.getSelection(); + var range = selection.getRanges(true)[0]; + + if (range.collapsed) { + //noinspection JSPotentiallyInvalidConstructorUsage + var text = new CKEDITOR.dom.text( + this.text || label || url); + range.insertNode(text); + range.selectNodeContents(text); + } + + //noinspection JSPotentiallyInvalidConstructorUsage + new CKEDITOR.style({ + type: CKEDITOR.STYLE_INLINE, + element: 'a', + attributes: attributes, + }).applyToRange(range); + + // focus dance between RTE & dialog blow up the stack in Safari + // and Chrome, so defer select() until dialog has been closed + setTimeout(function () { + range.select(); + }, 0); + } + }, + /** + * CKEDITOR.plugins.link.getSelectedLink ignores the editor's root, + * if the editor is set directly on a link it will thus not work. + */ + get_selected_link: function () { + return get_selected_link(this.editor); + }, + }); + /** * ImageDialog widget. Lets users change an image, including uploading a * new image in OpenERP or selecting the image style (if supported by -- cgit v1.2.3 From 4ae5425fb84b6ce99876da83e7138df650bac70b Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Tue, 29 Oct 2013 17:11:28 +0100 Subject: [FIX] Buggy qweb template loading bzr revid: fme@openerp.com-20131029161128-ko0ocpa0h6kziooh --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index b3c568c16fc..2019b295193 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -4,7 +4,7 @@ var website = openerp.website; // $.fn.data automatically parses value, '0'|'1' -> 0|1 - website.templates.push('/website/static/src/xml/website.editor.xml'); + website.add_template_file('/website/static/src/xml/website.editor.xml'); website.dom_ready.done(function () { var is_smartphone = $(document.body)[0].clientWidth < 767; -- cgit v1.2.3 From a87196eece2c193d2ee8e26377d9e489b466ad6a Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 30 Oct 2013 16:12:01 +0100 Subject: [REM] Removed useless feature bzr revid: fme@openerp.com-20131030151201-liz3qyn4mkv2ukc2 --- addons/website/static/src/js/website.editor.js | 41 -------------------------- 1 file changed, 41 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 9044d8f3e54..cd45f771a24 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -808,7 +808,6 @@ start: function () { return $.when( this.fetch_pages().done(this.proxy('fill_pages')), - this.fetch_menus().done(this.proxy('fill_menus')), this._super() ).done(this.proxy('bind_data')); }, @@ -833,23 +832,6 @@ '/pagenew/%s?noredirect', encodeURI(val))) .then(function (response) { self.make_link(response, false, val); - var parent_id = self.$('.add-to-menu').val(); - if (parent_id) { - return openerp.jsonRpc('/web/dataset/call_kw', 'call', { - model: 'website.menu', - method: 'create', - args: [{ - 'name': val, - 'url': response, - 'sequence': 0, // TODO: better tree widget - 'website_id': website.id, - 'parent_id': parent_id|0, - }], - kwargs: { - context: website.get_context() - }, - }); - } }); } else { this.make_link(val, this.$('input.window-new').prop('checked')); @@ -911,29 +893,6 @@ new Option(result.name, result.url); }); }, - fetch_menus: function () { - var context = website.get_context(); - return openerp.jsonRpc('/web/dataset/call_kw', 'call', { - model: 'website.menu', - method: 'get_tree', - args: [[context.website_id]], - kwargs: { - context: context - }, - }); - }, - fill_menus: function (tree) { - var self = this; - var menus = this.$('select.add-to-menu')[0]; - var process_tree = function(node) { - var name = (new Array(node.level + 1).join('|-')) + ' ' + node.name; - menus.options[menus.options.length] = new Option(name, node.id); - node.children.forEach(function (child) { - process_tree(child); - }); - }; - process_tree(tree); - }, }); website.editor.RTELinkDialog = website.editor.LinkDialog.extend({ start: function () { -- cgit v1.2.3 From 35d469d51f52d1dac7c99e8bab42d0b0a22122c5 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Thu, 31 Oct 2013 17:51:17 +0100 Subject: [FIX] Reuse website.editor.LinkDialog#bind_data() bzr revid: fme@openerp.com-20131031165117-13yo8nrfg1ru4cp8 --- addons/website/static/src/js/website.editor.js | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index cd45f771a24..4781a639b66 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -806,10 +806,13 @@ this.text = null; }, start: function () { + var self = this; return $.when( this.fetch_pages().done(this.proxy('fill_pages')), this._super() - ).done(this.proxy('bind_data')); + ).done(function () { + self.bind_data(); + }); }, save: function () { var self = this, _super = this._super.bind(this); @@ -840,17 +843,24 @@ }, make_link: function (url, new_window, label) { }, - bind_data: function () { - var href = this.element && (this.element.data( 'cke-saved-href') + bind_data: function (text, href, new_window) { + href = href || this.element && (this.element.data( 'cke-saved-href') || this.element.getAttribute('href')); if (!href) { return; } + if (new_window === undefined) { + new_window = this.element.getAttribute('target') === '_blank'; + } + if (text === undefined) { + text = this.element.getText(); + } + var match, $control; - if (match = /mailto:(.+)/.exec(href)) { + if ((match = /mailto:(.+)/.exec(href))) { $control = this.$('input.email-address').val(match[1]); } else if (href in this.pages) { $control = this.$('select.existing').val(href); - } else if (match = /\/page\/(.+)/.exec(href)) { + } else if ((match = /\/page\/(.+)/.exec(href))) { var actual_href = '/page/website.' + match[1]; if (actual_href in this.pages) { $control = this.$('select.existing').val(actual_href); @@ -862,9 +872,8 @@ this.changed($control); - this.$('input#link-text').val(this.element.getText()); - this.$('input.window-new').prop( - 'checked', this.element.getAttribute('target') === '_blank'); + this.$('input#link-text').val(text); + this.$('input.window-new').prop('checked', new_window); }, changed: function ($e) { this.$('.url-source').not($e).val(''); -- cgit v1.2.3 From f880400e43dcbf94230401b7ffbbb34344d7e579 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Mon, 4 Nov 2013 12:34:12 +0100 Subject: [IMP] Improved menu link dialog bzr revid: fme@openerp.com-20131104113412-q5d8263741pq9wna --- addons/website/static/src/js/website.editor.js | 1 + 1 file changed, 1 insertion(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 4781a639b66..45120030da3 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -821,6 +821,7 @@ if (!val || !$e[0].checkValidity()) { // FIXME: error message $e.closest('.form-group').addClass('has-error'); + $e.focus(); return; } -- cgit v1.2.3 From 5a425dda78897cc3d16477661aee8076d473229a Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Wed, 6 Nov 2013 09:38:33 +0100 Subject: [IMP] More explicit; where is the Edit button [IMP] remove "Create a free website if logged", see usertesting [IMP] Advanced view editor -> "HTML Editor" [IMP] Footer: editable zone grouped in a
    for efficient distribute branding bzr revid: fp@tinyerp.com-20131106083833-cz4xc2ast5d9ao19 --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 45120030da3..a3cad21c680 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -361,7 +361,7 @@ }); // Adding Static Menus menu.append('
  • Change Theme
  • '); - menu.append('
  • Advanced view editor
  • '); + menu.append('
  • HTML Editor
  • '); self.trigger('rte:customize_menu_ready'); } ); -- cgit v1.2.3 From 2d81712e2cfa0f87ce112a6cf540ed39680b60f3 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 6 Nov 2013 12:57:54 +0100 Subject: [FIX] Prevent dropdown closing when a contenteditable children is focused bzr revid: fme@openerp.com-20131106115754-lyt6hd8pnrfv7vfi --- addons/website/static/src/js/website.editor.js | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index a3cad21c680..734d4b0606d 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -11,6 +11,15 @@ if (!is_smartphone) { website.ready().then(website.init_editor); } + + $(document).on('hide.bs.dropdown', '.dropdown', function (ev) { + // Prevent dropdown closing when a contenteditable children is focused + if (ev.originalEvent + && $(ev.target).has(ev.originalEvent.target).length + && $(ev.originalEvent.target).is('[contenteditable]')) { + ev.preventDefault(); + } + }); }); function link_dialog(editor) { -- cgit v1.2.3 From 20899155c5881f2ca1a576b01fb68da876e6e2a9 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 6 Nov 2013 16:24:12 +0100 Subject: [IMP] during image upload, disable save button hide it and replace it with a button telling the user what we're currently doing (uploading the image). Leave the possibility of discarding the whole thing and going away though. bzr revid: xmo@openerp.com-20131106152412-eb283vghb18aafyr --- addons/website/static/src/js/website.editor.js | 3 +++ 1 file changed, 3 insertions(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 734d4b0606d..b23ccf7a9f0 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -1030,6 +1030,7 @@ }), start: function () { + this.$('.modal-footer [disabled]').text("Uploading…"); var $options = this.$('.image-style').children(); this.image_styles = $options.map(function () { return this.value; }).get(); @@ -1065,6 +1066,7 @@ }, file_selection: function () { + this.$el.addClass('nosave'); this.$('button.filepicker').removeClass('btn-danger btn-success'); var self = this; @@ -1087,6 +1089,7 @@ this.set_image(url); }, preview_image: function () { + this.$el.removeClass('nosave'); var image = this.$('input.url').val(); if (!image) { return; } -- cgit v1.2.3 From ea65573b48b35e5d99bc31410941c8363b37614e Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 7 Nov 2013 10:20:18 +0100 Subject: [ADD] image edition button v0 bzr revid: xmo@openerp.com-20131107092018-66tae9nu1kcft21g --- addons/website/static/src/js/website.editor.js | 33 ++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index b23ccf7a9f0..9f5e32ae183 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -63,6 +63,39 @@ link_dialog(editor); }, null, null, 500); + var previousSelection; + editor.on('selectionChange', function (evt) { + var selected = evt.data.path.lastElement; + if (previousSelection) { + // cleanup previous selection + $(previousSelection).next().remove(); + previousSelection = null; + } + if (!selected.is('img') + || selected.data('cke-realelement') + || selected.isReadOnly() + || selected.data('oe-model') === 'ir.ui.view') { + return; + } + + // display button + var $el = $(previousSelection = selected.$); + var $btn = $('') + .insertAfter($el) + .click(function (e) { + e.preventDefault(); + e.stopPropagation(); + image_dialog(editor); + }); + + var position = $el.position(); + $btn.css({ + position: 'absolute', + top: $el.height() / 2 + position.top - $btn.outerHeight() / 2, + left: $el.width() / 2 + position.left - $btn.outerWidth() / 2, + }); + }); + //noinspection JSValidateTypes editor.addCommand('link', { exec: function (editor) { -- cgit v1.2.3 From 14146a7b6c7b74dd2062b607c9f470ae406ec8ef Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Sat, 9 Nov 2013 09:35:50 +0100 Subject: [IMP] Show Sign In as an option bzr revid: fp@openerp.com-20131109083550-pa2u3dqvynz0qrb1 --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 9f5e32ae183..a9dabb25dee 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -403,7 +403,7 @@ }); // Adding Static Menus menu.append('
  • Change Theme
  • '); - menu.append('
  • HTML Editor
  • '); + menu.append('
  • HTML Editor
  • '); self.trigger('rte:customize_menu_ready'); } ); -- cgit v1.2.3 From bc62ae21b6b0f1aa191b951f077820109831d174 Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Sat, 9 Nov 2013 15:27:51 +0100 Subject: [IMP] Remove Bounce effet bzr revid: fp@openerp.com-20131109142751-cj9334s8avd4rzve --- addons/website/static/src/js/website.editor.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index a9dabb25dee..236be4ad68f 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -402,8 +402,9 @@ } }); // Adding Static Menus - menu.append('
  • Change Theme
  • '); - menu.append('
  • HTML Editor
  • '); + menu.append('
  • '); + menu.append('
  • HTML Editor
  • '); + menu.append('
  • Change Theme
  • '); self.trigger('rte:customize_menu_ready'); } ); -- cgit v1.2.3 From 854916ce54817dc23ed887e249586237882a94ae Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Sat, 9 Nov 2013 16:06:13 +0100 Subject: [IMP] Reorder menu bzr revid: fp@openerp.com-20131109150613-scepw4gdw7my4s76 --- addons/website/static/src/js/website.editor.js | 1 + 1 file changed, 1 insertion(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 236be4ad68f..5915ee5b359 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -405,6 +405,7 @@ menu.append('
  • '); menu.append('
  • HTML Editor
  • '); menu.append('
  • Change Theme
  • '); + menu.append('
  • Install Apps
  • '); self.trigger('rte:customize_menu_ready'); } ); -- cgit v1.2.3 From 122ddb8e310df0a4cfd597cb49cbe8863f862d8b Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 13 Nov 2013 11:18:24 +0100 Subject: [IMP] rename list_pages to enumerate_pages, add a search method and a basic non-contiguous substring match bzr revid: xmo@openerp.com-20131113101824-uqatvqokkzhvi0ei --- addons/website/static/src/js/website.editor.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 5915ee5b359..af5763b9500 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -930,9 +930,10 @@ fetch_pages: function () { return openerp.jsonRpc('/web/dataset/call_kw', 'call', { model: 'website', - method: 'list_pages', + method: 'search_pages', args: [null], kwargs: { + limit: 10, context: website.get_context() }, }); -- cgit v1.2.3 From d15a6f426ddbd75a17cfd491e127966c7a1c03c6 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 13 Nov 2013 15:39:34 +0100 Subject: [IMP] replace selection list of existing CMS pages by FAYT via select2 bzr revid: xmo@openerp.com-20131113143934-je7dusgzj15f7li0 --- addons/website/static/src/js/website.editor.js | 83 +++++++++++++------------- 1 file changed, 43 insertions(+), 40 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index af5763b9500..994876d6c05 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -2,7 +2,7 @@ 'use strict'; var website = openerp.website; - // $.fn.data automatically parses value, '0'|'1' -> 0|1 + var _t = openerp._t; website.add_template_file('/website/static/src/xml/website.editor.xml'); website.dom_ready.done(function () { @@ -828,7 +828,7 @@ website.editor.LinkDialog = website.editor.Dialog.extend({ template: 'website.editor.dialog.link', events: _.extend({}, website.editor.Dialog.prototype.events, { - 'change .url-source': function (e) { this.changed($(e.target)); }, + 'change :input.url-source': function (e) { this.changed($(e.target)); }, 'mousedown': function (e) { var $target = $(e.target).closest('.list-group-item'); if (!$target.length || $target.hasClass('active')) { @@ -836,7 +836,7 @@ return; } - this.changed($target.find('.url-source')); + this.changed($target.find('.url-source').filter(':input')); }, 'click button.remove': 'remove_link', 'change input#link-text': function (e) { @@ -846,21 +846,36 @@ init: function (editor) { this._super(editor); // url -> name mapping for existing pages - this.pages = Object.create(null); this.text = null; }, start: function () { var self = this; - return $.when( - this.fetch_pages().done(this.proxy('fill_pages')), - this._super() - ).done(function () { - self.bind_data(); + this.$('#link-page').select2({ + minimumInputLength: 3, + placeholder: _t("New or existing page"), + query: function (q) { + // FIXME: out-of-order, abort + self.fetch_pages(q.term).then(function (results) { + var rs = _.map(results, function (r) { + return { id: r.url, text: r.name, }; + }); + rs.push({ + create: true, + id: q.term, + text: "Create " + q.term, + }); + q.callback({ + more: false, + results: rs + }); + }); + }, }); + return this._super().then(this.proxy('bind_data')); }, save: function () { var self = this, _super = this._super.bind(this); - var $e = this.$('.list-group-item.active .url-source'); + var $e = this.$('.list-group-item.active .url-source').filter(':input'); var val = $e.val(); if (!val || !$e[0].checkValidity()) { // FIXME: error message @@ -872,15 +887,18 @@ var done = $.when(); if ($e.hasClass('email-address')) { this.make_link('mailto:' + val, false, val); - } else if ($e.hasClass('existing')) { - self.make_link(val, false, this.pages[val]); - } else if ($e.hasClass('pages')) { - // Create the page, get the URL back - done = $.get(_.str.sprintf( - '/pagenew/%s?noredirect', encodeURI(val))) - .then(function (response) { - self.make_link(response, false, val); - }); + } else if ($e.hasClass('page')) { + var data = $e.select2('data'); + if (!data.create) { + self.make_link(data.id, false, data.text); + } else { + // Create the page, get the URL back + done = $.get(_.str.sprintf( + '/pagenew/%s?noredirect', encodeURI(data.id))) + .then(function (response) { + self.make_link(response, false, data.id); + }); + } } else { this.make_link(val, this.$('input.window-new').prop('checked')); } @@ -903,13 +921,6 @@ var match, $control; if ((match = /mailto:(.+)/.exec(href))) { $control = this.$('input.email-address').val(match[1]); - } else if (href in this.pages) { - $control = this.$('select.existing').val(href); - } else if ((match = /\/page\/(.+)/.exec(href))) { - var actual_href = '/page/website.' + match[1]; - if (actual_href in this.pages) { - $control = this.$('select.existing').val(actual_href); - } } if (!$control) { $control = this.$('input.url').val(href); @@ -921,33 +932,25 @@ this.$('input.window-new').prop('checked', new_window); }, changed: function ($e) { - this.$('.url-source').not($e).val(''); + this.$('.url-source').filter(':input').not($e).val('') + .filter(function () { return !!$(this).data('select2'); }) + .select2('data', null); $e.closest('.list-group-item') .addClass('active') .siblings().removeClass('active') .addBack().removeClass('has-error'); }, - fetch_pages: function () { + fetch_pages: function (term) { return openerp.jsonRpc('/web/dataset/call_kw', 'call', { model: 'website', method: 'search_pages', - args: [null], + args: [null, term], kwargs: { - limit: 10, + limit: 9, context: website.get_context() }, }); }, - fill_pages: function (results) { - var self = this; - var pages = this.$('select.existing')[0]; - _(results).each(function (result) { - self.pages[result.url] = result.name; - - pages.options[pages.options.length] = - new Option(result.name, result.url); - }); - }, }); website.editor.RTELinkDialog = website.editor.LinkDialog.extend({ start: function () { -- cgit v1.2.3 From 837aa436e5b31a06a8fab1a7bfcfdf97ab877f2b Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 13 Nov 2013 16:18:32 +0100 Subject: [IMP] abort FAYT requests when the next one comes in bzr revid: xmo@openerp.com-20131113151832-ym4hvpyhn5t7ocxs --- addons/website/static/src/js/website.editor.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 994876d6c05..245abd9960e 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -845,8 +845,9 @@ }), init: function (editor) { this._super(editor); - // url -> name mapping for existing pages this.text = null; + // Store last-performed request to be able to cancel/abort it. + this.req = null; }, start: function () { var self = this; @@ -941,7 +942,9 @@ .addBack().removeClass('has-error'); }, fetch_pages: function (term) { - return openerp.jsonRpc('/web/dataset/call_kw', 'call', { + var self = this; + if (this.req) { this.req.abort(); } + return this.req = openerp.jsonRpc('/web/dataset/call_kw', 'call', { model: 'website', method: 'search_pages', args: [null, term], @@ -949,6 +952,9 @@ limit: 9, context: website.get_context() }, + }).done(function () { + // request completed successfully -> unstore it + self.req = null; }); }, }); -- cgit v1.2.3 From ca0537ad4ae41065a43d1e8d549a63e8393c2d27 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 13 Nov 2013 16:57:04 +0100 Subject: [FIX] menu entry dialog to work correctly with select2 page picker bzr revid: xmo@openerp.com-20131113155704-7l0d87va0860h7dx --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 245abd9960e..22367e24d47 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -863,7 +863,7 @@ rs.push({ create: true, id: q.term, - text: "Create " + q.term, + text: _.str.sprintf(_t("Create page '%s'"), q.term), }); q.callback({ more: false, -- cgit v1.2.3 From 7598bcdb98795d7e95a6a7b3eacdf018766f1328 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 13 Nov 2013 18:14:38 +0100 Subject: [ADD] Content menu links splitted per modules TODO: website.prompt() should be finished for Add a blog post link Added @id=editable_scripts_hook in layout template so modules can easly add *.editor.js files bzr revid: fme@openerp.com-20131113171438-3l0wo08ta5vsulq3 --- addons/website/static/src/js/website.editor.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 5915ee5b359..a617f712976 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -12,6 +12,16 @@ website.ready().then(website.init_editor); } + $(document).on('click', 'a.js_link2post', function (ev) { + ev.preventDefault(); + var form = document.createElement('form'); + form.action = this.pathname; // restrict to same origin + form.method = 'POST'; + // TODO: support this.search as form input fields + $(this).append(form); + form.submit(); + }); + $(document).on('hide.bs.dropdown', '.dropdown', function (ev) { // Prevent dropdown closing when a contenteditable children is focused if (ev.originalEvent @@ -383,6 +393,7 @@ 'click button[data-action=edit]': 'edit', 'click button[data-action=save]': 'save', 'click button[data-action=cancel]': 'cancel', + 'click a[data-action=new_page]': 'new_page', }, container: 'body', customize_setup: function() { @@ -531,6 +542,12 @@ cancel: function () { website.reload(); }, + new_page: function (ev) { + ev.preventDefault(); + website.prompt('Create a new page', 'Page name').then(function (val) { + document.location = '/pagenew/' + encodeURI(val); + }); + }, }); var blocks_selector = _.keys(CKEDITOR.dtd.$block).join(','); -- cgit v1.2.3 From 95f63af9921b4f48ba7b9e2a656418b916aa2dd8 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Thu, 14 Nov 2013 10:32:14 +0100 Subject: [IMP] Improved openerp.website.prompt() and write documentation Yeah ! You read me ! I (fme) wrote documentation ! Yeaaaaaaaaaaaaah !!! bzr revid: fme@openerp.com-20131114093214-isjmwwbzsj3ahr61 --- addons/website/static/src/js/website.editor.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index a617f712976..8dfa2fe8ad3 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -544,7 +544,10 @@ }, new_page: function (ev) { ev.preventDefault(); - website.prompt('Create a new page', 'Page name').then(function (val) { + website.prompt({ + window_title: "Create a new page", + input: "Page name", + }).then(function (val) { document.location = '/pagenew/' + encodeURI(val); }); }, -- cgit v1.2.3 From 85265aefb9959bf148c499b6879afd8c277a0aa1 Mon Sep 17 00:00:00 2001 From: Fabien Pinckaers Date: Thu, 14 Nov 2013 22:28:56 +0100 Subject: [IMP] layout of website.prompt bzr revid: fp@openerp.com-20131114212856-ff42xtka5dlv8c8c --- addons/website/static/src/js/website.editor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 8dfa2fe8ad3..74cf6ab81c0 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -545,8 +545,8 @@ new_page: function (ev) { ev.preventDefault(); website.prompt({ - window_title: "Create a new page", - input: "Page name", + window_title: "New Page", + input: "Page Title", }).then(function (val) { document.location = '/pagenew/' + encodeURI(val); }); -- cgit v1.2.3 From 1b77b7646052bdb59e67a3f260d6c2c528b8f1e0 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Mon, 18 Nov 2013 13:49:58 +0100 Subject: [ADD] breadcrumb return_url to Website bzr revid: fme@openerp.com-20131118124958-j1t85mywopoawtk7 --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 74cf6ab81c0..27dd8c8e2f4 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -416,7 +416,7 @@ menu.append('
  • '); menu.append('
  • HTML Editor
  • '); menu.append('
  • Change Theme
  • '); - menu.append('
  • Install Apps
  • '); + menu.append('
  • Install Apps
  • '); self.trigger('rte:customize_menu_ready'); } ); -- cgit v1.2.3 From bb0badbf404102f4566e92b50be18c34489d856c Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Tue, 19 Nov 2013 12:06:12 +0100 Subject: [IMP] Simplify js_link2post event bzr revid: fme@openerp.com-20131119110612-uc4j1l6xexrt9fyt --- addons/website/static/src/js/website.editor.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 530d8470af8..1fe4149e78d 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -14,12 +14,7 @@ $(document).on('click', 'a.js_link2post', function (ev) { ev.preventDefault(); - var form = document.createElement('form'); - form.action = this.pathname; // restrict to same origin - form.method = 'POST'; - // TODO: support this.search as form input fields - $(this).append(form); - form.submit(); + website.form(this.pathname, 'POST'); }); $(document).on('hide.bs.dropdown', '.dropdown', function (ev) { -- cgit v1.2.3 From ba2ee4e2872b1cecbb9f066700339946c062e89a Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 19 Nov 2013 13:55:20 +0100 Subject: [FIX] cleanup image edition button on editor save bzr revid: xmo@openerp.com-20131119125520-qpts34qbx1oofdc1 --- addons/website/static/src/js/website.editor.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 1fe4149e78d..2281b6fd30d 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -85,7 +85,7 @@ // display button var $el = $(previousSelection = selected.$); - var $btn = $('') + var $btn = $('') .insertAfter($el) .click(function (e) { e.preventDefault(); @@ -100,6 +100,11 @@ left: $el.width() / 2 + position.left - $btn.outerWidth() / 2, }); }); + editor.on('destroy', function (evt) { + if (previousSelection) { + $('.image-edit-button').remove(); + } + }); //noinspection JSValidateTypes editor.addCommand('link', { -- cgit v1.2.3 From b6be7b87c646f83b54c69cc4b0217043cb7b6956 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 19 Nov 2013 14:11:13 +0100 Subject: [IMP] add img-responsive to images generated via dialog avoids having the image end up larger than its container bzr revid: xmo@openerp.com-20131119131113-9010p4tubk1yz10s --- addons/website/static/src/js/website.editor.js | 1 + 1 file changed, 1 insertion(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 2281b6fd30d..1a982fb7d30 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -1195,6 +1195,7 @@ if (!(element = this.element)) { element = editor.document.createElement('img'); element.addClass('img'); + element.addClass('img-responsive'); // 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 => -- cgit v1.2.3 From 8054696a43b968164b94575a6c97a8d69a16aa08 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 19 Nov 2013 14:57:04 +0100 Subject: [FIX] website editor for IE bzr revid: chm@openerp.com-20131119135704-rnva3skoh55h3eti --- addons/website/static/src/js/website.editor.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 1a982fb7d30..0dacbf0478e 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -694,9 +694,11 @@ self.setup_editables(root); - // disable firefox's broken table resizing thing - document.execCommand("enableObjectResizing", false, "false"); - document.execCommand("enableInlineTableEditing", false, "false"); + try { + // disable firefox's broken table resizing thing + document.execCommand("enableObjectResizing", false, "false"); + document.execCommand("enableInlineTableEditing", false, "false"); + } catch (e) {} self.trigger('rte:ready'); def.resolve(); -- cgit v1.2.3 From 5e7a8a957c449e857b0fd3718331e7b094618732 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 19 Nov 2013 15:32:59 +0100 Subject: [IMP] website editor: better rendering of the popover when failure write raise by except_osv. bzr revid: chm@openerp.com-20131119143259-vm7o3vq79358h56w --- addons/website/static/src/js/website.editor.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 0dacbf0478e..30af6fdee04 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -513,16 +513,23 @@ if (!_.isArray(failed)) { failed = [failed]; } _(failed).each(function (failure) { + var html = failure.error.exception_type === "except_osv"; + if (html) { + var msg = $("
    ").text(failure.error.message).html(); + var data = msg.substring(3,msg.length-2).split(/', u'/); + failure.error.message = '' + data[0] + '
    ' + data[1]; + } $(root).find('.' + failure.id) .removeClass(failure.id) .popover({ + html: html, trigger: 'hover', content: failure.error.message, placement: 'auto top', }) // Force-show popovers so users will notice them. .popover('show'); - }) + }); }); }); }, -- cgit v1.2.3 From fd02a389e99bca1c8b3773915e94c8a49ac84449 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 20 Nov 2013 10:11:47 +0100 Subject: [REM] apparently unnecessary icons bzr revid: xmo@openerp.com-20131120091147-4vshzojq6mwhvice --- addons/website/static/src/js/website.editor.js | 2 -- 1 file changed, 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 30af6fdee04..895bc8864c6 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -129,13 +129,11 @@ label: 'Link', command: 'link', toolbar: 'links,10', - icon: '/website/static/lib/ckeditor/plugins/link/icons/link.png', }); editor.ui.addButton('Image', { label: 'Image', command: 'image', toolbar: 'insert,10', - icon: '/website/static/lib/ckeditor/plugins/image/icons/image.png', }); editor.setKeystroke(CKEDITOR.CTRL + 76 /*L*/, 'link'); -- cgit v1.2.3 From 6b10be15b245e05adac2a54f0321305c6d5076d9 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 20 Nov 2013 12:52:50 +0100 Subject: [IMP] website snippet: add group for styles snippets, add custom picture with style snippet, mouseover and mouseout preview, fix dark css class in demo data bzr revid: chm@openerp.com-20131120115250-etqv5ofqguze0zsj --- addons/website/static/src/js/website.editor.js | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 895bc8864c6..feb8e403c54 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -834,6 +834,7 @@ events: { 'hidden.bs.modal': 'destroy', 'click button.save': 'save', + 'click button[data-dismiss="modal"]': 'cancel', }, init: function (editor) { this._super(); @@ -847,6 +848,8 @@ save: function () { this.close(); }, + cancel: function () { + }, close: function () { this.$el.modal('hide'); }, @@ -1127,6 +1130,9 @@ }); return this._super(); }, + cancel: function () { + this.trigger('cancel'); + }, /** * Sets the provided image url as the dialog's value-to-save and -- cgit v1.2.3 From fee8cb0fff1773648ea3c246a14470d92840686b Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 21 Nov 2013 12:07:48 +0100 Subject: [FIX] reimplement [Edit] button on images Button implementation turned out to be crap: * Didn't work at all in Firefox (!) * Unreliable in webkit, some types of image selection wouldn't correctly activate the button -> * changed RTEImageDialog to take an (optional) image element, used as the "source element" if provided. This allows greater reliability for events which may leave selection in debatable or variable (across browsers) state * setup and teardown button on hover, using selection triggered issues with oe_overlay thing where e.g. the first click on the button would work but the second one would not (it'd be intercepted by the overlay as far as I can tell). This also saves a click for user, they will see the [Edit] button immediately when putting the cursor over the image. bzr revid: xmo@openerp.com-20131121110748-s5e2ne3etpzwi2a6 --- addons/website/static/src/js/website.editor.js | 60 +++++++++++++++----------- 1 file changed, 34 insertions(+), 26 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index feb8e403c54..e8544221b00 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -30,8 +30,8 @@ function link_dialog(editor) { return new website.editor.RTELinkDialog(editor).appendTo(document.body); } - function image_dialog(editor) { - return new website.editor.RTEImageDialog(editor).appendTo(document.body); + function image_dialog(editor, image) { + return new website.editor.RTEImageDialog(editor, image).appendTo(document.body); } // only enable editors manually @@ -53,7 +53,7 @@ && !element.data('cke-realelement') && !element.isReadOnly() && (element.data('oe-model') !== 'ir.ui.view')) { - image_dialog(editor); + image_dialog(editor, element); return; } @@ -69,13 +69,9 @@ }, null, null, 500); var previousSelection; - editor.on('selectionChange', function (evt) { - var selected = evt.data.path.lastElement; - if (previousSelection) { - // cleanup previous selection - $(previousSelection).next().remove(); - previousSelection = null; - } + $(editor.element.$).on('mouseenter', 'img', function () { + if (previousSelection) { return; } + var selected = new CKEDITOR.dom.element(this); if (!selected.is('img') || selected.data('cke-realelement') || selected.isReadOnly() @@ -84,13 +80,13 @@ } // display button - var $el = $(previousSelection = selected.$); + var $el = $((previousSelection = selected).$); var $btn = $('') .insertAfter($el) .click(function (e) { e.preventDefault(); e.stopPropagation(); - image_dialog(editor); + image_dialog(editor, selected); }); var position = $el.position(); @@ -99,6 +95,14 @@ top: $el.height() / 2 + position.top - $btn.outerHeight() / 2, left: $el.width() / 2 + position.left - $btn.outerWidth() / 2, }); + }).on('mouseleave', 'img', function (e) { + var $button = $(previousSelection.$).next('button'); + $button.css('visibility', 'hidden'); + var el = document.elementFromPoint(e.clientX, e.clientY); + $button.css('visibility', ''); + if (el === this) { return; } + $button.remove(); + previousSelection = null; }); editor.on('destroy', function (evt) { if (previousSelection) { @@ -1182,26 +1186,30 @@ }, }); website.editor.RTEImageDialog = website.editor.ImageDialog.extend({ - init: function () { - this._super.apply(this, arguments); + init: function (editor, image) { + this._super(editor); + + this.element = image; this.on('start', this, this.proxy('started')); this.on('save', this, this.proxy('saved')); }, started: function (holder) { - var selection = this.editor.getSelection(); - var el = selection && selection.getSelectedElement(); - this.element = null; - - if (el && el.is('img')) { - this.element = el; - _(this.image_styles).each(function (style) { - if (el.hasClass(style)) { - holder.style = style; - } - }); - holder.url = el.getAttribute('src'); + if (!this.element) { + var selection = this.editor.getSelection(); + this.element = selection && selection.getSelectedElement(); } + + var el = this.element; + if (!el || !el.is('img')) { + return; + } + _(this.image_styles).each(function (style) { + if (el.hasClass(style)) { + holder.style = style; + } + }); + holder.url = el.getAttribute('src'); }, saved: function (data) { var element, editor = this.editor; -- cgit v1.2.3 From 32147fbffc3d3781fb571f3c8a6de3ced22316fb Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 21 Nov 2013 16:45:01 +0100 Subject: [REM] bootstrap link configuration combo, it has served its testing purposes bzr revid: xmo@openerp.com-20131121154501-vrs26caromm6ebgb --- addons/website/static/src/js/website.editor.js | 153 +------------------------ 1 file changed, 1 insertion(+), 152 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index e8544221b00..ae673dd811b 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -228,157 +228,6 @@ } }); - CKEDITOR.plugins.add('bootstrapcombo', { - requires: 'richcombo', - - init: function (editor) { - var config = editor.config; - - editor.ui.addRichCombo('BootstrapLinkCombo', { - // default title - label: "Links", - // hover - title: "Link styling", - toolbar: 'styles,10', - allowedContent: ['a'], - - panel: { - css: [ - '/website/static/lib/bootstrap/css/bootstrap.css', - CKEDITOR.skin.getPath( 'editor' ) - ].concat( config.contentsCss ), - multiSelect: true, - }, - - types: { - 'basic': 'btn-default', - 'primary': 'btn-primary', - 'success': 'btn-success', - 'info': 'btn-info', - 'warning': 'btn-warning', - 'danger': 'btn-danger', - }, - - sizes: { - 'large': 'btn-lg', - 'default': '', - 'small': 'btn-sm', - 'extra small': 'btn-xs', - }, - - init: function () { - this.add('', 'Reset'); - this.startGroup("Types"); - for(var type in this.types) { - if (!this.types.hasOwnProperty(type)) { continue; } - var cls = this.types[type]; - var el = _.str.sprintf( - '%s', - cls, type); - this.add(type, el); - } - this.startGroup("Sizes"); - for (var size in this.sizes) { - if (!this.sizes.hasOwnProperty(size)) { continue; } - cls = this.sizes[size]; - - el = _.str.sprintf( - '%s', - cls, size); - this.add(size, el); - } - this.commit(); - }, - onRender: function () { - var self = this; - editor.on('selectionChange', function (e) { - var path = e.data.path, el; - - if (!(el = path.contains('a'))) { - self.element = null; - self.disable(); - return; - } - - self.enable(); - // This is crap, but getting the currently selected - // element from within onOpen absolutely does not - // work, so store the "current" element in the - // widget instead - self.element = el; - }); - setTimeout(function () { - // Because I can't find any normal hook where the - // bloody button's bloody element is available - self.disable(); - }, 0); - }, - onOpen: function () { - this.showAll(); - this.unmarkAll(); - - for(var val in this.types) { - if (!this.types.hasOwnProperty(val)) { continue; } - var cls = this.types[val]; - if (!this.element.hasClass(cls)) { continue; } - - this.mark(val); - break; - } - - var found; - for(val in this.sizes) { - if (!this.sizes.hasOwnProperty(val)) { continue; } - cls = this.sizes[val]; - if (!cls || !this.element.hasClass(cls)) { continue; } - - found = true; - this.mark(val); - break; - } - if (!found && this.element.hasClass('btn')) { - this.mark('default'); - } - }, - onClick: function (value) { - editor.focus(); - editor.fire('saveShapshot'); - - // basic btn setup - var el = this.element; - if (!el.hasClass('btn')) { - el.addClass('btn'); - el.addClass('btn-default'); - } - - if (!value) { - this.setClass(this.types); - this.setClass(this.sizes); - el.removeClass('btn'); - } else if (value in this.types) { - this.setClass(this.types, value); - } else if (value in this.sizes) { - this.setClass(this.sizes, value); - } - - editor.fire('saveShapshot'); - }, - setClass: function (classMap, value) { - var element = this.element; - _(classMap).each(function (cls) { - if (!cls) { return; } - element.removeClass(cls); - }.bind(this)); - - var cls = classMap[value]; - if (cls) { - element.addClass(cls); - } - } - }); - }, - }); - var editor = new website.EditorBar(); var $body = $(document.body); editor.prependTo($body).then(function () { @@ -814,7 +663,7 @@ "Image", "TableButton" ]},{ name: 'styles', items: [ - "Styles", "BootstrapLinkCombo" + "Styles" ]} ], // styles dropdown in toolbar -- cgit v1.2.3 From 233e460b5222025ae96d3a3269ce5153392e8160 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 21 Nov 2013 17:05:16 +0100 Subject: [FIX] forgot to tell ckeditor not to load removed bootstrap combo plugin bzr revid: xmo@openerp.com-20131121160516-a29x498ode34p1ml --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index ae673dd811b..d1cb5781eba 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -641,7 +641,7 @@ fillEmptyBlocks: false, filebrowserImageUploadUrl: "/website/attach", // Support for sharedSpaces in 4.x - extraPlugins: 'sharedspace,customdialogs,tablebutton,oeref,bootstrapcombo', + extraPlugins: 'sharedspace,customdialogs,tablebutton,oeref', // Place toolbar in controlled location sharedSpaces: { top: 'oe_rte_toolbar' }, toolbar: [{ -- cgit v1.2.3 From 1f2a40e3f78277a90b357b1e26d195bd548bec28 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 22 Nov 2013 11:11:54 +0100 Subject: [FIX] horizontal centering of edition button on images centered with margin: 0 auto in webkit-based browsers bzr revid: xmo@openerp.com-20131122101154-fsae9uz33smy2ja9 --- addons/website/static/src/js/website.editor.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index d1cb5781eba..aedd5b011d9 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -90,10 +90,18 @@ }); var position = $el.position(); + // http://bugs.jquery.com/ticket/5445#comment:6 + // if the image has margin: x auto for centering, FF & IE + // will report top/left as the "correct" value and + // marginTop/marginLeft at "0px", webkit browsers will + // report top/left as 0-ish and set marginTop and + // marginLeft + var image_top = position.top + parseInt($el.css('marginTop'), 10); + var image_left = position.left + parseInt($el.css('marginLeft'), 10); $btn.css({ position: 'absolute', - top: $el.height() / 2 + position.top - $btn.outerHeight() / 2, - left: $el.width() / 2 + position.left - $btn.outerWidth() / 2, + top: $el.height() / 2 + image_top - $btn.outerHeight() / 2, + left: $el.width() / 2 + image_left - $btn.outerWidth() / 2, }); }).on('mouseleave', 'img', function (e) { var $button = $(previousSelection.$).next('button'); -- cgit v1.2.3 From 264fe7d98bb1fa28fde30cbe823e51b90d5e8eed Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 22 Nov 2013 11:23:22 +0100 Subject: [ADD] small transparency when hovering editable images, so [Edit] button stands out more bzr revid: xmo@openerp.com-20131122102322-s776o3f80bku3f4a --- addons/website/static/src/js/website.editor.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index aedd5b011d9..cce7b09644a 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -103,19 +103,23 @@ top: $el.height() / 2 + image_top - $btn.outerHeight() / 2, left: $el.width() / 2 + image_left - $btn.outerWidth() / 2, }); + $el.css('opacity', 0.75); }).on('mouseleave', 'img', function (e) { - var $button = $(previousSelection.$).next('button'); + var $previous = $(previousSelection.$); + var $button = $previous.next('button'); $button.css('visibility', 'hidden'); var el = document.elementFromPoint(e.clientX, e.clientY); $button.css('visibility', ''); if (el === this) { return; } $button.remove(); + $previous.css('opacity', ''); previousSelection = null; }); editor.on('destroy', function (evt) { - if (previousSelection) { - $('.image-edit-button').remove(); - } + if (!previousSelection) { return; } + $('.image-edit-button') + .prev().css('opacity', '').end() + .remove(); }); //noinspection JSValidateTypes -- cgit v1.2.3 From 53793703de74c9745429e213517caafc8dac6853 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 22 Nov 2013 16:11:24 +0100 Subject: [ADD] dropdown for link style bzr revid: xmo@openerp.com-20131122151124-1n7cnwldm3ej6wz7 --- addons/website/static/src/js/website.editor.js | 152 ++++++++++++++++++++++++- 1 file changed, 150 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index cce7b09644a..cee4409240d 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -218,6 +218,154 @@ } }); + CKEDITOR.plugins.add('linkstyle', { + requires: 'panelbutton,floatpanel', + init: function (editor) { + var label = "Link Style"; + + editor.ui.add('LinkStyle', CKEDITOR.UI_PANELBUTTON, { + label: label, + title: label, + icon: '/website/static/src/img/bglink.png', + modes: { wysiwyg: true }, + editorFocus: true, + panel: { + css: '/website/static/lib/bootstrap/css/bootstrap.css', + attributes: { 'role': 'listbox', 'aria-label': label }, + }, + + types: { + 'btn-default': _t("Basic"), + 'btn-primary': _t("Primary"), + 'btn-success': _t("Success"), + 'btn-info': _t("Info"), + 'btn-warning': _t("Warning"), + 'btn-danger': _t("Danger"), + }, + sizes: { + 'btn-xs': _t("Extra Small"), + 'btn-sm': _t("Small"), + '': _t("Default"), + 'btn-lg': _t("Large") + }, + + onRender: function () { + var self = this; + editor.on('selectionChange', function (e) { + var path = e.data.path, el; + + if (!(e = path.contains('a')) || e.isReadOnly()) { + self.disable(); + return; + } + + self.enable(); + }); + // no hook where button is available, so wait + // "some time" after render. + setTimeout(function () { + self.disable(); + }, 0) + }, + enable: function () { + this.setState(CKEDITOR.TRISTATE_OFF); + }, + disable: function () { + this.setState(CKEDITOR.TRISTATE_DISABLED); + }, + + onOpen: function () { + var link = get_selected_link(editor); + var id = this._.id; + var block = this._.panel._.panel._.blocks[id]; + var $root = $(block.element.$); + $root.find('button').removeClass('active').removeProp('disabled'); + + // enable buttons matching link state + for (var type in this.types) { + if (!this.types.hasOwnProperty(type)) { continue; } + if (!link.hasClass(type)) { continue; } + + $root.find('button[data-type=types].' + type) + .addClass('active'); + } + var found; + for (var size in this.sizes) { + if (!this.sizes.hasOwnProperty(size)) { continue; } + if (!size || !link.hasClass(size)) { continue; } + found = true; + $root.find('button[data-type=sizes].' + size) + .addClass('active'); + } + if (!found && link.hasClass('btn')) { + $root.find('button[data-type="sizes"][data-set-class=""]') + .addClass('active'); + } + }, + + onBlock: function (panel, block) { + var self = this; + block.autoSize = true; + + var html = ['
    ']; + html.push('
    '); + _(this.types).each(function (label, key) { + html.push(_.str.sprintf( + '', + key, key, label)); + }); + html.push('
    '); + html.push('
    '); + _(this.sizes).each(function (label, key) { + html.push(_.str.sprintf( + '', + key, key, label)); + }); + html.push('
    '); + html.push(''); + html.push('
    '); + + block.element.setHtml(html.join(' ')); + var $panel = $(block.element.$); + $panel.on('click', 'button', function () { + self.clicked(this); + }); + }, + clicked: function (button) { + editor.focus(); + editor.fire('saveSnapshot'); + + var $button = $(button), + $link = $(get_selected_link(editor).$); + if (!$link.hasClass('btn')) { + $link.addClass('btn btn-default'); + } + switch($button.data('type')) { + case 'reset': + $link.removeClass('btn') + .removeClass(_.keys(this.types).join(' ')) + .removeClass(_.keys(this.sizes).join(' ')); + break; + case 'types': + $link.removeClass(_.keys(this.types).join(' ')) + .addClass($button.data('set-class')); + break; + case 'sizes': + $link.removeClass(_.keys(this.sizes).join(' ')) + .addClass($button.data('set-class')); + } + this._.panel.hide(); + + editor.fire('saveSnapshot'); + }, + + }); + } + }); + CKEDITOR.plugins.add('oeref', { requires: 'widget', @@ -653,7 +801,7 @@ fillEmptyBlocks: false, filebrowserImageUploadUrl: "/website/attach", // Support for sharedSpaces in 4.x - extraPlugins: 'sharedspace,customdialogs,tablebutton,oeref', + extraPlugins: 'sharedspace,customdialogs,tablebutton,oeref,linkstyle', // Place toolbar in controlled location sharedSpaces: { top: 'oe_rte_toolbar' }, toolbar: [{ @@ -665,7 +813,7 @@ "Superscript", "TextColor", "BGColor", "RemoveFormat" ]},{ name: 'span', items: [ - "Link", "Blockquote", "BulletedList", + "Link", "LinkStyle", "Blockquote", "BulletedList", "NumberedList", "Indent", "Outdent" ]},{ name: 'justify', items: [ -- cgit v1.2.3 From 52b8226a83d87fd23cf4bd6d6d720edf4975014c Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 25 Nov 2013 11:18:19 +0100 Subject: [FIX] on completion error, tell user there are no results not sure whether and how an error could/should be reported to the user. For now, it's automatically logged into the console. bzr revid: xmo@openerp.com-20131125101819-u2akhr16bd5kcsmf --- addons/website/static/src/js/website.editor.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index cee4409240d..adb60c7f362 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -912,6 +912,8 @@ more: false, results: rs }); + }, function () { + q.callback({more: false, results: []}); }); }, }); @@ -995,8 +997,8 @@ limit: 9, context: website.get_context() }, - }).done(function () { - // request completed successfully -> unstore it + }).always(function () { + // request completed -> unstore it self.req = null; }); }, -- cgit v1.2.3 From 4679bfd283d0af50233afc9e1c6ecd18e7d663cf Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 25 Nov 2013 11:22:28 +0100 Subject: [IMP] lower completion trigger threshold to 1 could be removed entirely, but not sure users would realize there are plenty more urls to look for... bzr revid: xmo@openerp.com-20131125102228-igkzfsh50y1ytwef --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index adb60c7f362..339aedcc27c 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -895,7 +895,7 @@ start: function () { var self = this; this.$('#link-page').select2({ - minimumInputLength: 3, + minimumInputLength: 1, placeholder: _t("New or existing page"), query: function (q) { // FIXME: out-of-order, abort -- cgit v1.2.3 From b05db3495c36ec5e46158f3bc3f7911280bc4fb7 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 25 Nov 2013 13:05:48 +0100 Subject: [IMP] in crawler testing, indicate at which page the failed url was found bzr revid: xmo@openerp.com-20131125120548-0s7xnhszd48e1u9v --- addons/website/static/src/js/website.editor.js | 1 - 1 file changed, 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 339aedcc27c..f3344c36e78 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -898,7 +898,6 @@ minimumInputLength: 1, placeholder: _t("New or existing page"), query: function (q) { - // FIXME: out-of-order, abort self.fetch_pages(q.term).then(function (results) { var rs = _.map(results, function (r) { return { id: r.url, text: r.name, }; -- cgit v1.2.3 From 854e45395882efe0968c1d50d3d1a4761627865f Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 26 Nov 2013 10:23:39 +0100 Subject: [CHG] remove opacity changes on image hover bzr revid: xmo@openerp.com-20131126092339-7wqx54t8iuvy8e9a --- addons/website/static/src/js/website.editor.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index f3344c36e78..6d6094a5d65 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -103,7 +103,6 @@ top: $el.height() / 2 + image_top - $btn.outerHeight() / 2, left: $el.width() / 2 + image_left - $btn.outerWidth() / 2, }); - $el.css('opacity', 0.75); }).on('mouseleave', 'img', function (e) { var $previous = $(previousSelection.$); var $button = $previous.next('button'); @@ -112,14 +111,11 @@ $button.css('visibility', ''); if (el === this) { return; } $button.remove(); - $previous.css('opacity', ''); previousSelection = null; }); - editor.on('destroy', function (evt) { + editor.on('destroy', function () { if (!previousSelection) { return; } - $('.image-edit-button') - .prev().css('opacity', '').end() - .remove(); + $('.image-edit-button').remove(); }); //noinspection JSValidateTypes -- cgit v1.2.3 From 3731d33852046e4b56d9d61cdf93c90f1ec10892 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 26 Nov 2013 13:47:39 +0100 Subject: [FIX] don't perform page creation when no name was provided bzr revid: xmo@openerp.com-20131126124739-djk6nbifyo087bmz --- addons/website/static/src/js/website.editor.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 6d6094a5d65..52b3f19e1ba 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -562,7 +562,9 @@ window_title: "New Page", input: "Page Title", }).then(function (val) { - document.location = '/pagenew/' + encodeURI(val); + if (val) { + document.location = '/pagenew/' + encodeURI(val); + } }); }, }); -- cgit v1.2.3 From 44af6d1e09aa3bec6967ac3eb4e67b3e9215fb08 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 26 Nov 2013 17:01:48 +0100 Subject: [IMP] significantly improve handling of trying to create a new page which already exists # Through the menu Rather than output a generic error (500 due to an IntegrityError), return a templated 409 letting the user either visit the page-which-already-exists-with-the-name-he'd-picked or open the page creation dialog again for a second round. An alternative would be to promote the website.prompt use to full-blown dialog as a result of selecting "New Page" and handle the "page already exists" case without even closing the dialog. # Through the link dialog Added an RPC call to check if a page already exists (essentially a cheaper version of opening /page/whatever and checking whether it's a 200 over JSON-RPC), if the page matching the completion term already exists, do *not* add the choice of creating the page, only provide completions from existing pages. bzr revid: xmo@openerp.com-20131126160148-wrk4zvz9istscwa0 --- addons/website/static/src/js/website.editor.js | 52 +++++++++++++++++--------- 1 file changed, 34 insertions(+), 18 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 52b3f19e1ba..c50ad392887 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -888,7 +888,8 @@ this._super(editor); this.text = null; // Store last-performed request to be able to cancel/abort it. - this.req = null; + this.page_exists_req = null; + this.search_pages_req = null; }, start: function () { var self = this; @@ -896,15 +897,20 @@ minimumInputLength: 1, placeholder: _t("New or existing page"), query: function (q) { - self.fetch_pages(q.term).then(function (results) { + $.when( + self.page_exists(q.term), + self.fetch_pages(q.term) + ).then(function (exists, results) { var rs = _.map(results, function (r) { return { id: r.url, text: r.name, }; }); - rs.push({ - create: true, - id: q.term, - text: _.str.sprintf(_t("Create page '%s'"), q.term), - }); + if (!exists) { + rs.push({ + create: true, + id: q.term, + text: _.str.sprintf(_t("Create page '%s'"), q.term), + }); + } q.callback({ more: false, results: rs @@ -983,20 +989,30 @@ .siblings().removeClass('active') .addBack().removeClass('has-error'); }, - fetch_pages: function (term) { + call: function (method, args, kwargs) { var self = this; - if (this.req) { this.req.abort(); } - return this.req = openerp.jsonRpc('/web/dataset/call_kw', 'call', { + var req = method + '_req'; + + if (this[req]) { this[req].abort(); } + + return this[req] = openerp.jsonRpc('/web/dataset/call_kw', 'call', { model: 'website', - method: 'search_pages', - args: [null, term], - kwargs: { - limit: 9, - context: website.get_context() - }, + method: method, + args: args, + kwargs: kwargs, }).always(function () { - // request completed -> unstore it - self.req = null; + self[req] = null; + }); + }, + page_exists: function (term) { + return this.call('page_exists', [null, term], { + context: website.get_context(), + }); + }, + fetch_pages: function (term) { + return this.call('search_pages', [null, term], { + limit: 9, + context: website.get_context(), }); }, }); -- cgit v1.2.3 From 9a399dfb9461acfb6ebe53779aed1012421f2846 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Fri, 29 Nov 2013 17:00:45 +0100 Subject: [FIX] website snippets: quote, quotes slider, parallax bzr revid: chm@openerp.com-20131129160045-527o2i6unyyymr6e --- addons/website/static/src/js/website.editor.js | 1 + 1 file changed, 1 insertion(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index c50ad392887..c1d31bcd7cc 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -104,6 +104,7 @@ left: $el.width() / 2 + image_left - $btn.outerWidth() / 2, }); }).on('mouseleave', 'img', function (e) { + if (!previousSelection) { return; } var $previous = $(previousSelection.$); var $button = $previous.next('button'); $button.css('visibility', 'hidden'); -- cgit v1.2.3 From fdfa7362ac00bbf47344643191ecbe56fdbf61e2 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 2 Dec 2013 12:33:04 +0100 Subject: [FIX] image fields getting overly dirty the addition and removal of the [edit] button on hover would be caught by the mutation observer and mark the image field as dirty, even when it had not actually been altered, leaving to spurious save events for said field. bzr revid: xmo@openerp.com-20131202113304-xpgu43se5er1ho7y --- addons/website/static/src/js/website.editor.js | 32 ++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index c1d31bcd7cc..78e452ef76c 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -1371,6 +1371,11 @@ // a/@href, ...) _(mutations).chain() .filter(function (m) { + // ignore any change related to mundane image-edit-button + if (m.target && m.target.className + && m.target.className.indexOf('image-edit-button') !== -1) { + return false; + } switch(m.type) { case 'attributes': // ignore .cke_focus being added or removed // if attribute is not a class, can't be .cke_focus change @@ -1384,8 +1389,11 @@ // ignore mutation if the *only* change is .cke_focus return change.length !== 1 || change[0] === 'cke_focus'; case 'childList': - //
    appears when focusing RTE in FF, ignore - return m.addedNodes.length !== 1 || m.addedNodes[0].nodeName !== 'BR'; + // 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. + return !!remove_mundane_nodes(m.addedNodes).length || + !!remove_mundane_nodes(m.removedNodes).length; default: return true; } @@ -1402,4 +1410,24 @@ .uniq() .each(function (node) { $(node).trigger('content_changed'); }) }); + function remove_mundane_nodes(nodes) { + if (!nodes || !nodes.length) { return []; } + + var output = []; + for(var i=0; i appears when focusing RTE in FF, ignore + continue; + } + if (node.className.indexOf('image-edit-button') !== -1) { + // [Edit] button added and removed on image hover, don't count + // as making parent node dirty + continue; + } + + output.push(node); + } + return output; + } })(); -- cgit v1.2.3 From d53a289c5b205fab11d4448ae159f7b9370551f8 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 2 Dec 2013 12:38:25 +0100 Subject: [REM] leftover thing bzr revid: xmo@openerp.com-20131202113825-c5jbqs17nihip81t --- addons/website/static/src/js/website.editor.js | 1 - 1 file changed, 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 78e452ef76c..b5caac71d74 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -1403,7 +1403,6 @@ while (node && !$(node).hasClass('oe_editable')) { node = node.parentNode; } - $(m.target).trigger('node_changed'); return node; }) .compact() -- cgit v1.2.3 From 9d9d3f207e7e6089d01f0b7fe26d7fd9cda0ddce Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 3 Dec 2013 12:13:23 +0100 Subject: [IMP] cancellation of RTE * rename Cancel to Discard for clarity (user test) * add intermediate dialog in case of mis-click, use 'danger' button style to clearly indicate this is a destructive operation bzr revid: xmo@openerp.com-20131203111323-9mx7aazfpsybe718 --- addons/website/static/src/js/website.editor.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index b5caac71d74..5128a3028ce 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -555,7 +555,20 @@ }); }, cancel: function () { - website.reload(); + new $.Deferred(function (d) { + var $dialog = $(openerp.qweb.render('website.editor.discard')).appendTo(document.body); + $dialog.on('click', '.btn-danger', function () { + d.resolve(); + }).on('hidden.bs.modal', function () { + d.reject(); + }); + d.always(function () { + $dialog.remove(); + }); + $dialog.modal('show'); + }).then(function () { + website.reload(); + }) }, new_page: function (ev) { ev.preventDefault(); -- cgit v1.2.3 From abf5c885109bb55e8bc3637d8428766b56f7f832 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Tue, 3 Dec 2013 16:55:36 +0100 Subject: [FIX] website: customize: apply fontawesome to icons bzr revid: chm@openerp.com-20131203155536-de2htsq0rwv6oepz --- addons/website/static/src/js/website.editor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 5128a3028ce..64726b5625b 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -416,8 +416,8 @@ if (item.header) { menu.append(''); } else { - menu.append(_.str.sprintf('
  • %s
  • ', - item.id, item.active ? '' : '-empty', item.name)); + menu.append(_.str.sprintf('
  • %s
  • ', + item.id, item.active ? '' : '-check', item.name)); } }); // Adding Static Menus -- cgit v1.2.3 From 49f357da541296d4b7a34318386fd758c3680b27 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Tue, 3 Dec 2013 17:16:30 +0100 Subject: [FIX] rte crashes when inserting new lines We deal with text nodes in this case bzr revid: fme@openerp.com-20131203161630-f34r1nrqcb4m6jge --- addons/website/static/src/js/website.editor.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 64726b5625b..1bdc6bb9292 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -1428,14 +1428,16 @@ var output = []; for(var i=0; i appears when focusing RTE in FF, ignore - continue; - } - if (node.className.indexOf('image-edit-button') !== -1) { - // [Edit] button added and removed on image hover, don't count - // as making parent node dirty - continue; + if (node.nodeType === document.ELEMENT_NODE) { + if (node.nodeName === 'BR' && node.getAttribute('type') === '_moz') { + //
    appears when focusing RTE in FF, ignore + continue; + } + if (node.className.indexOf('image-edit-button') !== -1) { + // [Edit] button added and removed on image hover, don't count + // as making parent node dirty + continue; + } } output.push(node); -- cgit v1.2.3 From 31381c1469e4970dae7c0f00b49c7556cc6c3cf7 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 4 Dec 2013 11:42:25 +0100 Subject: [FIX] Disable form submition in editable mode bzr revid: fme@openerp.com-20131204104225-2s3jp325731mqd92 --- addons/website/static/src/js/website.editor.js | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 1bdc6bb9292..52e67ecd9e3 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -17,6 +17,11 @@ website.form(this.pathname, 'POST'); }); + $(document).on('submit', '.cke_editable form', function (ev) { + // Disable form submition in editable mode + ev.preventDefault(); + }); + $(document).on('hide.bs.dropdown', '.dropdown', function (ev) { // Prevent dropdown closing when a contenteditable children is focused if (ev.originalEvent -- cgit v1.2.3 From b79e56d1af9a2d9e10631df79c4325ea7d0854e1 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 4 Dec 2013 11:52:12 +0100 Subject: [IMP] clarity of links edition According to user tests, users have a hard time finding out how to edit links. Thus, add same system as image edition (a small button appearing when hovering the element). Extract and unify these two to avoid redundancies between handlings as they are broadly similar (only details such as label, positioning and size of button relative to the element being hovered really change, the lifecycle itself is the same). The main setup still isn't very clean, there might be a better way to do it. bzr revid: xmo@openerp.com-20131204105212-u0a49nbvwilgtfst --- addons/website/static/src/js/website.editor.js | 148 +++++++++++++++---------- 1 file changed, 92 insertions(+), 56 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 52e67ecd9e3..a834f5f8162 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -73,57 +73,6 @@ link_dialog(editor); }, null, null, 500); - var previousSelection; - $(editor.element.$).on('mouseenter', 'img', function () { - if (previousSelection) { return; } - var selected = new CKEDITOR.dom.element(this); - if (!selected.is('img') - || selected.data('cke-realelement') - || selected.isReadOnly() - || selected.data('oe-model') === 'ir.ui.view') { - return; - } - - // display button - var $el = $((previousSelection = selected).$); - var $btn = $('') - .insertAfter($el) - .click(function (e) { - e.preventDefault(); - e.stopPropagation(); - image_dialog(editor, selected); - }); - - var position = $el.position(); - // http://bugs.jquery.com/ticket/5445#comment:6 - // if the image has margin: x auto for centering, FF & IE - // will report top/left as the "correct" value and - // marginTop/marginLeft at "0px", webkit browsers will - // report top/left as 0-ish and set marginTop and - // marginLeft - var image_top = position.top + parseInt($el.css('marginTop'), 10); - var image_left = position.left + parseInt($el.css('marginLeft'), 10); - $btn.css({ - position: 'absolute', - top: $el.height() / 2 + image_top - $btn.outerHeight() / 2, - left: $el.width() / 2 + image_left - $btn.outerWidth() / 2, - }); - }).on('mouseleave', 'img', function (e) { - if (!previousSelection) { return; } - var $previous = $(previousSelection.$); - var $button = $previous.next('button'); - $button.css('visibility', 'hidden'); - var el = document.elementFromPoint(e.clientX, e.clientY); - $button.css('visibility', ''); - if (el === this) { return; } - $button.remove(); - previousSelection = null; - }); - editor.on('destroy', function () { - if (!previousSelection) { return; } - $('.image-edit-button').remove(); - }); - //noinspection JSValidateTypes editor.addCommand('link', { exec: function (editor) { @@ -463,6 +412,7 @@ this.rte = new website.RTE(this); this.rte.on('change', this, this.proxy('rte_changed')); this.rte.on('rte:ready', this, function () { + self.setup_hover_buttons(); self.trigger('rte:ready'); }); @@ -586,6 +536,97 @@ } }); }, + + /** + * Creates a "hover" button for image and link edition + * + * @param {String} label the button's label + * @param {Function} editfn edition function, called when clicking the button + * @param {String} [classes] additional classes to set on the button + * @returns {jQuery} + */ + make_hover_button: function (label, editfn, classes) { + return $(openerp.qweb.render('website.editor.hoverbutton', { + label: label, + classes: classes, + })).hide().appendTo(document.body).click(function (e) { + e.preventDefault(); + e.stopPropagation(); + editfn.call(this, e); + }); + }, + /** + * For UI clarity, during RTE edition when the user hovers links and + * images a small button should appear to make the capability clear, + * as not all users think of double-clicking the image or link. + */ + setup_hover_buttons: function () { + var editor = this.rte.editor; + var $link_button = this.make_hover_button(_t("Edit Link"), function () { + var sel = new CKEDITOR.dom.element(previous); + editor.getSelection().selectElement(sel); + link_dialog(editor); + $link_button.hide(); + previous = null; + }, 'btn-xs'); + var $image_button = this.make_hover_button(_t("Edit Image"), function () { + image_dialog(editor, new CKEDITOR.dom.element(previous)); + $image_button.hide(); + previous = null; + }); + + // previous is the state of the button-trigger: it's the + // currently-ish hovered element which can trigger a button showing. + // -ish, because when moving to the button itself ``previous`` is + // still set to the element having triggered showing the button. + var previous; + $(editor.element.$).on('mouseover', 'a, img', function (e) { + // Back from edit button -> ignore + if (previous && previous === this) { return; } + + var selected = new CKEDITOR.dom.element(this); + if (selected.data('oe-model') === 'ir.ui.view' + || selected.data('cke-realelement') + || selected.isReadOnly()) { + return; + } + + previous = this; + var $selected = $(this); + var position = $selected.offset(); + if ($selected.is('img')) { + var image_top = position.top + parseInt($selected.css('marginTop'), 10); + var image_left = position.left + parseInt($selected.css('marginLeft'), 10); + $link_button.hide(); + // center button on image + $image_button.show().offset({ + top: $selected.outerHeight() / 2 + + image_top + - $image_button.outerHeight() / 2, + left: $selected.outerWidth() / 2 + + image_left + - $image_button.outerWidth() / 2, + }); + } else { + $image_button.hide(); + // put button below link, horizontally centered + $link_button.show().offset({ + top: $selected.outerHeight() + + position.top, + left: $selected.outerWidth() / 2 + + position.left + - $link_button.outerWidth() / 2 + }) + } + }).on('mouseleave', 'a, img', function (e) { + var current = document.elementFromPoint(e.clientX, e.clientY); + if (current === $link_button[0] || current === $image_button[0]) { + return; + } + $image_button.add($link_button).hide(); + previous = null; + }); + } }); var blocks_selector = _.keys(CKEDITOR.dtd.$block).join(','); @@ -1438,11 +1479,6 @@ //
    appears when focusing RTE in FF, ignore continue; } - if (node.className.indexOf('image-edit-button') !== -1) { - // [Edit] button added and removed on image hover, don't count - // as making parent node dirty - continue; - } } output.push(node); -- cgit v1.2.3 From b1765e2834b0e04596b85eab29ceabc135d5b585 Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 4 Dec 2013 17:17:54 +0100 Subject: [IMP] website: slip layout bzr revid: chm@openerp.com-20131204161754-5dq4bt7gghnk878c --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index a834f5f8162..aa3d7adac6c 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -371,7 +371,7 @@ menu.append(''); } else { menu.append(_.str.sprintf('
  • %s
  • ', - item.id, item.active ? '' : '-check', item.name)); + item.id, item.active ? '-check' : '', item.name)); } }); // Adding Static Menus -- cgit v1.2.3 From 04045c369931ea0c4359ddff0196c163dc5e6db5 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 4 Dec 2013 17:28:05 +0100 Subject: [IMP] use ckeditor 4.3 final feature to disable widget draghandle entirely instead of relying on CSS bzr revid: xmo@openerp.com-20131204162805-rikk5kbbx304tol6 --- addons/website/static/src/js/website.editor.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index a834f5f8162..b7bc451009b 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -323,6 +323,7 @@ init: function (editor) { editor.widgets.add('oeref', { editables: { text: '*' }, + draggable: false, upcast: function (el) { return el.attributes['data-oe-type'] @@ -331,6 +332,7 @@ }); editor.widgets.add('monetary', { editables: { text: 'span.oe_currency_value' }, + draggable: false, upcast: function (el) { return el.attributes['data-oe-type'] === 'monetary'; -- cgit v1.2.3 From a1ecb6923b8673f9f4e00f4e27e0a6a12491edd8 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 5 Dec 2013 12:39:08 +0100 Subject: [ADD] saving of oddly localized/formatted stuff bzr revid: xmo@openerp.com-20131205113908-9tr575ejn7hanhi7 --- addons/website/static/src/js/website.editor.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index b7bc451009b..6269013dd25 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -326,8 +326,18 @@ draggable: false, upcast: function (el) { - return el.attributes['data-oe-type'] - && el.attributes['data-oe-type'] !== 'monetary'; + var matches = el.attributes['data-oe-type'] && el.attributes['data-oe-type'] !== 'monetary'; + if (!matches) { return false; } + + if (el.attributes['data-oe-original']) { + while (el.children.length) { + el.children[0].remove(); + } + el.add(new CKEDITOR.htmlParser.text( + el.attributes['data-oe-original'] + )); + } + return true; }, }); editor.widgets.add('monetary', { -- cgit v1.2.3 From 083e88167e5c376a9559e6c38fd3af193266ff2f Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 11 Dec 2013 17:33:05 +0100 Subject: [IMP] website: save (button) or discard (link), on left in modal bzr revid: chm@openerp.com-20131211163305-5qwltn11k2ph179o --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index f88a876d82f..92556be0c98 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -366,7 +366,7 @@ events: { 'click button[data-action=edit]': 'edit', 'click button[data-action=save]': 'save', - 'click button[data-action=cancel]': 'cancel', + 'click a[data-action=cancel]': 'cancel', 'click a[data-action=new_page]': 'new_page', }, container: 'body', -- cgit v1.2.3 From bf876739fe1b3623f8c5c99a6fd9c1b80b317c0d Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Fri, 13 Dec 2013 10:20:25 +0100 Subject: [REM] undo RTE button by fp demand, apparently unseen & unused by users bzr revid: xmo@openerp.com-20131213092025-thlltl0xjxq0noyp --- addons/website/static/src/js/website.editor.js | 3 --- 1 file changed, 3 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 92556be0c98..40b7820e89a 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -875,9 +875,6 @@ // Place toolbar in controlled location sharedSpaces: { top: 'oe_rte_toolbar' }, toolbar: [{ - name: 'clipboard', items: [ - "Undo" - ]},{ name: 'basicstyles', items: [ "Bold", "Italic", "Underline", "Strike", "Subscript", "Superscript", "TextColor", "BGColor", "RemoveFormat" -- cgit v1.2.3 From 98c4e6b3d4023663e4fda1244d57dbf94219fd9d Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 16 Dec 2013 14:44:24 +0100 Subject: [IMP] editability criteria for links and images if a link or image is an editing host (has @contenteditable=true), its body is editable *but* its attributes should not be considered editable: if the attributes come from a t-att-*, @contenteditable will be set on the node itself. such elements should be ignored by the link & image dialog handling thing, as editing their attributes has undesirable effects. bzr revid: xmo@openerp.com-20131216134424-fdqs03i9pidbmaqt --- addons/website/static/src/js/website.editor.js | 37 ++++++++++++++++++-------- 1 file changed, 26 insertions(+), 11 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 40b7820e89a..1e3ef0da66a 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -32,6 +32,27 @@ }); }); + /** + * An editing host is an HTML element with @contenteditable=true, or the + * child of a document in designMode=on (but that one's not supported) + * + * https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#editing-host + */ + function is_editing_host(element) { + return element.getAttribute('contentEditable') === 'true'; + } + /** + * Checks that both the element's content *and the element itself* are + * editable: an editing host is considered non-editable because its content + * is editable but its attributes should not be considered editable + */ + function is_editable_node(element) { + return !(element.data('oe-model') === 'ir.ui.view' + || element.data('cke-realelement') + || is_editing_host(element) + || element.isReadOnly()); + } + function link_dialog(editor) { return new website.editor.RTELinkDialog(editor).appendTo(document.body); } @@ -54,18 +75,13 @@ init: function (editor) { editor.on('doubleclick', function (evt) { var element = evt.data.element; - if (element.is('img') - && !element.data('cke-realelement') - && !element.isReadOnly() - && (element.data('oe-model') !== 'ir.ui.view')) { + if (element.is('img') && is_editable_node(element)) { image_dialog(editor, element); return; } element = get_selected_link(editor) || evt.data.element; - if (element.isReadOnly() - || !element.is('a') - || element.data('oe-model')) { + if (!(element.is('a') && is_editable_node(element))) { return; } @@ -360,7 +376,8 @@ }); $body.css('padding-top', '50px'); // Not working properly: editor.$el.outerHeight()); }; - /* ----- TOP EDITOR BAR FOR ADMIN ---- */ + + /* ----- TOP EDITOR BAR FOR ADMIN ---- */ website.EditorBar = openerp.Widget.extend({ template: 'website.editorbar', events: { @@ -597,9 +614,7 @@ if (previous && previous === this) { return; } var selected = new CKEDITOR.dom.element(this); - if (selected.data('oe-model') === 'ir.ui.view' - || selected.data('cke-realelement') - || selected.isReadOnly()) { + if (!is_editable_node(selected)) { return; } -- cgit v1.2.3 From 128f1e1281a640d21cb4ef7b587f66fdffc4ce7f Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Tue, 17 Dec 2013 16:37:51 +0100 Subject: [FIX] odd behavior in cke widgets in "block-level" widgets (divs), when hitting [return] instead of adding a newline in the widget a new bit of widget may be added. This is caused by an incompability between widgets and the enterKey plugin. Remove enterKey, behavior on [Return] is slightly worse (always inserts br) but widgets don't get broken. See https://dev.ckeditor.com/ticket/11326 for issue in upstream. bzr revid: xmo@openerp.com-20131217153751-7fbwp34o8kac9x94 --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 1e3ef0da66a..c7c5620c9a4 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -859,7 +859,7 @@ var plugins = [ 'a11yhelp', 'basicstyles', 'blockquote', 'clipboard', 'colorbutton', 'colordialog', 'dialogadvtab', - 'elementspath', 'enterkey', 'entities', 'filebrowser', + 'elementspath', /*'enterkey',*/ 'entities', 'filebrowser', 'find', 'floatingspace','format', 'htmlwriter', 'iframe', 'indentblock', 'indentlist', 'justify', 'list', 'pastefromword', 'pastetext', 'preview', -- cgit v1.2.3 From 9abcc28884688bd251c5a9de77b3afda11dcec90 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 18 Dec 2013 18:39:15 +0100 Subject: [IMP] Set EditorBar height programmatically bzr revid: fme@openerp.com-20131218173915-ds5jeyfypbaefrqf --- addons/website/static/src/js/website.editor.js | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index c7c5620c9a4..661c6d80a5f 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -374,7 +374,6 @@ editor.edit(); } }); - $body.css('padding-top', '50px'); // Not working properly: editor.$el.outerHeight()); }; /* ----- TOP EDITOR BAR FOR ADMIN ---- */ @@ -423,7 +422,7 @@ }, start: function() { var self = this; - + this.height = null; this.saving_mutex = new openerp.Mutex(); this.$('#website-top-edit').hide(); @@ -443,12 +442,26 @@ this.rte.on('rte:ready', this, function () { self.setup_hover_buttons(); self.trigger('rte:ready'); + self.check_height(); }); + $(window).on('resize', _.debounce(this.check_height.bind(this), 50)); + this.check_height(); + return $.when( this._super.apply(this, arguments), this.rte.appendTo(this.$('#website-top-edit .nav.pull-right')) - ); + ).then(function () { + self.check_height(); + }); + }, + check_height: function () { + var editor_height = this.$el.outerHeight(); + if (this.height != editor_height) { + this.height = editor_height; + $(document.body).css('padding-top', this.height); + this.trigger('resize', this.height); + } }, edit: function () { this.$buttons.edit.prop('disabled', true); @@ -456,7 +469,7 @@ this.$('#website-top-edit').show(); $('.css_non_editable_mode_hidden').removeClass("css_non_editable_mode_hidden"); - this.rte.start_edition(); + this.rte.start_edition().then(this.check_height.bind(this)); }, rte_changed: function () { this.$buttons.save.prop('disabled', false); -- cgit v1.2.3 From b180d69808e7ef16e3854ef347cc8aa57eca718f Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 18 Dec 2013 21:16:19 +0100 Subject: [IMP] Better events naming for EditorBar height related stuff bzr revid: fme@openerp.com-20131218201619-vja6dv0sctokep3b --- addons/website/static/src/js/website.editor.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 661c6d80a5f..51f14a0f6d5 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -422,7 +422,6 @@ }, start: function() { var self = this; - this.height = null; this.saving_mutex = new openerp.Mutex(); this.$('#website-top-edit').hide(); @@ -457,10 +456,9 @@ }, check_height: function () { var editor_height = this.$el.outerHeight(); - if (this.height != editor_height) { - this.height = editor_height; - $(document.body).css('padding-top', this.height); - this.trigger('resize', this.height); + if (this.get('height') != editor_height) { + $(document.body).css('padding-top', editor_height); + this.set('height', editor_height); } }, edit: function () { -- cgit v1.2.3 From bcef910f841318a4ac96ebe96529ed9cd71bba0c Mon Sep 17 00:00:00 2001 From: Christophe Matthieu Date: Wed, 15 Jan 2014 15:17:56 +0100 Subject: [FIX] website editor: add attributeEditable attribute to edit an editing host bzr revid: chm@openerp.com-20140115141756-4ixq240p5z1snt9h --- addons/website/static/src/js/website.editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 51f14a0f6d5..095ce642994 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -49,7 +49,7 @@ function is_editable_node(element) { return !(element.data('oe-model') === 'ir.ui.view' || element.data('cke-realelement') - || is_editing_host(element) + || (is_editing_host(element) && element.getAttribute('attributeEditable') !== 'true') || element.isReadOnly()); } -- cgit v1.2.3 From e2fede3fe78c0f1c036f4f1695ebf7348655590f Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Thu, 16 Jan 2014 10:47:47 +0100 Subject: [ADD] dialog for fontawesome glyph manipulation bzr revid: xmo@openerp.com-20140116094747-w1uey27l39fy66zc --- addons/website/static/src/js/website.editor.js | 123 +++++++++++++++++++++++++ 1 file changed, 123 insertions(+) (limited to 'addons/website/static/src/js/website.editor.js') diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js index 095ce642994..69b58a0c496 100644 --- a/addons/website/static/src/js/website.editor.js +++ b/addons/website/static/src/js/website.editor.js @@ -364,6 +364,20 @@ return el.attributes['data-oe-type'] === 'monetary'; } }); + editor.widgets.add('icons', { + draggable: false, + + init: function () { + this.on('edit', function () { + new website.editor.FontIconsDialog(editor, this.element.$) + .appendTo(document.body); + }); + }, + upcast: function (el) { + return el.attributes['class'] + && (/\bfa\b/.test(el.attributes['class'])); + } + }); } }); @@ -1449,6 +1463,115 @@ .contains('a', true); } + website.editor.FontIconsDialog = website.editor.Dialog.extend({ + template: 'website.editor.dialog.font-icons', + events : _.extend({}, website.editor.Dialog.prototype.events, { + change: 'update_preview', + }), + + // List of FontAwesome icons in 4.0.3, extracted from the cheatsheet. + // Each icon provides the unicode codepoint as ``text`` and the class + // name as ``id`` so the whole thing can be fed directly to select2 + // without post-processing and do the right thing (except for the part + // where we still need to implement ``initSelection``) + // TODO: add id/name to the text in order to allow FAYT selection of icons? + icons: [{"text": "\uf000", "id": "fa-glass"}, {"text": "\uf001", "id": "fa-music"}, {"text": "\uf002", "id": "fa-search"}, {"text": "\uf003", "id": "fa-envelope-o"}, {"text": "\uf004", "id": "fa-heart"}, {"text": "\uf005", "id": "fa-star"}, {"text": "\uf006", "id": "fa-star-o"}, {"text": "\uf007", "id": "fa-user"}, {"text": "\uf008", "id": "fa-film"}, {"text": "\uf009", "id": "fa-th-large"}, {"text": "\uf00a", "id": "fa-th"}, {"text": "\uf00b", "id": "fa-th-list"}, {"text": "\uf00c", "id": "fa-check"}, {"text": "\uf00d", "id": "fa-times"}, {"text": "\uf00e", "id": "fa-search-plus"}, {"text": "\uf010", "id": "fa-search-minus"}, {"text": "\uf011", "id": "fa-power-off"}, {"text": "\uf012", "id": "fa-signal"}, {"text": "\uf013", "id": "fa-cog"}, {"text": "\uf014", "id": "fa-trash-o"}, {"text": "\uf015", "id": "fa-home"}, {"text": "\uf016", "id": "fa-file-o"}, {"text": "\uf017", "id": "fa-clock-o"}, {"text": "\uf018", "id": "fa-road"}, {"text": "\uf019", "id": "fa-download"}, {"text": "\uf01a", "id": "fa-arrow-circle-o-down"}, {"text": "\uf01b", "id": "fa-arrow-circle-o-up"}, {"text": "\uf01c", "id": "fa-inbox"}, {"text": "\uf01d", "id": "fa-play-circle-o"}, {"text": "\uf01e", "id": "fa-repeat"}, {"text": "\uf021", "id": "fa-refresh"}, {"text": "\uf022", "id": "fa-list-alt"}, {"text": "\uf023", "id": "fa-lock"}, {"text": "\uf024", "id": "fa-flag"}, {"text": "\uf025", "id": "fa-headphones"}, {"text": "\uf026", "id": "fa-volume-off"}, {"text": "\uf027", "id": "fa-volume-down"}, {"text": "\uf028", "id": "fa-volume-up"}, {"text": "\uf029", "id": "fa-qrcode"}, {"text": "\uf02a", "id": "fa-barcode"}, {"text": "\uf02b", "id": "fa-tag"}, {"text": "\uf02c", "id": "fa-tags"}, {"text": "\uf02d", "id": "fa-book"}, {"text": "\uf02e", "id": "fa-bookmark"}, {"text": "\uf02f", "id": "fa-print"}, {"text": "\uf030", "id": "fa-camera"}, {"text": "\uf031", "id": "fa-font"}, {"text": "\uf032", "id": "fa-bold"}, {"text": "\uf033", "id": "fa-italic"}, {"text": "\uf034", "id": "fa-text-height"}, {"text": "\uf035", "id": "fa-text-width"}, {"text": "\uf036", "id": "fa-align-left"}, {"text": "\uf037", "id": "fa-align-center"}, {"text": "\uf038", "id": "fa-align-right"}, {"text": "\uf039", "id": "fa-align-justify"}, {"text": "\uf03a", "id": "fa-list"}, {"text": "\uf03b", "id": "fa-outdent"}, {"text": "\uf03c", "id": "fa-indent"}, {"text": "\uf03d", "id": "fa-video-camera"}, {"text": "\uf03e", "id": "fa-picture-o"}, {"text": "\uf040", "id": "fa-pencil"}, {"text": "\uf041", "id": "fa-map-marker"}, {"text": "\uf042", "id": "fa-adjust"}, {"text": "\uf043", "id": "fa-tint"}, {"text": "\uf044", "id": "fa-pencil-square-o"}, {"text": "\uf045", "id": "fa-share-square-o"}, {"text": "\uf046", "id": "fa-check-square-o"}, {"text": "\uf047", "id": "fa-arrows"}, {"text": "\uf048", "id": "fa-step-backward"}, {"text": "\uf049", "id": "fa-fast-backward"}, {"text": "\uf04a", "id": "fa-backward"}, {"text": "\uf04b", "id": "fa-play"}, {"text": "\uf04c", "id": "fa-pause"}, {"text": "\uf04d", "id": "fa-stop"}, {"text": "\uf04e", "id": "fa-forward"}, {"text": "\uf050", "id": "fa-fast-forward"}, {"text": "\uf051", "id": "fa-step-forward"}, {"text": "\uf052", "id": "fa-eject"}, {"text": "\uf053", "id": "fa-chevron-left"}, {"text": "\uf054", "id": "fa-chevron-right"}, {"text": "\uf055", "id": "fa-plus-circle"}, {"text": "\uf056", "id": "fa-minus-circle"}, {"text": "\uf057", "id": "fa-times-circle"}, {"text": "\uf058", "id": "fa-check-circle"}, {"text": "\uf059", "id": "fa-question-circle"}, {"text": "\uf05a", "id": "fa-info-circle"}, {"text": "\uf05b", "id": "fa-crosshairs"}, {"text": "\uf05c", "id": "fa-times-circle-o"}, {"text": "\uf05d", "id": "fa-check-circle-o"}, {"text": "\uf05e", "id": "fa-ban"}, {"text": "\uf060", "id": "fa-arrow-left"}, {"text": "\uf061", "id": "fa-arrow-right"}, {"text": "\uf062", "id": "fa-arrow-up"}, {"text": "\uf063", "id": "fa-arrow-down"}, {"text": "\uf064", "id": "fa-share"}, {"text": "\uf065", "id": "fa-expand"}, {"text": "\uf066", "id": "fa-compress"}, {"text": "\uf067", "id": "fa-plus"}, {"text": "\uf068", "id": "fa-minus"}, {"text": "\uf069", "id": "fa-asterisk"}, {"text": "\uf06a", "id": "fa-exclamation-circle"}, {"text": "\uf06b", "id": "fa-gift"}, {"text": "\uf06c", "id": "fa-leaf"}, {"text": "\uf06d", "id": "fa-fire"}, {"text": "\uf06e", "id": "fa-eye"}, {"text": "\uf070", "id": "fa-eye-slash"}, {"text": "\uf071", "id": "fa-exclamation-triangle"}, {"text": "\uf072", "id": "fa-plane"}, {"text": "\uf073", "id": "fa-calendar"}, {"text": "\uf074", "id": "fa-random"}, {"text": "\uf075", "id": "fa-comment"}, {"text": "\uf076", "id": "fa-magnet"}, {"text": "\uf077", "id": "fa-chevron-up"}, {"text": "\uf078", "id": "fa-chevron-down"}, {"text": "\uf079", "id": "fa-retweet"}, {"text": "\uf07a", "id": "fa-shopping-cart"}, {"text": "\uf07b", "id": "fa-folder"}, {"text": "\uf07c", "id": "fa-folder-open"}, {"text": "\uf07d", "id": "fa-arrows-v"}, {"text": "\uf07e", "id": "fa-arrows-h"}, {"text": "\uf080", "id": "fa-bar-chart-o"}, {"text": "\uf081", "id": "fa-twitter-square"}, {"text": "\uf082", "id": "fa-facebook-square"}, {"text": "\uf083", "id": "fa-camera-retro"}, {"text": "\uf084", "id": "fa-key"}, {"text": "\uf085", "id": "fa-cogs"}, {"text": "\uf086", "id": "fa-comments"}, {"text": "\uf087", "id": "fa-thumbs-o-up"}, {"text": "\uf088", "id": "fa-thumbs-o-down"}, {"text": "\uf089", "id": "fa-star-half"}, {"text": "\uf08a", "id": "fa-heart-o"}, {"text": "\uf08b", "id": "fa-sign-out"}, {"text": "\uf08c", "id": "fa-linkedin-square"}, {"text": "\uf08d", "id": "fa-thumb-tack"}, {"text": "\uf08e", "id": "fa-external-link"}, {"text": "\uf090", "id": "fa-sign-in"}, {"text": "\uf091", "id": "fa-trophy"}, {"text": "\uf092", "id": "fa-github-square"}, {"text": "\uf093", "id": "fa-upload"}, {"text": "\uf094", "id": "fa-lemon-o"}, {"text": "\uf095", "id": "fa-phone"}, {"text": "\uf096", "id": "fa-square-o"}, {"text": "\uf097", "id": "fa-bookmark-o"}, {"text": "\uf098", "id": "fa-phone-square"}, {"text": "\uf099", "id": "fa-twitter"}, {"text": "\uf09a", "id": "fa-facebook"}, {"text": "\uf09b", "id": "fa-github"}, {"text": "\uf09c", "id": "fa-unlock"}, {"text": "\uf09d", "id": "fa-credit-card"}, {"text": "\uf09e", "id": "fa-rss"}, {"text": "\uf0a0", "id": "fa-hdd-o"}, {"text": "\uf0a1", "id": "fa-bullhorn"}, {"text": "\uf0f3", "id": "fa-bell"}, {"text": "\uf0a3", "id": "fa-certificate"}, {"text": "\uf0a4", "id": "fa-hand-o-right"}, {"text": "\uf0a5", "id": "fa-hand-o-left"}, {"text": "\uf0a6", "id": "fa-hand-o-up"}, {"text": "\uf0a7", "id": "fa-hand-o-down"}, {"text": "\uf0a8", "id": "fa-arrow-circle-left"}, {"text": "\uf0a9", "id": "fa-arrow-circle-right"}, {"text": "\uf0aa", "id": "fa-arrow-circle-up"}, {"text": "\uf0ab", "id": "fa-arrow-circle-down"}, {"text": "\uf0ac", "id": "fa-globe"}, {"text": "\uf0ad", "id": "fa-wrench"}, {"text": "\uf0ae", "id": "fa-tasks"}, {"text": "\uf0b0", "id": "fa-filter"}, {"text": "\uf0b1", "id": "fa-briefcase"}, {"text": "\uf0b2", "id": "fa-arrows-alt"}, {"text": "\uf0c0", "id": "fa-users"}, {"text": "\uf0c1", "id": "fa-link"}, {"text": "\uf0c2", "id": "fa-cloud"}, {"text": "\uf0c3", "id": "fa-flask"}, {"text": "\uf0c4", "id": "fa-scissors"}, {"text": "\uf0c5", "id": "fa-files-o"}, {"text": "\uf0c6", "id": "fa-paperclip"}, {"text": "\uf0c7", "id": "fa-floppy-o"}, {"text": "\uf0c8", "id": "fa-square"}, {"text": "\uf0c9", "id": "fa-bars"}, {"text": "\uf0ca", "id": "fa-list-ul"}, {"text": "\uf0cb", "id": "fa-list-ol"}, {"text": "\uf0cc", "id": "fa-strikethrough"}, {"text": "\uf0cd", "id": "fa-underline"}, {"text": "\uf0ce", "id": "fa-table"}, {"text": "\uf0d0", "id": "fa-magic"}, {"text": "\uf0d1", "id": "fa-truck"}, {"text": "\uf0d2", "id": "fa-pinterest"}, {"text": "\uf0d3", "id": "fa-pinterest-square"}, {"text": "\uf0d4", "id": "fa-google-plus-square"}, {"text": "\uf0d5", "id": "fa-google-plus"}, {"text": "\uf0d6", "id": "fa-money"}, {"text": "\uf0d7", "id": "fa-caret-down"}, {"text": "\uf0d8", "id": "fa-caret-up"}, {"text": "\uf0d9", "id": "fa-caret-left"}, {"text": "\uf0da", "id": "fa-caret-right"}, {"text": "\uf0db", "id": "fa-columns"}, {"text": "\uf0dc", "id": "fa-sort"}, {"text": "\uf0dd", "id": "fa-sort-asc"}, {"text": "\uf0de", "id": "fa-sort-desc"}, {"text": "\uf0e0", "id": "fa-envelope"}, {"text": "\uf0e1", "id": "fa-linkedin"}, {"text": "\uf0e2", "id": "fa-undo"}, {"text": "\uf0e3", "id": "fa-gavel"}, {"text": "\uf0e4", "id": "fa-tachometer"}, {"text": "\uf0e5", "id": "fa-comment-o"}, {"text": "\uf0e6", "id": "fa-comments-o"}, {"text": "\uf0e7", "id": "fa-bolt"}, {"text": "\uf0e8", "id": "fa-sitemap"}, {"text": "\uf0e9", "id": "fa-umbrella"}, {"text": "\uf0ea", "id": "fa-clipboard"}, {"text": "\uf0eb", "id": "fa-lightbulb-o"}, {"text": "\uf0ec", "id": "fa-exchange"}, {"text": "\uf0ed", "id": "fa-cloud-download"}, {"text": "\uf0ee", "id": "fa-cloud-upload"}, {"text": "\uf0f0", "id": "fa-user-md"}, {"text": "\uf0f1", "id": "fa-stethoscope"}, {"text": "\uf0f2", "id": "fa-suitcase"}, {"text": "\uf0a2", "id": "fa-bell-o"}, {"text": "\uf0f4", "id": "fa-coffee"}, {"text": "\uf0f5", "id": "fa-cutlery"}, {"text": "\uf0f6", "id": "fa-file-text-o"}, {"text": "\uf0f7", "id": "fa-building-o"}, {"text": "\uf0f8", "id": "fa-hospital-o"}, {"text": "\uf0f9", "id": "fa-ambulance"}, {"text": "\uf0fa", "id": "fa-medkit"}, {"text": "\uf0fb", "id": "fa-fighter-jet"}, {"text": "\uf0fc", "id": "fa-beer"}, {"text": "\uf0fd", "id": "fa-h-square"}, {"text": "\uf0fe", "id": "fa-plus-square"}, {"text": "\uf100", "id": "fa-angle-double-left"}, {"text": "\uf101", "id": "fa-angle-double-right"}, {"text": "\uf102", "id": "fa-angle-double-up"}, {"text": "\uf103", "id": "fa-angle-double-down"}, {"text": "\uf104", "id": "fa-angle-left"}, {"text": "\uf105", "id": "fa-angle-right"}, {"text": "\uf106", "id": "fa-angle-up"}, {"text": "\uf107", "id": "fa-angle-down"}, {"text": "\uf108", "id": "fa-desktop"}, {"text": "\uf109", "id": "fa-laptop"}, {"text": "\uf10a", "id": "fa-tablet"}, {"text": "\uf10b", "id": "fa-mobile"}, {"text": "\uf10c", "id": "fa-circle-o"}, {"text": "\uf10d", "id": "fa-quote-left"}, {"text": "\uf10e", "id": "fa-quote-right"}, {"text": "\uf110", "id": "fa-spinner"}, {"text": "\uf111", "id": "fa-circle"}, {"text": "\uf112", "id": "fa-reply"}, {"text": "\uf113", "id": "fa-github-alt"}, {"text": "\uf114", "id": "fa-folder-o"}, {"text": "\uf115", "id": "fa-folder-open-o"}, {"text": "\uf118", "id": "fa-smile-o"}, {"text": "\uf119", "id": "fa-frown-o"}, {"text": "\uf11a", "id": "fa-meh-o"}, {"text": "\uf11b", "id": "fa-gamepad"}, {"text": "\uf11c", "id": "fa-keyboard-o"}, {"text": "\uf11d", "id": "fa-flag-o"}, {"text": "\uf11e", "id": "fa-flag-checkered"}, {"text": "\uf120", "id": "fa-terminal"}, {"text": "\uf121", "id": "fa-code"}, {"text": "\uf122", "id": "fa-reply-all"}, {"text": "\uf122", "id": "fa-mail-reply-all"}, {"text": "\uf123", "id": "fa-star-half-o"}, {"text": "\uf124", "id": "fa-location-arrow"}, {"text": "\uf125", "id": "fa-crop"}, {"text": "\uf126", "id": "fa-code-fork"}, {"text": "\uf127", "id": "fa-chain-broken"}, {"text": "\uf128", "id": "fa-question"}, {"text": "\uf129", "id": "fa-info"}, {"text": "\uf12a", "id": "fa-exclamation"}, {"text": "\uf12b", "id": "fa-superscript"}, {"text": "\uf12c", "id": "fa-subscript"}, {"text": "\uf12d", "id": "fa-eraser"}, {"text": "\uf12e", "id": "fa-puzzle-piece"}, {"text": "\uf130", "id": "fa-microphone"}, {"text": "\uf131", "id": "fa-microphone-slash"}, {"text": "\uf132", "id": "fa-shield"}, {"text": "\uf133", "id": "fa-calendar-o"}, {"text": "\uf134", "id": "fa-fire-extinguisher"}, {"text": "\uf135", "id": "fa-rocket"}, {"text": "\uf136", "id": "fa-maxcdn"}, {"text": "\uf137", "id": "fa-chevron-circle-left"}, {"text": "\uf138", "id": "fa-chevron-circle-right"}, {"text": "\uf139", "id": "fa-chevron-circle-up"}, {"text": "\uf13a", "id": "fa-chevron-circle-down"}, {"text": "\uf13b", "id": "fa-html5"}, {"text": "\uf13c", "id": "fa-css3"}, {"text": "\uf13d", "id": "fa-anchor"}, {"text": "\uf13e", "id": "fa-unlock-alt"}, {"text": "\uf140", "id": "fa-bullseye"}, {"text": "\uf141", "id": "fa-ellipsis-h"}, {"text": "\uf142", "id": "fa-ellipsis-v"}, {"text": "\uf143", "id": "fa-rss-square"}, {"text": "\uf144", "id": "fa-play-circle"}, {"text": "\uf145", "id": "fa-ticket"}, {"text": "\uf146", "id": "fa-minus-square"}, {"text": "\uf147", "id": "fa-minus-square-o"}, {"text": "\uf148", "id": "fa-level-up"}, {"text": "\uf149", "id": "fa-level-down"}, {"text": "\uf14a", "id": "fa-check-square"}, {"text": "\uf14b", "id": "fa-pencil-square"}, {"text": "\uf14c", "id": "fa-external-link-square"}, {"text": "\uf14d", "id": "fa-share-square"}, {"text": "\uf14e", "id": "fa-compass"}, {"text": "\uf150", "id": "fa-caret-square-o-down"}, {"text": "\uf151", "id": "fa-caret-square-o-up"}, {"text": "\uf152", "id": "fa-caret-square-o-right"}, {"text": "\uf153", "id": "fa-eur"}, {"text": "\uf154", "id": "fa-gbp"}, {"text": "\uf155", "id": "fa-usd"}, {"text": "\uf156", "id": "fa-inr"}, {"text": "\uf157", "id": "fa-jpy"}, {"text": "\uf158", "id": "fa-rub"}, {"text": "\uf159", "id": "fa-krw"}, {"text": "\uf15a", "id": "fa-btc"}, {"text": "\uf15b", "id": "fa-file"}, {"text": "\uf15c", "id": "fa-file-text"}, {"text": "\uf15d", "id": "fa-sort-alpha-asc"}, {"text": "\uf15e", "id": "fa-sort-alpha-desc"}, {"text": "\uf160", "id": "fa-sort-amount-asc"}, {"text": "\uf161", "id": "fa-sort-amount-desc"}, {"text": "\uf162", "id": "fa-sort-numeric-asc"}, {"text": "\uf163", "id": "fa-sort-numeric-desc"}, {"text": "\uf164", "id": "fa-thumbs-up"}, {"text": "\uf165", "id": "fa-thumbs-down"}, {"text": "\uf166", "id": "fa-youtube-square"}, {"text": "\uf167", "id": "fa-youtube"}, {"text": "\uf168", "id": "fa-xing"}, {"text": "\uf169", "id": "fa-xing-square"}, {"text": "\uf16a", "id": "fa-youtube-play"}, {"text": "\uf16b", "id": "fa-dropbox"}, {"text": "\uf16c", "id": "fa-stack-overflow"}, {"text": "\uf16d", "id": "fa-instagram"}, {"text": "\uf16e", "id": "fa-flickr"}, {"text": "\uf170", "id": "fa-adn"}, {"text": "\uf171", "id": "fa-bitbucket"}, {"text": "\uf172", "id": "fa-bitbucket-square"}, {"text": "\uf173", "id": "fa-tumblr"}, {"text": "\uf174", "id": "fa-tumblr-square"}, {"text": "\uf175", "id": "fa-long-arrow-down"}, {"text": "\uf176", "id": "fa-long-arrow-up"}, {"text": "\uf177", "id": "fa-long-arrow-left"}, {"text": "\uf178", "id": "fa-long-arrow-right"}, {"text": "\uf179", "id": "fa-apple"}, {"text": "\uf17a", "id": "fa-windows"}, {"text": "\uf17b", "id": "fa-android"}, {"text": "\uf17c", "id": "fa-linux"}, {"text": "\uf17d", "id": "fa-dribbble"}, {"text": "\uf17e", "id": "fa-skype"}, {"text": "\uf180", "id": "fa-foursquare"}, {"text": "\uf181", "id": "fa-trello"}, {"text": "\uf182", "id": "fa-female"}, {"text": "\uf183", "id": "fa-male"}, {"text": "\uf184", "id": "fa-gittip"}, {"text": "\uf185", "id": "fa-sun-o"}, {"text": "\uf186", "id": "fa-moon-o"}, {"text": "\uf187", "id": "fa-archive"}, {"text": "\uf188", "id": "fa-bug"}, {"text": "\uf189", "id": "fa-vk"}, {"text": "\uf18a", "id": "fa-weibo"}, {"text": "\uf18b", "id": "fa-renren"}, {"text": "\uf18c", "id": "fa-pagelines"}, {"text": "\uf18d", "id": "fa-stack-exchange"}, {"text": "\uf18e", "id": "fa-arrow-circle-o-right"}, {"text": "\uf190", "id": "fa-arrow-circle-o-left"}, {"text": "\uf191", "id": "fa-caret-square-o-left"}, {"text": "\uf192", "id": "fa-dot-circle-o"}, {"text": "\uf193", "id": "fa-wheelchair"}, {"text": "\uf194", "id": "fa-vimeo-square"}, {"text": "\uf195", "id": "fa-try"}, {"text": "\uf196", "id": "fa-plus-square-o"}], + init: function (editor, element) { + this._super(editor); + this.element = element; + }, + /** + * Initializes select2: in Chrome and Safari,