Skip to content
Snippets Groups Projects
Commit ff58a961 authored by Christophe Matthieu's avatar Christophe Matthieu
Browse files

[IMP] web_editor: add modal to translate node attributes

parent 89d620e4
No related branches found
No related tags found
No related merge requests found
......@@ -55,7 +55,7 @@ editor.reload = function () {
/* ----- TOP EDITOR BAR FOR ADMIN ---- */
base.ready().then(function () {
if (editor.editable && location.search.indexOf("enable_editor") >= 0 && !editor.no_editor) {
if (editor.editable && location.search.indexOf("enable_editor") >= 0) {
editor.editor_bar = new editor.Class();
editor.editor_bar.prependTo(document.body);
}
......@@ -90,7 +90,7 @@ editor.Class = Widget.extend({
var flag = false;
window.onbeforeunload = function(event) {
if ($('.o_editable.o_dirty').length && !flag) {
if (rte.history.getEditableHasUndo().length && !flag) {
flag = true;
setTimeout(function () {flag=false;},0);
return _t('This document is not saved!');
......
......@@ -8,8 +8,10 @@ var Class = require('web.Class');
var Widget = require('web.Widget');
var base = require('web_editor.base');
var rte = require('web_editor.rte');
var editor_widget = require('web_editor.widget');
var qweb = core.qweb;
var _t = core._t;
ajax.loadXML('/web_editor/static/src/xml/translator.xml', qweb);
......@@ -17,14 +19,20 @@ ajax.loadXML('/web_editor/static/src/xml/translator.xml', qweb);
var translatable = !!$('html').data('translatable');
var edit_translations = !!$('html').data('edit_translations');
function unbind_click(event) {
if (event.ctrlKey || !$(event.target).is(':o_editable')) {
return;
}
event.preventDefault();
event.stopPropagation();
}
$.fn.extend({
prependEvent: function (events, selector, data, handler) {
this.on(events, selector, data, handler);
events = events.split(' ');
this.each(function () {
var el = this;
_.each(events, function (event) {
var handler = $._data(el, 'events')[event].pop();
$._data(el, 'events')[event].unshift(handler);
});
});
return this;
}
});
var RTE_Translate = rte.Class.extend({
saveElement: function ($el, context) {
......@@ -49,6 +57,33 @@ var RTE_Translate = rte.Class.extend({
},
});
var Translate_Modal = editor_widget.Dialog.extend({
template: 'web_editor.translator.attributes',
init: function (parent, node) {
this._super();
this.parent = parent;
this.$target = $(node);
this.translation = $(node).data('translation');
},
start: function () {
var self = this;
this._super();
var $group = this.$el.find('.form-group');
_.each(this.translation, function (node, attr) {
var $node = $(node);
var $label = $('<label class="control-label"></label>').text(attr);
var $input = $('<input class="form-control"/>').val($node.html());
$input.on('change keyup', function () {
var value = $input.val();
$node.html(value).trigger('change', node);
$node.data('$node').attr($node.data('attribute'), value).trigger('translate');
self.parent.rte_changed(node);
});
$group.append($label).append($input);
});
}
});
var Translate = Widget.extend({
events: {
'click [data-action="save"]': 'save_and_reload',
......@@ -63,14 +98,43 @@ var Translate = Widget.extend({
this._super();
this.rte = new RTE_Translate(this, this.config);
this.rte.on('change', this, this.onChange);
this.rte.on('change', this, this.rte_changed);
},
start: function () {
this._super();
this.$('button[data-action=save]').prop('disabled', true);
return this.edit();
},
setTarget: function ($target) {
this.$target = $target.find('[data-oe-translation-id], [data-oe-model][data-oe-id][data-oe-field]');
// attributes
var attrs = ['placeholder', 'title', 'alt'];
_.each(attrs, function (attr) {
$target.find('['+attr+'*="data-oe-translation-id="]').each(function () {
var $node = $(this);
var translation = $node.data('translation') || {};
var trans = $node.attr(attr);
var match = trans.match(/<span [^>]*data-oe-translation-id="([0-9]+)"[^>]*>(.*)<\/span>/);
var $trans = $(trans).addClass('hidden o_editable o_editable_translatable_attribute').appendTo('body');
$trans.data('$node', $node).data('attribute', attr);
translation[attr] = $trans[0];
$node.attr(attr, match[2]);
var select2 = $node.data('select2');
if (select2) {
select2.blur();
$node.on('translate', function () {
select2.blur();
});
$node = select2.container.find('input');
}
$node.addClass('o_translatable_attribute').data('translation', translation);
});
});
this.$target_attr = $target.find('.o_translatable_attribute');
this.$target_attribute = $('.o_editable_translatable_attribute');
},
find: function (selector) {
return selector ? this.$target.find(selector).addBack().filter(selector) : this.$target;
......@@ -94,10 +158,11 @@ var Translate = Widget.extend({
this.$el.show();
this.trigger("edit");
},
onChange: function (node) {
rte_changed: function (node) {
var $node = $(node);
var trans = this.getTranlationObject($node[0]);
$node.toggleClass('o_dirty', trans.value !== $node.html().replace(/[ \t\n\r]+/, ' '));
this.$('button[data-action=save]').prop('disabled', !$('.o_editable.o_dirty').length);
},
getTranlationObject: function (node) {
var $node = $(node);
......@@ -113,14 +178,48 @@ var Translate = Widget.extend({
}
return trans;
},
__unbind_click: function (event) {
if (event.ctrlKey || !$(event.target).is(':o_editable')) {
return;
}
event.preventDefault();
event.stopPropagation();
},
__translate_attribute: function (event) {
if (event.ctrlKey) {
return;
}
event.preventDefault();
event.stopPropagation();
if (event.type !== 'click') {
return;
}
new Translate_Modal(event.data, event.target).appendTo('body');
},
markTranslatableNodes: function (node) {
var self = this;
this.$target.each(function () {
this.$target.add(this.$target_attribute).each(function () {
var $node = $(this);
var trans = self.getTranlationObject(this);
trans.value = (trans.value ? trans.value : $node.html() ).replace(/[ \t\n\r]+/, ' ');
});
this.$target.parent().on('click', unbind_click);
this.$target.parent().prependEvent('click', this, this.__unbind_click);
// attributes
this.$target_attr.each(function () {
var $node = $(this);
var translation = $node.data('translation');
_.each(translation, function (node, attr) {
var trans = self.getTranlationObject(node);
trans.value = (trans.value ? trans.value : $node.html() ).replace(/[ \t\n\r]+/, ' ');
$node.attr('data-oe-translation-state', (trans.state || 'to_translate'));
});
});
this.$target_attr.prependEvent('mousedown click mouseup', this, this.__translate_attribute);
console.info('Click on CTRL when you click in an translatable area to have the default behavior');
},
unarkTranslatableNode: function () {
......@@ -147,6 +246,7 @@ var Translate = Widget.extend({
this.unarkTranslatableNode();
this.trigger("cancel");
this.$el.hide();
window.onbeforeunload = null;
},
destroy: function () {
this.cancel();
......
......@@ -11,7 +11,7 @@
</t>
<t t-name="web_editor.dialog">
<div class="modal note-link-dialog" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal web_editor-dialog" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
......
......@@ -11,4 +11,23 @@
</div>
</t>
<t t-name="web_editor.translator.attributes">
<div class="modal web_editor-dialog" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 class="modal-title">Translate Attribute</h3>
</div>
<div class="modal-body">
<div class="form-group"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary save">Close</button>
</div>
</div>
</div>
</div>
</t>
</templates>
......@@ -66,7 +66,7 @@ li > p {
}
font[style*='background'], font[class*='bg-'] {
padding: 0 2px
padding: 0 2px;
}
.o_ul_toggle_self, .o_ul_toggle_next {
......@@ -179,7 +179,6 @@ body > nav.navbar {
padding-top: 34px;
}
}
/* ----- BOOTSTRAP FIX ----- */
.col-md-12 {
float: left;
......@@ -754,21 +753,25 @@ div.carousel .item.text_only .container > .carousel-image {
#oe_main_menu_navbar .navbar-nav.navbar-right:last-child {
margin-right: 0 !important;
}
.container nav#oe_main_menu_navbar {
position: inherit;
}
.oe_search_clear {
position: absolute;
display:none;
cursor: pointer;
z-index: 2;
right: 42px;
color: #939393;
padding: 10px 0;
top: 1px;
}
}
.oe_search_box {
padding-right: 23px;
padding-right: 23px;
}
.note-editor button {
height: 30px;
}
/*# sourceMappingURL=website.css.map */
......@@ -632,4 +632,7 @@ div.carousel
top: 1px
.oe_search_box
padding-right: 23px
padding-right: 23px
.note-editor button
height: 30px
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment