[MERGE] forward port branch saas-11.1 up to 7e469eb77a

This commit is contained in:
Christophe Simonis
2018-02-01 18:20:28 +01:00
112 changed files with 1165 additions and 671 deletions
@@ -409,7 +409,19 @@ var FieldTextHtml = AbstractField.extend({
var layoutInfo = self.editor.rte.editable().data('layoutInfo');
$.summernote.pluginEvents.codeview(undefined, undefined, layoutInfo, false);
}
var $ancestors = self.$iframe.filter(':not(:visible)').parentsUntil(':visible').addBack();
var ancestorsStyle = [];
// temporarily force displaying iframe (needed for firefox)
_.each($ancestors, function (el) {
var $el = $(el);
ancestorsStyle.unshift($el.attr('style') || null);
$el.css({display: 'initial', visibility: 'hidden', height: 1});
});
self.editor.snippetsMenu && self.editor.snippetsMenu.cleanForSave();
_.each($ancestors, function (el) {
var $el = $(el);
$el.attr('style', ancestorsStyle.pop());
});
self._setValue(self.$content.html());
});
},
+13 -21
View File
@@ -281,8 +281,10 @@ var RTEWidget = Widget.extend({
.each(function () {
var $node = $(this);
// fallback for firefox iframe display:none see https://github.com/odoo/odoo/pull/22610
var computedStyles = window.getComputedStyle(this) || window.parent.getComputedStyle(this);
// add class to display inline-block for empty t-field
if (window.getComputedStyle(this).display === 'inline' && $node.data('oe-type') !== 'image') {
if (computedStyles.display === 'inline' && $node.data('oe-type') !== 'image') {
$node.addClass('o_is_inline_editable');
}
});
@@ -651,26 +653,16 @@ var RTEWidget = Widget.extend({
self.historyRecordUndo($target, 'activate', true);
});
// To Fix Google Chrome Tripleclick Issue, which selects the ending
// whitespace characters (so Tripleclicking then typing text will remove
// the whole paragraph instead of its content).
// http://stackoverflow.com/questions/38467334/why-does-google-chrome-always-add-space-after-selected-text
if ($.browser.chrome === true && ev.originalEvent.detail === 3) {
var currentSelection = range.create();
if (currentSelection.sc.parentNode === currentSelection.ec) {
_selectSC(currentSelection);
} else if (currentSelection.eo === 0) {
var $hasNext = $(currentSelection.sc).parent();
while (!$hasNext.next().length && !$hasNext.is('body')) {
$hasNext = $hasNext.parent();
}
if ($hasNext.next()[0] === currentSelection.ec) {
_selectSC(currentSelection);
}
}
}
function _selectSC(selection) {
range.create(selection.sc, selection.so, selection.sc, selection.sc.length).select();
// Browsers select different content from one to another after a
// triple click (especially: if triple-clicking on a paragraph on
// Chrome, blank characters of the element following the paragraph are
// selected too)
//
// The triple click behavior is reimplemented for all browsers here
if (ev.originalEvent.detail === 3) {
// Select the whole content inside the deepest DOM element that was
// triple-clicked
range.create(ev.target, 0, ev.target, ev.target.childNodes.length).select();
}
},
});
@@ -421,6 +421,9 @@ dom.isImg = function (node) {
};
var fn_is_forbidden_node = dom.isForbiddenNode || function () {};
dom.isForbiddenNode = function (node) {
if (node.tagName === "BR") {
return false;
}
return fn_is_forbidden_node(node) || $(node).is(".media_iframe_video");
};
var fn_is_img_font = dom.isImgFont || function () {};
@@ -694,10 +694,16 @@ dom.isRemovableEmptyNode = function (node) {
dom.isForbiddenNode = function (node) {
return node.tagName === "BR" || $(node).is(".fa, img");
};
dom.listBetween = function (sc, ec) {
/**
* @todo 'so' and 'eo' were added as a bugfix and are not given everytime. They
* however should be as the function may be wrong without them (for example,
* when asking the list between an element and its parent, as there is no path
* from the beginning of the former to the beginning of the later).
*/
dom.listBetween = function (sc, ec, so, eo) {
var nodes = [];
var ancestor = dom.commonAncestor(sc, ec);
dom.walkPoint({'node': sc, 'offset': 0}, {'node': ec, 'offset': 0}, function (point) {
dom.walkPoint({'node': sc, 'offset': so || 0}, {'node': ec, 'offset': eo || 0}, function (point) {
if (ancestor !== point.node || ancestor === sc || ancestor === ec) {
nodes.push(point.node);
}
@@ -1869,7 +1875,7 @@ $.summernote.pluginEvents.formatBlock = function (event, editor, layoutInfo, sTa
}
// fix by odoo because if you select a style in a li with no p tag all the ul is wrapped by the style tag
var nodes = dom.listBetween(r.sc, r.ec);
var nodes = dom.listBetween(r.sc, r.ec, r.so, r.eo);
for (var i=0; i<nodes.length; i++) {
if (dom.isBR(nodes[i]) || (dom.isText(nodes[i]) && dom.isVisibleText(nodes[i])) || dom.isB(nodes[i]) || dom.isU(nodes[i]) || dom.isS(nodes[i]) || dom.isI(nodes[i]) || dom.isFont(nodes[i])) {
var ancestor = dom.ancestor(nodes[i], isFormatNode);
@@ -1984,6 +1990,14 @@ eventHandler.modules.editor.currentStyle = function (target) {
if (r)
styleInfo.image = r.isOnImg();
}
// Fix when the target is a link: the text-align buttons state should
// indicate the alignment of the link in the parent, not the text inside
// the link (which is not possible to customize with summernote). Summernote fixed
// this in their newest version... by just not showing the active button
// for alignments.
if (styleInfo.anchor) {
styleInfo['text-align'] = $(styleInfo.anchor).parent().css('text-align');
}
return styleInfo;
};
@@ -742,7 +742,7 @@ var ViewEditor = Widget.extend({
var text = data.text || '';
if (!isSelected) {
text = Array($elem.data('level')).join('-') + ' ' + text;
text = Array($elem.data('level') + 1).join('-') + ' ' + text;
}
var $div = $('<div/>', {
text: text,
@@ -136,12 +136,12 @@ QUnit.test('field html_frame widget', function (assert) {
model: 'mass.mailing',
data: this.data,
arch: '<form string="Partners">' +
'<field name="body" widget="html_frame" options="{\'editor_url\': \'/test\'}"/>' +
'<field name="body" widget="html_frame" options="{\'editor_url\': \'/logo\'}"/>' +
'</form>',
res_id: 1,
session: {user_context: {lang: "en_us"}},
mockRPC: function (route) {
if (_.str.startsWith(route, '/test')) {
if (_.str.startsWith(route, '/logo')) {
// those tests will be executed twice, once in readonly and once in edit
assert.ok(route.search('model=mass.mailing') > 0,
"the route should specify the correct model");
@@ -200,7 +200,7 @@ QUnit.test('html_frame does not crash when saving in readonly', function (assert
data: this.data,
arch: '<form string="Partners">' +
'<sheet>' +
'<field name="body" widget="html_frame" options="{\'editor_url\': \'/test\'}"/>' +
'<field name="body" widget="html_frame" options="{\'editor_url\': \'/logo\'}"/>' +
'</sheet>' +
'</form>',
res_id: 1,
@@ -208,7 +208,7 @@ QUnit.test('html_frame does not crash when saving in readonly', function (assert
if (args.method) {
assert.step(args.method);
}
if (_.str.startsWith(route, '/test')) {
if (_.str.startsWith(route, '/logo')) {
// manually call the callback to simulate that the iframe has
// been loaded (note: just the content, not the editor)
window.odoo[$.deparam(route).callback + '_content'].call();
@@ -237,7 +237,7 @@ QUnit.test('html_frame does not crash when saving in edit mode (editor not loade
arch: '<form string="Partners">' +
'<sheet>' +
'<field name="display_name"/>' +
'<field name="body" widget="html_frame" options="{\'editor_url\': \'/test\'}"/>' +
'<field name="body" widget="html_frame" options="{\'editor_url\': \'/logo\'}"/>' +
'</sheet>' +
'</form>',
res_id: 1,
@@ -245,7 +245,7 @@ QUnit.test('html_frame does not crash when saving in edit mode (editor not loade
if (args.method) {
assert.step(args.method);
}
if (_.str.startsWith(route, '/test')) {
if (_.str.startsWith(route, '/logo')) {
// manually call the callback to simulate that the iframe has
// been partially loaded (just the content, not the editor)
window.odoo[$.deparam(route).callback + '_content']();
@@ -279,7 +279,7 @@ QUnit.test('html_frame saving in edit mode (editor and content fully loaded)', f
arch: '<form string="Partners">' +
'<sheet>' +
'<field name="display_name"/>' +
'<field name="body" widget="html_frame" options="{\'editor_url\': \'/test\'}"/>' +
'<field name="body" widget="html_frame" options="{\'editor_url\': \'/logo\'}"/>' +
'</sheet>' +
'</form>',
res_id: 1,
@@ -290,7 +290,7 @@ QUnit.test('html_frame saving in edit mode (editor and content fully loaded)', f
writeDeferred.resolve();
}
}
if (_.str.startsWith(route, '/test')) {
if (_.str.startsWith(route, '/logo')) {
// manually call the callback to simulate that the iframe has
// been fully loaded (content + editor)
var callback = $.deparam(route).callback;