[IMP] website: create a new web editor in the backend to edit html field with the website builder

This commit is contained in:
Christophe Matthieu
2015-02-12 11:58:12 +01:00
committed by Julien De Coster
parent a46a060f0f
commit 28ed28f945
23 changed files with 1607 additions and 1224 deletions
+1 -1
View File
@@ -413,7 +413,7 @@ openerp.EventDispatcherMixin = _.extend({}, openerp.ParentedMixin, {
},
on: function(events, dest, func) {
var self = this;
if (!(func instanceof Function)) {
if (typeof func !== "function") {
throw new Error("Event handler must be a function.");
}
events = events.split(/\s+/);
+2 -2
View File
@@ -843,9 +843,9 @@ instance.web.FormView = instance.web.View.extend(instance.web.form.FieldManagerM
// on 'create' : save all non readonly fields
// on 'edit' : save non readonly modified fields
if (!f.get("readonly")) {
values[f.name] = f.get_value();
values[f.name] = f.get_value(true);
} else {
readonly_values[f.name] = f.get_value();
readonly_values[f.name] = f.get_value(true);
}
}
}
+1
View File
@@ -18,6 +18,7 @@ OpenERP Website CMS
'security/ir.model.access.csv',
'security/ir_ui_view.xml',
'views/website_templates.xml',
'views/website.backend.xml',
'views/website_views.xml',
'views/snippets.xml',
'views/themes.xml',
+20
View File
@@ -537,3 +537,23 @@ class Website(openerp.addons.web.controllers.main.Home):
if res:
return res
return request.redirect('/')
#------------------------------------------------------
# Backend html field
#------------------------------------------------------
@http.route('/website/field/html', type='http', auth="public", website=True)
def FieldTextHtml(self, model=None, res_id=None, field=None, callback=None, **kwargs):
record = None
if model and res_id:
res_id = int(res_id)
record = request.registry[model].browse(request.cr, request.uid, res_id, request.context)
datarecord = json.loads(kwargs['datarecord'])
kwargs.update({
'content': record and getattr(record, field) or "",
'model': model,
'res_id': res_id,
'field': field,
'datarecord': datarecord
})
return request.website.render(kwargs.get("template") or "website.FieldTextHtml", kwargs)
+27 -1
View File
@@ -178,11 +178,37 @@
.oe_structure.oe_empty:empty, [data-oe-type=html]:empty, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child {
background-image: url("/website/static/src/img/edit_here.png") !important;
}
.oe_structure.oe_empty:empty:before, [data-oe-type=html]:empty:before, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child:before, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child:before {
content: "Press The Top-Left Edit Button" !important;
}
.o_editable.oe_structure.oe_empty > p:empty:only-child, .o_editable[data-oe-type=html] > p:empty:only-child {
color: #aaa;
}
.o_editable.oe_structure.oe_empty:empty, .o_editable[data-oe-type=html]:empty, .o_editable.oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, .o_editable[data-oe-type=html] > .oe_drop_zone.oe_insert:only-child, .o_editable.oe_structure.oe_empty > p:empty:only-child, .o_editable[data-oe-type=html] > p:empty:only-child {
background-image: none !important;
}
.o_editable.oe_structure.oe_empty:empty:before, .o_editable[data-oe-type=html]:empty:before, .o_editable.oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child:before, .o_editable[data-oe-type=html] > .oe_drop_zone.oe_insert:only-child:before, .o_editable.oe_structure.oe_empty > p:empty:only-child:before, .o_editable[data-oe-type=html] > p:empty:only-child:before {
content: "Write your text here" !important;
}
.o_editable.oe_structure.oe_empty:empty:focus:before, .o_editable[data-oe-type=html]:empty:focus:before, .o_editable.oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child:focus:before, .o_editable[data-oe-type=html] > .oe_drop_zone.oe_insert:only-child:focus:before, .o_editable.oe_structure.oe_empty > p:empty:only-child:focus:before, .o_editable[data-oe-type=html] > p:empty:only-child:focus:before {
display: none;
}
#oe_snippets ~ #wrapwrap .oe_structure.oe_empty:empty, #oe_snippets ~ #wrapwrap [data-oe-type=html]:empty, #oe_snippets ~ #wrapwrap .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, #oe_snippets ~ #wrapwrap [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child {
background-image: url("/website/static/src/img/drag_here.png") !important;
}
#oe_snippets ~ #wrapwrap .oe_structure.oe_empty:empty:before, #oe_snippets ~ #wrapwrap [data-oe-type=html]:empty:before, #oe_snippets ~ #wrapwrap .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child:before, #oe_snippets ~ #wrapwrap [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child:before {
content: "Drag Building Blocks Here" !important;
}
.oe_structure.oe_empty:empty, [data-oe-type=html]:empty, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child {
background-image: none;
background-repeat: no-repeat;
background-position: center;
height: 220px !important;
}
[data-oe-type=html].oe_no_empty:empty:before {
content: "" !important;
}
+24 -3
View File
@@ -148,12 +148,33 @@
.o_editable .media_iframe_video .css_editable_mode_display
display: block !important
.oe_structure.oe_empty:empty, [data-oe-type=html]:empty, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child
background-image: url('/website/static/src/img/edit_here.png') !important
&:before
content: 'Press The Top-Left Edit Button' !important
.oe_structure.oe_empty:empty:before, [data-oe-type=html]:empty:before, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child:before, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child:before
content: 'Press The Top-Left Edit Button' !important
.o_editable
&.oe_structure.oe_empty > p:empty:only-child, &[data-oe-type=html] > p:empty:only-child
color: #aaa
&.oe_structure.oe_empty:empty, &[data-oe-type=html]:empty, &.oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, &[data-oe-type=html] > .oe_drop_zone.oe_insert:only-child, &.oe_structure.oe_empty > p:empty:only-child, &[data-oe-type=html] > p:empty:only-child
background-image: none !important
&:before
content: 'Write your text here' !important
&:focus:before
display: none
#oe_snippets ~ #wrapwrap
.oe_structure.oe_empty:empty, [data-oe-type=html]:empty, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child
background-image: url('/website/static/src/img/drag_here.png') !important
&:before
content: 'Drag Building Blocks Here' !important
.oe_structure.oe_empty:empty, [data-oe-type=html]:empty, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child
background-image: none
background-repeat: no-repeat
background-position: center
height: 220px !important
[data-oe-type=html].oe_no_empty:empty:before
content: '' !important
+47 -38
View File
@@ -1,25 +1,24 @@
/* ---- SNIPPET EDITOR ---- {{{ */
#oe_snippets .scroll, #oe_snippets .o_arrow {
#oe_snippets #o_left_bar, #oe_snippets #o_arrow {
position: fixed;
top: 34px;
left: 0px;
bottom: 0;
padding-top: 10px;
background: #282828;
-moz-box-shadow: 0px 10px 10px -10px black inset;
-webkit-box-shadow: 0px 10px 10px -10px black inset;
box-shadow: 0px 10px 10px -10px black inset;
}
#oe_snippets .o_arrow {
#oe_snippets #o_arrow {
z-index: 1009;
width: 24px;
opacity: 0.75;
}
#oe_snippets .o_arrow > * {
#oe_snippets #o_arrow > * {
position: absolute;
color: white;
}
#oe_snippets .o_arrow div {
#oe_snippets #o_arrow div {
-moz-transform: translateX(-36%) rotate(-90deg);
-ms-transform: translateX(-36%) rotate(-90deg);
-webkit-transform: translateX(-36%) rotate(-90deg);
@@ -27,61 +26,70 @@
top: 50%;
white-space: nowrap;
}
#oe_snippets .o_arrow .fa {
#oe_snippets #o_arrow .fa {
width: 100%;
left: 40%;
}
#oe_snippets .scroll {
left: -220px;
#oe_snippets #o_left_bar {
left: -228px;
z-index: 1010;
width: 200px;
width: 208px;
-moz-transition: all 500ms ease;
-o-transition: all 500ms ease;
-webkit-transition: all 500ms ease;
transition: all 500ms ease;
}
#oe_snippets.o_open .scroll {
#oe_snippets #o_left_bar ul {
text-align: center;
margin: 0;
padding: 6px 0;
list-style-type: none;
}
#oe_snippets #o_left_bar ul li {
display: inline-block;
padding: 0 3px;
}
#oe_snippets #o_left_bar ul li a {
color: #aaa;
}
#oe_snippets #o_left_bar ul li .fa-stack {
overflow: hidden;
}
#oe_snippets #o_left_bar ul li.active a.fa, #oe_snippets #o_left_bar ul li.active .fa-stack-1x {
color: #428bca;
}
#oe_snippets.o_open #o_left_bar {
left: 0;
}
#oe_snippets .nav {
float: none;
border-bottom: none !important;
margin-bottom: 6px;
}
#oe_snippets .nav > li {
display: block;
float: none;
}
#oe_snippets .nav > li.active {
background: black !important;
}
#oe_snippets .nav > li > a {
padding: 2px 10px !important;
width: 100%;
display: block;
border-radius: 4px;
#oe_snippets .o_panel {
margin: 0;
border: 0;
width: 208px;
}
#oe_snippets .nav > li span {
font-size: 0.8em;
#oe_snippets .o_panel_header {
background: #dff0d8;
padding: 1px 8px;
color: #414141;
text-align: center;
}
#oe_snippets .pill-content {
border: 0;
#oe_snippets .o_panel_header .fa-stack {
overflow: hidden;
font-size: 1em;
}
#oe_snippets .tab-content {
#oe_snippets .o_panel_body {
white-space: normal;
background: black;
margin-left: 3px;
padding: 7px 3px;
}
#oe_snippets .tab-content > div {
#oe_snippets .o_panel_body > div {
background: black;
}
#oe_snippets .tab-content > div label {
#oe_snippets .o_panel_body > div label {
width: 44px;
color: #fff;
padding-left: 10px;
}
#oe_snippets .tab-content > div label div {
#oe_snippets .o_panel_body > div label div {
width: 100px;
text-align: center;
-moz-transform: translate(-39px, 44px);
@@ -97,8 +105,9 @@
display: inline-block;
vertical-align: top;
width: 93px;
margin-left: 1px;
margin-top: 0px;
margin-left: 3px;
margin-right: 3px;
margin-top: 1px;
position: relative;
overflow: hidden;
-moz-user-select: -moz-none;
+37 -29
View File
@@ -6,15 +6,14 @@
/* ---- SNIPPET EDITOR ---- {{{ */
#oe_snippets
.scroll, .o_arrow
#o_left_bar, #o_arrow
position: fixed
top: 34px
left: 0px
bottom: 0
padding-top: 10px
background: rgb(40,40,40)
+box-shadow(0px 10px 10px -10px black inset)
.o_arrow
#o_arrow
z-index: 1009
width: 24px
opacity: 0.75
@@ -28,36 +27,44 @@
.fa
width: 100%
left: 40%
.scroll
left: -220px
#o_left_bar
left: -228px
z-index: 1010
width: 200px
width: 208px
@include transition(all 500ms ease)
&.o_open .scroll
ul
text-align: center
margin: 0
padding: 6px 0
list-style-type: none
li
display: inline-block
padding: 0 3px
a
color: #aaa
.fa-stack
overflow: hidden
li.active a.fa, li.active .fa-stack-1x
color: #428bca
&.o_open #o_left_bar
left: 0
.nav
float: none
border-bottom: none !important
margin-bottom: 6px
> li
display: block
float: none
&.active
background: black !important
> a
padding: 2px 10px !important
width: 100%
display: block
border-radius: 4px
border: 0
span
font-size: 0.8em
.pill-content
.o_panel
margin: 0
border: 0
.tab-content
width: 208px
.o_panel_header
background: #dff0d8
padding: 1px 8px
color: #414141
text-align: center
.fa-stack
overflow: hidden
font-size: 1em
.o_panel_body
white-space: normal
background: black
margin-left: 3px
padding: 7px 3px
> div
background: rgb(0,0,0)
label
@@ -75,8 +82,9 @@
display: inline-block
vertical-align: top
width: 93px
margin-left: 1px
margin-top: 0px
margin-left: 3px
margin-right: 3px
margin-top: 1px
position: relative
overflow: hidden
+user-select(none)
@@ -3,4 +3,32 @@
}
.oe_WidgetWebsiteButton.success .oe_unpublish {
display: none;
}
.oe_form_field_html iframe {
display: block;
width: 100%;
border: 0;
padding: 0;
margin: 0;
min-height: 300px;
}
.o_form_FieldTextHtml_fullscreen .oe_form_field_html iframe {
position: absolute !important;
left: 0 !important;
right: 0 !important;
top: 0px !important;
bottom: 0 !important;
width: 100% !important;
z-index: 1001 !important;
border: 0;
}
.o_form_FieldTextHtml_fullscreen .modal .oe_form_field_html iframe {
top: 0 !important;
}
.o_form_FieldTextHtml_fullscreen .oe_webclient *, .o_form_FieldTextHtml_fullscreen .modal * {
position: static !important;
top: 0 !important;
left: 0 !important;
overflow: visible !important;
width: auto !important;
}
+34 -21
View File
@@ -105,6 +105,30 @@ div.media_iframe_video.padding-xl iframe {
padding: 32px;
}
.fa-6x {
font-size: 6em;
}
.fa-7x {
font-size: 7em;
}
.fa-8x {
font-size: 8em;
}
.fa-9x {
font-size: 9em;
}
.fa-10x {
font-size: 10em;
}
.fa.center-block {
text-align: center;
}
ul {
list-style-type: disc;
}
@@ -221,8 +245,8 @@ table.table {
table-layout: fixed;
}
#wrapwrap p:empty:after {
content: "⁠";
td {
min-width: 20px;
}
/* ----- Editor (for public user, like forum) ----- */
@@ -230,6 +254,10 @@ table.table {
margin-left: 0 !important;
}
.note-popover .popover > .arrow {
display: none;
}
/* ----- Snippets Styles ----- */
.para_large {
font-size: 120%;
@@ -309,18 +337,7 @@ nav.navbar + #wrapwrap {
width: 100%;
}
}
/* ---- HACK FOR COVERING UP CK EDITOR BOGUS P INSERTION --- */
.oe_structure.oe_editable.oe_empty:empty, .oe_editable[data-oe-type=html]:empty, .oe_structure.oe_editable.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child {
background-image: url("/website/static/src/img/drag_here.png") !important;
}
.oe_structure.oe_empty:empty, [data-oe-type=html]:empty, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child {
background-image: none;
background-repeat: no-repeat;
background-position: center;
height: 220px !important;
}
/* ---- HACK FOR COVERING UP EDITOR BOGUS P INSERTION --- */
.oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child {
position: static;
}
@@ -329,21 +346,17 @@ nav.navbar + #wrapwrap {
content: " ";
text-align: center;
display: block;
padding-top: 160px;
padding-bottom: 30px;
min-height: 1em;
color: grey;
font-size: 24px;
}
.oe_structure.oe_editable.oe_empty:empty:before, .oe_editable[data-oe-type=html]:empty:before, .oe_structure.oe_editable.oe_empty > .oe_drop_zone.oe_insert:only-child:before, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child:before {
content: "Drag Building Blocks Here" !important;
padding-top: 160px;
}
.css_editable_display {
display: none;
}
/* ---- HACK FOR COVERING UP CK EDITOR BOGUS P INSERTION --- */
/* ---- HACK FOR COVERING UP EDITOR BOGUS P INSERTION --- */
.navbar .nav > li > p {
margin-bottom: 0px;
}
+22 -22
View File
@@ -70,6 +70,19 @@ div.media_iframe_video
&.padding-xl iframe
padding: 32px
.fa-6x
font-size: 6em
.fa-7x
font-size: 7em
.fa-8x
font-size: 8em
.fa-9x
font-size: 9em
.fa-10x
font-size: 10em
.fa.center-block
text-align: center
ul
list-style-type: disc
li > ul
@@ -148,17 +161,17 @@ hr
table.table
table-layout: fixed
// add {WORD JOINER} (equivalent to deprecated ZERO WIDTH NO-BREAK SPACE) at
// the beginning of paragraphs so they don't "disappear" after saving when
// used solely for spacing.
#wrapwrap p:empty:after
content: '\2060'
td
min-width: 20px
/* ----- Editor (for public user, like forum) ----- */
.note-toolbar
margin-left: 0 !important
.note-popover .popover > .arrow
display: none
/* ----- Snippets Styles ----- */
.para_large
@@ -227,17 +240,7 @@ nav.navbar + #wrapwrap
.table .img-responsive
width: 100%
/* ---- HACK FOR COVERING UP CK EDITOR BOGUS P INSERTION --- */
.oe_structure.oe_editable.oe_empty:empty, .oe_editable[data-oe-type=html]:empty, .oe_structure.oe_editable.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child
background-image: url('/website/static/src/img/drag_here.png') !important
.oe_structure.oe_empty:empty, [data-oe-type=html]:empty, .oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child
background-image: none
background-repeat: no-repeat
background-position: center
height: 220px !important
/* ---- HACK FOR COVERING UP EDITOR BOGUS P INSERTION --- */
.oe_structure.oe_empty > .oe_drop_zone.oe_insert:only-child, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child
position: static
@@ -245,18 +248,15 @@ nav.navbar + #wrapwrap
content: ' '
text-align: center
display: block
padding-top: 160px
padding-bottom: 30px
min-height: 1em
color: grey
font-size: 24px
.oe_structure.oe_editable.oe_empty:empty:before, .oe_editable[data-oe-type=html]:empty:before, .oe_structure.oe_editable.oe_empty > .oe_drop_zone.oe_insert:only-child:before, [data-oe-type=html] > .oe_drop_zone.oe_insert:only-child:before
content: 'Drag Building Blocks Here' !important
padding-top: 160px
.css_editable_display
display: none
/* ---- HACK FOR COVERING UP CK EDITOR BOGUS P INSERTION --- */
/* ---- HACK FOR COVERING UP EDITOR BOGUS P INSERTION --- */
.navbar .nav > li > p
margin-bottom: 0px
@@ -0,0 +1,55 @@
(function () {
'use strict';
window.top.openerp[callback+"_set_value"] = function (value, fields_values) {
var $editable = $("#wrapwrap .o_editable:first");
if (value !== $editable.html()) {
openerp.website.editor_bar.rte.historyRecordUndo($editable);
openerp.website.editor_bar.snippets.make_active(false);
$editable.html(value);
}
};
openerp.website.EditorBar.include({
start: function () {
var res = this._super.apply(this, arguments);
if (location.search.indexOf("enable_editor") !== -1) {
this.on('rte:ready', this, function () {
$("#website-top-edit").hide();
if (window.top.openerp[callback+"_editor"]) {
window.top.openerp[callback+"_editor"](this);
}
var $editable = $("#wrapwrap .o_editable:first");
setTimeout(function () {
$($editable.find("*").filter(function () {return !this.children.length;}).first()[0] || $editable)
.focusIn().trigger("mousedown").trigger("keyup");
},0);
this.rte.on('change', this, function () {
window.top.openerp[callback+"_downup"]($editable.prop('innerHTML'));
});
});
var style = document.createElement("style");
style.textContent = "#wrapwrap > main > * { margin-top: 50px; }";
$("head").append(style);
this.on("snippets:ready", this, function () {
$(window.top).trigger("resize");
});
} else if (window.top.openerp[callback+"_editor"]) {
window.top.openerp[callback+"_editor"](this);
}
return res;
}
});
openerp.website.snippet.BuildingBlock.include({
_get_snippet_url: function () {
return snippets_url;
}
});
})();
+147 -15
View File
@@ -1,21 +1,153 @@
openerp.website = function(instance) {
var _t = instance.web._t;
(function () {
'use strict';
instance.web.form.WidgetWebsiteButton = instance.web.form.AbstractField.extend({
template: 'WidgetWebsiteButton',
var widgets = openerp.web.form.widgets;
while(!widgets.map.html) {
widgets = widgets.parent;
}
widgets.map.html = "openerp.web.form.FieldTextHtml";
var widget = openerp.web.form.AbstractField.extend(openerp.web.form.ReinitializeFieldMixin);
openerp.web.form.FieldTextHtml = widget.extend({
template: 'FieldTextHtml',
start: function () {
var self = this;
this.callback = _.uniqueId('FieldTextHtml_');
window.openerp[this.callback+"_editor"] = function (EditorBar) {
self.on_editor_loaded(EditorBar);
};
window.openerp[this.callback+"_content"] = function (EditorBar) {
self.on_content_loaded();
};
window.openerp[this.callback+"_updown"] = null;
window.openerp[this.callback+"_downup"] = function (value) {
self.dirty = true;
self.internal_set_value(value);
self.trigger('changed_value');
self.resize();
};
// init jqery objects
this.$iframe = this.$el.find('iframe');
this.document = null;
this.$body = $();
this.$content = $();
// init resize
this.resize = function resize() {
if ($("body").hasClass("o_form_FieldTextHtml_fullscreen")) {
self.$iframe.css('height', $("body").hasClass('o_form_FieldTextHtml_fullscreen') ? (document.body.clientHeight - self.$iframe.offset().top) + 'px' : '');
} else if (self.get('effective_readonly')) {
var height = 110;
try {
height += self.$body.height();
height += parseInt(self.$content.parent().css("margin-top"));
} catch (e) {}
self.$iframe.css("height", height+"px");
} else {
self.$iframe.css("height", (self.$body.find("#oe_snippets").length ? 500 : 300) + "px");
}
};
$(window).on('resize', self.resize);
return this._super();
},
get_url: function () {
var src = this.options.editor_url ? this.options.editor_url+"?" : "/website/field/html?";
var datarecord = this.view.get_fields_values();
var attr = {
'model': this.view.model,
'field': this.name,
'res_id': datarecord.id || '',
'callback': this.callback
};
if (this.options.snippets) {
attr['snippets'] = this.options.snippets;
}
if (!this.get("effective_readonly")) {
attr['enable_editor'] = 1;
}
if (openerp.session.debug) {
attr['debug'] = 1;
}
for (var k in attr) {
src += "&"+k+"="+attr[k];
}
delete datarecord[this.name];
src += "&datarecord="+ encodeURIComponent(JSON.stringify(datarecord));
return src;
},
initialize_content: function() {
this.$iframe = this.$el.find('iframe');
this.document = null;
this.$body = $();
this.$content = $();
this.dirty = false;
this.editor = false;
window.openerp[this.callback+"_set_value"] = function () {};
this.$iframe.attr("src", this.get_url());
},
on_content_loaded: function () {
var self = this;
this.document = this.$iframe.contents()[0];
this.$body = $("body", this.document);
this.$content = this.$body.find("#wrapwrap .o_editable:first");
setTimeout(this.resize,0);
},
on_editor_loaded: function (EditorBar) {
var self = this;
this.editor = EditorBar;
$("body").on('click', function (event) {
if ($("body").hasClass('o_form_FieldTextHtml_fullscreen')) {
$("body").removeClass("o_form_FieldTextHtml_fullscreen");
self.$iframe.css('height', '');
event.preventDefault();
event.stopPropagation();
}
});
setTimeout(function () {
var $fullscreen = $('<span class="btn btn-primary" style="margin: 5px;padding: 1px; position: fixed; top: 0; right: 0; z-index: 2000;"><span class="o_fullscreen fa fa-arrows-alt" style="color: white;margin: 3px 5px;"></span></span>');
var $nav = $("#website-top-navbar", self.document).append($fullscreen);
$fullscreen.on('click', function () {
$("body").toggleClass("o_form_FieldTextHtml_fullscreen");
self.resize();
});
setTimeout(self.resize,0);
}, 500);
},
render_value: function() {
this._super();
this.$()
.toggleClass("success", this.get_value())
.toggleClass("danger", !this.get_value());
if (this.node.attrs.class) {
this.$el.addClass(this.node.attrs.class);
if (!this.$content) {
return;
}
if(window.openerp[this.callback+"_set_value"]) {
window.openerp[this.callback+"_set_value"](this.get('value') || '', this.view.get_fields_values());
this.resize();
}
},
is_false: function() {
return this.get('value') === false || this.get('value') === "";
},
get_value: function(save_mode) {
if (save_mode && this.editor && this.editor.snippets && this.dirty) {
this.editor.snippets.clean_for_save();
this.internal_set_value( this.$content.prop('innerHTML') );
}
return this.get('value');
},
destroy: function () {
$(window).off('resize', self.resize);
delete window.openerp[this.callback];
delete window.openerp[this.callback+"_content"];
delete window.openerp[this.callback+"_updown"];
}
});
instance.web.form.widgets = instance.web.form.widgets.extend({
'website_button': 'instance.web.form.WidgetWebsiteButton',
});
};
})();
+67 -162
View File
@@ -51,6 +51,10 @@ define(['summernote/summernote'], function () {
var $linkPopover = $popover.find('.note-link-popover');
var $airPopover = $popover.find('.note-air-popover');
if (window === window.top) {
$popover.children().addClass("hidden-xs");
}
//////////////// image popover
// add center button for images
@@ -335,7 +339,7 @@ define(['summernote/summernote'], function () {
eventHandler.editor.resizefa = function ($editable, sValue) {
var $target = $(getImgTarget());
$editable.data('NoteHistory').recordUndo();
$target.removeClass('fa-1x fa-2x fa-3x fa-4x fa-5x');
$target.attr('class', $target.attr('class').replace(/\s*fa-[0-9]+x/g, ''));
if (+sValue > 1) {
$target.addClass('fa-'+sValue+'x');
}
@@ -470,41 +474,10 @@ define(['summernote/summernote'], function () {
$(data.sc).closest('.o_editable').data('range', r);
return r;
}
$(document).mousedown(function (event) {
if (!$(event.target).closest(".o_editable").length) {
return;
}
var r = range.create();
if (initial_data.range && event.shiftKey) {
initial_data.range.select();
}
if (event.shiftKey) {
var rect = r && r.getClientRects();
initial_data.rect = rect && rect.length ? rect[0] : { top: 0, left: 0 };
}
initial_data.event = event;
});
$(document).mouseup(function (event) {
if (!$(event.target).closest(".o_editable").length) {
return;
}
if (!initial_data.range || !event.shiftKey) {
setTimeout(function () {
initial_data.range = range.create();
},0);
}
});
function summernote_mouseup (event) {
if ($(event.target).closest("#website-top-navbar, .note-popover").length) {
return;
}
if ($(event.target).is(":o_editable")) {
var a = summernote_ie_fix(event, function (node) { return node.tagName === "A"; });
if (a) {
range.create().select();
}
}
// don't rerange if simple click
if (initial_data.event) {
var dx = event.clientX - (event.shiftKey ? initial_data.rect.left : initial_data.event.clientX);
@@ -513,17 +486,36 @@ define(['summernote/summernote'], function () {
reRangeSelect(event, dx, dy);
}
}
if (!$(event.target).closest(".o_editable").length) {
return;
}
if (!initial_data.range || !event.shiftKey) {
setTimeout(function () {
initial_data.range = range.create();
},0);
}
}
var remember_selection;
function summernote_mousedown (event) {
history.splitNext();
var $editable = $(event.target).closest(".o_editable");
if (!!document.documentMode) {
summernote_ie_fix(event, function (node) { return node.tagName === "DIV" || node.tagName === "IMG" || (node.dataset && node.dataset.oeModel); });
} else if (last_div && event.target !== last_div && last_div.tagName === "A") {
summernote_ie_fix(event, function (node) { return node.dataset && node.dataset.oeModel; });
} else if (last_div && event.target !== last_div) {
if (last_div.tagName === "A") {
summernote_ie_fix(event, function (node) { return node.dataset && node.dataset.oeModel; });
} else if ($editable.length) {
if (summernote_ie_fix(event, function (node) { return node.tagName === "A"; })) {
r = range.create();
r.select();
}
}
}
// remember_selection when click on non editable area
var r = range.create();
if ($(r ? dom.node(r.sc) : event.srcElement || event.target).closest('#website-top-navbar, #oe_main_menu_navbar, .note-popover, .modal').length) {
if (remember_selection && !$(event.target).is('input, select, label, button, a')) {
@@ -536,6 +528,17 @@ define(['summernote/summernote'], function () {
} else if (r && $(dom.node(r.sc)).closest('.o_editable, .note-editable').length) {
remember_selection = r;
}
initial_data.event = event;
// keep selection when click with shift
if (event.shiftKey && $editable.length) {
if (initial_data.range) {
initial_data.range.select();
}
var rect = r && r.getClientRects();
initial_data.rect = rect && rect.length ? rect[0] : { top: 0, left: 0 };
}
}
var last_div;
@@ -790,6 +793,8 @@ define(['summernote/summernote'], function () {
$editable.html(oSnap.contents).scrollTop(oSnap.scrollTop);
$(".oe_overlay").remove();
$(".note-control-selection").hide();
$editable.trigger("content_changed");
if (!oSnap.bookmark) {
return;
@@ -852,7 +857,12 @@ define(['summernote/summernote'], function () {
};
var last;
this.recordUndo = function ($editable, event) {
this.recordUndo = function ($editable, event, internal_history) {
if (!internal_history) {
if (!event || !last || !aUndo[pos-1] || aUndo[pos-1].editable !== $editable[0]) { // don't trigger change for all keypress
$(".o_editable.note-editable").trigger("content_changed");
}
}
if (event) {
if (last && aUndo[pos-1] && aUndo[pos-1].editable !== $editable[0]) {
// => make a snap when the user change editable zone (because: don't make snap for each keydown)
@@ -926,20 +936,7 @@ define(['summernote/summernote'], function () {
website.add_template_file('/website/static/src/xml/website.editor.xml');
website.dom_ready.done(function () {
var is_smartphone = $(document.body)[0].clientWidth < 767;
if (!is_smartphone) {
website.ready().then(website.init_editor);
} else {
var resize_smartphone = function () {
is_smartphone = $(document.body)[0].clientWidth < 767;
if (!is_smartphone) {
$(window).off("resize", resize_smartphone);
website.init_editor();
}
};
$(window).on("resize", resize_smartphone);
}
website.ready().then(website.init_editor);
$(document).on('click', 'a.js_link2post', function (ev) {
ev.preventDefault();
@@ -1049,7 +1046,6 @@ define(['summernote/summernote'], function () {
var saved = {}; // list of allready saved views and data
observer.disconnect();
var defs = $('.o_editable')
.filter('.o_dirty')
.removeAttr('contentEditable')
@@ -1222,7 +1218,7 @@ define(['summernote/summernote'], function () {
* Add a record undo to history
* @param {DOM} target where the dom is changed is editable zone
*/
historyRecordUndo: function ($target) {
historyRecordUndo: function ($target, internal_history) {
var rng = range.create();
var $editable = $($target || (rng && rng.sc)).closest(".o_editable");
if ($editable.length) {
@@ -1240,7 +1236,7 @@ define(['summernote/summernote'], function () {
}
$target = $(rng.sc);
$target.mousedown();
this.history.recordUndo($target);
this.history.recordUndo($target, null, internal_history);
$target.mousedown();
},
/**
@@ -1310,6 +1306,9 @@ define(['summernote/summernote'], function () {
}
$target.trigger('mousedown'); // for activate selection on picture
setTimeout(function () {
self.historyRecordUndo($editable, true);
},0);
}
});
@@ -1336,9 +1335,10 @@ define(['summernote/summernote'], function () {
}
// start element observation
observer.observe(node, OBSERVER_CONFIG);
$(node).one('content_changed', function () {
$node.addClass('o_dirty');
});
$(node).on('content_changed', function () {
self.trigger('change');
});
});
@@ -1392,107 +1392,6 @@ define(['summernote/summernote'], function () {
}
});
/* ----- OBSERVER ---- */
website.Observer = window.MutationObserver || window.WebKitMutationObserver || window.JsMutationObserver;
var OBSERVER_CONFIG = {
childList: true,
attributes: true,
characterData: true,
subtree: true,
attributeOldValue: true,
};
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,
// a/@href, ...)
_(mutations).chain()
.filter(function (m) {
// ignore any SVG target, these blokes are like weird mon
if (m.target && m.target instanceof SVGElement) {
return false;
}
// 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 contenteditable modification
if (m.attributeName === 'contenteditable') { return false; }
if (m.attributeName === 'attributeeditable') { return false; }
// remove content editable attribute from firefox
if (m.attributeName.indexOf('_moz') === 0) {
if (!m.oldValue) {
// remove stupid _moz attributes
$(m.target).filter(function () { return this.attributes[m.attributeName]; }).removeAttr(m.attributeName);
}
return false;
}
// ignore id modification
if (m.attributeName === 'id') { return false; }
// style not change
if (m.attributeName === 'style' && (m.oldValue || "") === (m.target.attributes.style ? m.target.attributes.style.value : "")) { return false; }
// 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 to create editable zone and add dirty class
var change = _.difference(change, ["note-air-editor", "note-editable", "o_dirty", "o_editable", ""]);
return !!change.length;
case 'childList':
// 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;
}
})
.map(function (m) {
var node = m.target;
while (node && (!node.className || node.className.indexOf('o_editable')===-1)) {
node = node.parentNode;
}
if (node) {
$(node).data('last-mutation', m);
}
return node;
})
.compact()
.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<nodes.length; ++i) {
var node = nodes[i];
if (node.nodeType === document.ELEMENT_NODE) {
if (node.nodeName === 'BR' && node.getAttribute('type') === '_moz') {
// <br type="_moz"> appears when focusing RTE in FF, ignore
continue;
} else if (node.nodeName === 'DIV' && $(node).hasClass('oe_drop_zone')) {
// ignore dropzone inserted by snippets
continue
}
}
output.push(node);
}
return output;
}
/* ----- EDITOR: LINK & MEDIA ---- */
website.editor = { };
@@ -2267,8 +2166,12 @@ define(['summernote/summernote'], function () {
});
function getCssSelectors(filter) {
var classes = [];
var cacheCssSelectors = {};
website.editor.getCssSelectors = function(filter) {
var css = [];
if (cacheCssSelectors[filter]) {
return cacheCssSelectors[filter];
}
var sheets = document.styleSheets;
for(var i = 0; i < sheets.length; i++) {
var rules = sheets[i].rules || sheets[i].cssRules;
@@ -2277,17 +2180,19 @@ define(['summernote/summernote'], function () {
var selectorText = rules[r].selectorText;
if (selectorText) {
var match = selectorText.match(filter);
if (match) classes.push(match[1].slice(1, match[1].length));
if (match) {
css.push([match[1], rules[r].cssText.replace(/(^.*\{\s*)|(\s*\}\s*$)/g, '')]);
}
}
}
}
}
return classes;
}
return cacheCssSelectors[filter] = css;
};
function computeFonts() {
_.each(website.editor.fontIcons, function (data) {
data.icons = _.map(getCssSelectors(data.parser), function (css) {
return css.replace(/::?before$/, '');
data.icons = _.map(website.editor.getCssSelectors(data.parser), function (css) {
return css[0].slice(1, css[0].length).replace(/::?before$/, '');
});
});
}
@@ -2366,7 +2271,7 @@ define(['summernote/summernote'], function () {
var self = this;
this.parent.trigger("save", this.media);
var icons = this.icons;
var style = this.media.attributes.style ? this.media.attributes.style.textContent : '';
var style = this.media.attributes.style ? this.media.attributes.style.value : '';
var classes = (this.media.className||"").split(/\s+/);
var non_fa_classes = _.reject(classes, function (cls) {
return self.getFont(cls);
@@ -27,6 +27,9 @@
this.snippets.insertAfter(this.$el);
website.snippet.start_animation(true);
$editable.find("*").off('mousedown mouseup click');
this.snippets.on("snippets:ready", this, function () {
self.trigger("snippets:ready");
});
});
return this._super.apply(this, arguments);
@@ -39,14 +42,6 @@
/* ----- SNIPPET SELECTOR ---- */
var observer = new website.Observer(function (mutations) {
if (!_(mutations).find(function (m) {
return m.type === 'childList' && m.addedNodes.length > 0;
})) {
return;
}
});
$.extend($.expr[':'],{
o_editable: function(node,i,m){
while (node) {
@@ -91,11 +86,6 @@
}
this.$active_snipped_id = false;
this.snippets = [];
observer.observe(document.body, {
childList: true,
subtree: true,
});
},
start: function() {
var self = this;
@@ -122,15 +112,9 @@
};
$(window).on('resize', function () {
if (self.$active_snipped_id) {
if (self.$active_snipped_id && self.$active_snipped_id.data("snippet-editor")) {
self.cover_target(self.$active_snipped_id.data("snippet-editor").$overlay, self.$active_snipped_id);
}
var $scroll = self.$snippet.find('.scroll:first').css("overflow", "");
if ($scroll.children().last().height() + $scroll.children().first().height() + 34 > document.body.clientHeight) {
$scroll.css("overflow", "auto").css("width", "216px");
} else {
$scroll.css("width", "");
}
});
$(document).on('mousemove', function () {
@@ -194,135 +178,191 @@
};
}
},
fetch_snippet_templates: function () {
var self = this;
openerp.jsonRpc(this._get_snippet_url(), 'call', {})
.then(function (html) {
var $html = $(html);
$html.siblings(".scroll").find('> ul li').tooltip({
delay: { "show": 500, "hide": 100 },
container: 'body',
title: function () {
return (navigator.appVersion.indexOf('Mac') > -1 ? 'CMD' : 'CTRL')+'+SHIFT+'+($(this).index()+1);
},
trigger: 'hover',
placement: 'right'
}).on('click', function () {$(this).tooltip('hide');});
// t-snippet
$html.find('> .tab-content > div > [data-oe-type="snippet"]').each(function () {
var $div = $('<div/>').insertAfter(this).append(this).attr('name', $(this).data('oe-name'));
});
// end
var selector = [];
var $styles = $html.find("[data-js], [data-selector]");
$styles.each(function () {
var $style = $(this);
var no_check = $style.data('no-check');
var option_id = $style.data('js');
var option = {
'option' : option_id,
'base_selector': $style.data('selector'),
'selector': self._add_check_selector($style.data('selector'), no_check),
'$el': $style,
'drop-near': $style.data('drop-near') && self._add_check_selector($style.data('drop-near'), no_check),
'drop-in': $style.data('drop-in') && self._add_check_selector($style.data('drop-in'), no_check),
'data': $style.data()
};
website.snippet.templateOptions.push(option);
selector.push(option.selector);
});
$styles.addClass("hidden");
website.snippet.globalSelector = {
closest: function ($from) {
var $temp;
var $target;
var len = selector.length;
for (var i = 0; i<len; i++) {
$temp = selector[i].closest($from, $target && $target[0]);
if (!$target || $temp.length) {
$target = $temp;
}
}
return $target;
},
all: function ($from) {
var $target;
var len = selector.length;
for (var i = 0; i<len; i++) {
if (!$target) $target = selector[i].all($from);
else $target = $target.add(selector[i].all($from));
}
return $target;
},
is: function ($from) {
var len = selector.length;
for (var i = 0; i<len; i++) {
if (selector[i].is($from)) {
return true;
}
}
return false;
},
};
self.$snippets = $html.find(".tab-content > div > div")
.addClass("oe_snippet")
.each(function () {
if (!$('.oe_snippet_thumbnail', this).size()) {
var $div = $(
'<div class="oe_snippet_thumbnail">'+
'<div class="oe_snippet_thumbnail_img"/>'+
'<span class="oe_snippet_thumbnail_title"></span>'+
'</div>');
$div.find('span').text($(this).attr("name"));
$(this).prepend($div);
// from t-snippet
var thumbnail = $("[data-oe-thumbnail]", this).data("oe-thumbnail");
if (thumbnail) {
$div.find('.oe_snippet_thumbnail_img').css('background-image', 'url(' + thumbnail + ')');
}
// end
}
$("> *:not(.oe_snippet_thumbnail)", this).addClass('oe_snippet_body');
});
// select all default text to edit (if snippet default text)
self.$snippets.find('.oe_snippet_body, .oe_snippet_body *')
.contents()
.filter(function() {
return this.nodeType === 3 && this.textContent.match(/\S/);
}).parent().addClass("o_default_snippet_text");
$(document).on("mouseup", ".o_default_snippet_text", function (event) {
$(event.target).selectContent();
});
$(document).on("keyup", function (event) {
var r = $.summernote.core.range.create();
$(r && r.sc).closest(".o_default_snippet_text").removeClass("o_default_snippet_text");
});
// end
// clean t-oe
$html.find('[data-oe-model]').each(function () {
for (var k=0; k<this.attributes.length; k++) {
if (this.attributes[k].name.indexOf('data-oe-') === 0) {
$(this).removeAttr(this.attributes[k].name);
k--;
}
}
});
// end
self.$el.append($html);
$(window).trigger('resize');
self.make_snippet_draggable(self.$snippets);
});
var url = this._get_snippet_url();
if (!url || !url.length) {
this.$snippet.detach();
return;
}
return openerp.jsonRpc(url, 'call', {}).then(function (html) {
self.compute_snippet_templates(html);
self.trigger("snippets:ready");
});
},
compute_snippet_templates: function (html) {
var self = this;
var $html = $(html);
var $left_bar = this.$el.find("#o_left_bar");
var $ul = $html.siblings("ul");
var $scroll = $html.siblings("#o_scroll");
if (!$scroll.length) {
throw new Error("Wrong snippets xml definition");
}
$ul.children().tooltip({
delay: { "show": 500, "hide": 100 },
container: 'body',
title: function () {
return (navigator.appVersion.indexOf('Mac') > -1 ? 'CMD' : 'CTRL')+'+SHIFT+'+($(this).index()+1);
},
trigger: 'hover',
placement: 'top'
}).on('click', function () {$(this).tooltip('hide');});
// t-snippet
$html.find('[data-oe-type="snippet"][data-oe-name]').each(function () {
var $div = $('<div/>').insertAfter(this).append(this).attr('name', $(this).data('oe-name'));
});
// end
var selector = [];
var $styles = $html.find("[data-js], [data-selector]");
$styles.each(function () {
var $style = $(this);
var no_check = $style.data('no-check');
var option_id = $style.data('js');
var option = {
'option' : option_id,
'base_selector': $style.data('selector'),
'selector': self._add_check_selector($style.data('selector'), no_check),
'$el': $style,
'drop-near': $style.data('drop-near') && self._add_check_selector($style.data('drop-near'), no_check),
'drop-in': $style.data('drop-in') && self._add_check_selector($style.data('drop-in'), no_check),
'data': $style.data()
};
website.snippet.templateOptions.push(option);
selector.push(option.selector);
});
$styles.addClass("hidden");
website.snippet.globalSelector = {
closest: function ($from) {
var $temp;
var $target;
var len = selector.length;
for (var i = 0; i<len; i++) {
$temp = selector[i].closest($from, $target && $target[0]);
if (!$target || $temp.length) {
$target = $temp;
}
}
return $target;
},
all: function ($from) {
var $target;
var len = selector.length;
for (var i = 0; i<len; i++) {
if (!$target) $target = selector[i].all($from);
else $target = $target.add(selector[i].all($from));
}
return $target;
},
is: function ($from) {
var len = selector.length;
for (var i = 0; i<len; i++) {
if (selector[i].is($from)) {
return true;
}
}
return false;
},
};
// oe_snippet_body
self.$snippets = $scroll.find(".o_panel_body").children()
.addClass("oe_snippet")
.each(function () {
if (!$('.oe_snippet_thumbnail', this).size()) {
var $div = $(
'<div class="oe_snippet_thumbnail">'+
'<div class="oe_snippet_thumbnail_img"/>'+
'<span class="oe_snippet_thumbnail_title"></span>'+
'</div>');
$div.find('span').text($(this).attr("name"));
$(this).prepend($div);
// from t-snippet
var thumbnail = $("[data-oe-thumbnail]", this).data("oe-thumbnail");
if (thumbnail) {
$div.find('.oe_snippet_thumbnail_img').css('background-image', 'url(' + thumbnail + ')');
}
// end
}
$("> *:not(.oe_snippet_thumbnail)", this).addClass('oe_snippet_body');
});
// select all default text to edit (if snippet default text)
self.$snippets.find('.oe_snippet_body, .oe_snippet_body *')
.contents()
.filter(function() {
return this.nodeType === 3 && this.textContent.match(/\S/);
}).parent().addClass("o_default_snippet_text");
$(document).on("mouseup", ".o_default_snippet_text", function (event) {
$(event.target).selectContent();
});
$(document).on("keyup", function (event) {
var r = $.summernote.core.range.create();
$(r && r.sc).closest(".o_default_snippet_text").removeClass("o_default_snippet_text");
});
// end
// clean t-oe
$html.find('[data-oe-model]').each(function () {
for (var k=0; k<this.attributes.length; k++) {
if (this.attributes[k].name.indexOf('data-oe-') === 0) {
$(this).removeAttr(this.attributes[k].name);
k--;
}
}
});
// end
$left_bar.append($html);
// animate for list of snippet blocks
$left_bar.on('click', '.scroll-link', function (event) {
event.preventDefault();
var targetOffset = $($(this).attr("href")).position().top - $ul.outerHeight() + $scroll[0].scrollTop;
$scroll.animate({'scrollTop': targetOffset}, 750);
});
$scroll.on('scroll', function () {
var middle = $scroll.height()/4;
var $li = $ul.find("a").parent().removeClass('active');
var last;
for (var k=0; k<$li.length; k++) {
var li = $($li[k]);
if (!li.data('target')) {
li.data('target', $($("a", li).attr("href")));
}
if (li.data('target').position().top > middle) {
break;
}
last = $li[k];
}
$(last).addClass("active");
});
// end
// display scrollbar
$(window).on('resize', function () {
$scroll.css("overflow", "");
var height = $left_bar.height() - $ul.outerHeight();
$scroll.css("height", height);
var $last = $scroll.children(":visible").last().children(".o_panel_body");
$last.css({'min-height': (height-$last.prev().outerHeight())+'px'});
if ($scroll[0].scrollHeight + $ul[0].scrollHeight > document.body.clientHeight) {
$scroll.css("overflow", "auto").css("width", "226px");
} else {
$scroll.css("width", "");
}
}).trigger('resize');
// end
self.make_snippet_draggable(self.$snippets);
},
cover_target: function ($el, $target){
if($el.data('not-cover_target')) return;
var pos = $target.offset();
@@ -442,7 +482,7 @@
for (var k in template) {
var Option = options[template[k]['option']];
if (Option && Option.prototype.clean_for_save !== dummy) {
template[k].selector.all().each(function () {
template[k].selector.all().filter(".o_dirty").each(function () {
new Option(self, null, $(this), k).clean_for_save();
});
}
@@ -777,19 +817,10 @@
var timer;
$target.closest('.o_editable').on("content_changed", function (event) {
if ($target[0] === $(event.target).data('last-mutation').target ||
$.contains($target[0], $(event.target).data('last-mutation').target)) {
$target.data('need_recover', true);
if ($target.data('overlay') && $target.data('overlay').hasClass("oe_active")) {
clearTimeout(timer);
timer = setTimeout(function () {
$(':data(need_recover)').each(function () {
var $snippet = $(this);
$snippet.data('need_recover', null);
if ($snippet.data('overlay')) {
self.cover_target($snippet.data('overlay'), $snippet);
}
});
self.cover_target($target.data('overlay'), $target);
},50);
}
});
@@ -8,4 +8,10 @@
</div>
</t>
<t t-name="FieldTextHtml">
<div class="oe_form_field oe_form_field_html oe_form_embedded_html" t-att-style="widget.node.attrs.style">
<iframe/>
</div>
</t>
</templates>
@@ -14,12 +14,13 @@
</t>
<t t-name="website.snippets">
<div id='oe_snippets' class="o_open">
<div class="o_arrow">
<div id='oe_snippets' class="hidden-xs o_open">
<div id="o_arrow">
<span class="fa fa-angle-double-right fa-1x" style="top: 10px;"></span>
<div>Insert Blocks</div>
<span class="fa fa-angle-double-right fa-1x" style="bottom: 10px;"></span>
</div>
<div id="o_left_bar"></div>
</div>
</t>
File diff suppressed because it is too large Load Diff
+79
View File
@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<template id="assets_backend" name="website assets for backend" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<link rel="stylesheet" href="/website/static/src/css/website.backend.css"/>
<script type="text/javascript" src="/website/static/src/js/website.backend.js"></script>
</xpath>
</template>
<template id="assets_backend_editor" name="assets for backend editor">
<t t-call="web.assets_common"/>
<script type="text/javascript" src="/web/static/src/js/watch.js"></script>
<script type="text/javascript" src="/website/static/src/js/website.js"></script>
<script type="text/javascript" src="/website/static/src/js/website.snippets.animation.js"></script>
<script type="text/javascript" src="/web/static/lib/bootstrap/js/bootstrap.js"></script>
<script type="text/javascript" src="/web/static/lib/select2/select2.js"></script>
<link rel="stylesheet" href="/web/static/lib/select2/select2.css"/>
<link rel="stylesheet" href="/website/static/lib/select2-bootstrap-css/select2-bootstrap.css"/>
<link rel="stylesheet" href='/website/static/src/css/website.css'/>
<link id="bootstrap_css" rel='stylesheet' href='/web/static/lib/bootstrap/css/bootstrap.css'/>
<t t-call="website.summernote"/>
<t t-call="website.editor"/>
<script type="text/javascript" src="/website/static/src/js/website.backend.iframe.js"></script>
<style>.note-popover .popover { left: 5px !important; }</style>
</template>
<template id="editor_layout" name="Editor layout">&lt;!DOCTYPE html&gt;
<html t-att-lang="lang and lang.replace('_', '-')"
t-att-data-website-id="website.id if editable and website else None"
t-att-data-editable="1"
t-att-data-translatable="'1' if translatable else None"
t-att-data-main-object="repr(main_object) if editable else None"
t-att-data-oe-company-name="res_company.name">
<head>
<meta charset="utf-8" />
<title>Odoo Editor layout</title>
<meta name="viewport" content="initial-scale=1"/>
<t t-set="languages" t-value="website.get_languages() if website else None"/>
<t t-if="request and request.website_multilang and website">
<t t-foreach="website.get_alternate_languages(request.httprequest)" t-as="lang">
<link rel="alternate" t-att-hreflang="lang['hreflang']" t-att-href="lang['href']"/>
</t>
</t>
<script>
var snippets_url = '<t t-esc="snippets or ''"/>';
var callback = window.location.href.match(/callback=([^&amp;=]+)/)[1];
window.top.openerp[callback+"_set_value"] = function (value, fields_values) {
var editable = document.getElementsByClassName("o_editable")[0];
if (value !== editable.innerHTML) {
editable.innerHTML = value;
}
};
</script>
<t t-if="not dont_load_assets">
<t t-call-assets="website.assets_backend_editor"/>
</t>
<t t-raw="head or ''"/>
</head>
<body onload="window.top.openerp[callback+'_content']();">
<div id="wrapwrap">
<main>
<t t-raw="0"/>
</main>
</div>
<t t-raw="add_html or ''"/>
</body>
</html>
</template>
<template id="FieldTextHtml" name="Editor layout">
<t t-call="website.editor_layout">
<div class="o_editable" t-att-data-oe-model="model" t-att-data-oe-field="field" t-att-data-oe-id="res_id" data-oe-type="html"><t t-raw="content"/></div>
</t>
</template>
</data>
</openerp>
+71 -69
View File
@@ -187,103 +187,105 @@
</xpath>
</template>
<template id="assets_common" inherit_id="web.assets_common" name="Website common assets">
<xpath expr='.' position="inside">
<script type="text/javascript" src="/website/static/src/js/openerp.define.js"></script>
<script>openerp.define.active();</script>
<script>openerp.define.next = 'summernote/core/async';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/core/async.js"></script>
<script>openerp.define.next = 'summernote/core/func';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/core/func.js"></script>
<script>openerp.define.next = 'summernote/core/agent';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/core/agent.js"></script>
<script>openerp.define.next = 'summernote/core/list';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/core/list.js"></script>
<script>openerp.define.next = 'summernote/core/dom';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/core/dom.js"></script>
<script>openerp.define.next = 'summernote/core/key';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/core/key.js"></script>
<script>openerp.define.next = 'summernote/core/range';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/core/range.js"></script>
<template id="summernote" name="Summernote">
<script type="text/javascript" src="/website/static/src/js/openerp.define.js"></script>
<script>openerp.define.active();</script>
<script>openerp.define.next = 'summernote/core/async';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/core/async.js"></script>
<script>openerp.define.next = 'summernote/core/func';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/core/func.js"></script>
<script>openerp.define.next = 'summernote/core/agent';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/core/agent.js"></script>
<script>openerp.define.next = 'summernote/core/list';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/core/list.js"></script>
<script>openerp.define.next = 'summernote/core/dom';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/core/dom.js"></script>
<script>openerp.define.next = 'summernote/core/key';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/core/key.js"></script>
<script>openerp.define.next = 'summernote/core/range';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/core/range.js"></script>
<script>openerp.define.next = 'summernote/editing/Bullet';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/editing/Bullet.js"></script>
<script>openerp.define.next = 'summernote/editing/History';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/editing/History.js"></script>
<script>openerp.define.next = 'summernote/editing/Style';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/editing/Style.js"></script>
<script>openerp.define.next = 'summernote/editing/Table';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/editing/Table.js"></script>
<script>openerp.define.next = 'summernote/editing/Typing';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/editing/Typing.js"></script>
<script>openerp.define.next = 'summernote/editing/Editor';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/editing/Editor.js"></script>
<script>openerp.define.next = 'summernote/editing/Bullet';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/editing/Bullet.js"></script>
<script>openerp.define.next = 'summernote/editing/History';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/editing/History.js"></script>
<script>openerp.define.next = 'summernote/editing/Style';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/editing/Style.js"></script>
<script>openerp.define.next = 'summernote/editing/Table';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/editing/Table.js"></script>
<script>openerp.define.next = 'summernote/editing/Typing';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/editing/Typing.js"></script>
<script>openerp.define.next = 'summernote/editing/Editor';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/editing/Editor.js"></script>
<script>openerp.define.next = 'summernote/module/Button';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/module/Button.js"></script>
<script>openerp.define.next = 'summernote/module/Dialog';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/module/Dialog.js"></script>
<script>openerp.define.next = 'summernote/module/Handle';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/module/Handle.js"></script>
<script>openerp.define.next = 'summernote/module/Popover';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/module/Popover.js"></script>
<script>openerp.define.next = 'summernote/module/Toolbar';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/module/Toolbar.js"></script>
<script>openerp.define.next = 'summernote/module/Button';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/module/Button.js"></script>
<script>openerp.define.next = 'summernote/module/Dialog';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/module/Dialog.js"></script>
<script>openerp.define.next = 'summernote/module/Handle';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/module/Handle.js"></script>
<script>openerp.define.next = 'summernote/module/Popover';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/module/Popover.js"></script>
<script>openerp.define.next = 'summernote/module/Toolbar';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/module/Toolbar.js"></script>
<script>openerp.define.next = 'summernote/Renderer';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/Renderer.js"></script>
<script>openerp.define.next = 'summernote/EventHandler';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/EventHandler.js"></script>
<script>openerp.define.next = 'summernote/Renderer';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/Renderer.js"></script>
<script>openerp.define.next = 'summernote/EventHandler';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/EventHandler.js"></script>
<script>openerp.define.next = 'summernote/settings';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/settings.js"></script>
<script>openerp.define.next = 'summernote/settings';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/settings.js"></script>
<script>openerp.define.next = 'summernote/summernote';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/summernote.js"></script>
<script>openerp.define.next = 'summernote/openerp';</script>
<script type="text/javascript" src="/website/static/src/js/summernote.js"></script>
<script>openerp.define.desactive();</script>
<script>openerp.define.next = 'summernote/summernote';</script>
<script type="text/javascript" src="/website/static/lib/summernote/src/js/summernote.js"></script>
<script>openerp.define.next = 'summernote/openerp';</script>
<script type="text/javascript" src="/website/static/src/js/summernote.js"></script>
<script>openerp.define.desactive();</script>
<!--link rel="stylesheet" href="/website/static/lib/summernote/src/less/summernote.less"/-->
<link rel="stylesheet" href="/website/static/lib/summernote/summernote.css"/>
</xpath>
<!--link rel="stylesheet" href="/website/static/lib/summernote/src/less/summernote.less"/-->
<link rel="stylesheet" href="/website/static/lib/summernote/summernote.css"/>
</template>
<template id="assets_editor" name="Editor assets">
<template id="editor" name="Editor">
<link rel='stylesheet' href='/website/static/src/css/snippets.css'/>
<link rel='stylesheet' href='/website/static/src/css/editor.css'/>
<link rel='stylesheet' href="/web/static/lib/jquery.ui/jquery-ui.css"/>
<script type="text/javascript" src="/web/static/lib/select2/select2.js"></script>
<link rel="stylesheet" href="/web/static/lib/select2/select2.css"/>
<link rel="stylesheet" href="/website/static/lib/select2-bootstrap-css/select2-bootstrap.css"/>
<script type="text/javascript" src="/website/static/lib/ace/ace.js"></script>
<script type="text/javascript" src="/website/static/lib/ace/theme-monokai.js"></script>
<script type="text/javascript" src="/website/static/lib/ace/mode-xml.js"></script>
<script type="text/javascript" src="/website/static/lib/vkbeautify/vkbeautify.0.99.00.beta.js"></script>
<script type="text/javascript" src="/website/static/lib/jQuery.transfo.js"></script>
<t t-call="web.jqueryui_conflict">
<script type="text/javascript" src="/web/static/lib/jquery.ui/jquery-ui.js"></script>
</t>
<script type="text/javascript" src='/website/static/lib/nearest/jquery.nearest.js'></script>
<!-- mutation observers shim backed by mutation events (8 < IE < 11, Safari < 6, FF < 14, Chrome < 17) -->
<script type="text/javascript" src="/website/static/lib//jquery.mjs.nestedSortable/jquery.mjs.nestedSortable.js"></script>
<script type="text/javascript" src="/website/static/lib/MutationObservers/test/sidetable.js"></script>
<script type="text/javascript" src='/website/static/lib/nearest/jquery.nearest.js'></script>
<script type="text/javascript" src="/website/static/lib/MutationObservers/MutationObserver.js"></script>
<script type="text/javascript" src="/website/static/src/js/website.editor.js"></script>
<script type="text/javascript" src="/website/static/src/js/website.snippets.editor.js"></script>
<script type="text/javascript" src="/website/static/src/js/website.snippets.gallery.js" />
</template>
<template id="assets_common" inherit_id="web.assets_common" name="Website common assets">
<xpath expr='.' position="inside">
<t t-call="website.summernote"/>
</xpath>
</template>
<template id="assets_editor" name="Editor assets">
<t t-call="website.editor"/>
<script type="text/javascript" src="/website/static/lib/ace/ace.js"></script>
<script type="text/javascript" src="/website/static/lib/ace/theme-monokai.js"></script>
<script type="text/javascript" src="/website/static/lib/ace/mode-xml.js"></script>
<script type="text/javascript" src="/website/static/lib/vkbeautify/vkbeautify.0.99.00.beta.js"></script>
<script type="text/javascript" src="/website/static/lib//jquery.mjs.nestedSortable/jquery.mjs.nestedSortable.js"></script>
<script type="text/javascript" src="/website/static/src/js/website.contentMenu.js"></script> <!-- groups="base.group_website_designer" -->
<script type="text/javascript" src="/website/static/src/js/website.mobile.js"></script>
<script type="text/javascript" src="/website/static/src/js/website.seo.js"></script>
<script type="text/javascript" src="/website/static/src/js/website.tour.js"></script>
<script type="text/javascript" src="/website/static/src/js/website.tour.banner.js"></script> <!-- groups="base.group_website_designer" -->
<script type="text/javascript" src="/website/static/src/js/website.tour.rte.js"></script>
<script type="text/javascript" src="/website/static/src/js/website.snippets.editor.js"></script>
<script type="text/javascript" src="/website/static/src/js/website.snippets.gallery.js" />
<script type="text/javascript" src="/website/static/src/js/website.ace.js"></script>
<script type="text/javascript" src="/website/static/src/js/website.translator.js"></script>
<script type="text/javascript" src="/website/static/src/js/website.theme.js"></script>
</template>
<template id="login_layout" inherit_id="web.login_layout" name="Website Login Layout">
+1 -1
View File
@@ -520,7 +520,7 @@
<!-- Snippets -->
<template id="country_events" name="Country Events" inherit_id="website.snippets">
<xpath expr="//div[@id='snippet_content']" position="inside">
<xpath expr="//div[@id='snippet_content']/div[@class='o_panel_body']" position="inside">
<div>
<div class="oe_snippet_thumbnail">
<div style="background: white;box-shadow:none;-webkit-box-shadow:none;" class="oe_snippet_thumbnail_img" >
+1 -1
View File
@@ -4,7 +4,7 @@
<template id="subscribe" inherit_id="website.snippets" name="Snippet Subscribe">
<xpath expr="//div[@id='snippet_content']" position="inside">
<xpath expr="//div[@id='snippet_content']/div[@class='o_panel_body']" position="inside">
<div>
<div class="oe_snippet_thumbnail">
<img class="oe_snippet_thumbnail_img" src="/website_mail_group/static/src/img/blocks/button_group_subscribe.png"/>
@@ -2,7 +2,7 @@
<openerp>
<data>
<template id="website_twitter_snippet" name="Twitter snippet" inherit_id="website.snippets">
<xpath expr="//div[@id='snippet_feature']" position="inside">
<xpath expr="//div[@id='snippet_feature']/div[@class='o_panel_body']" position="inside">
<div>
<div class="oe_snippet_thumbnail">
<img class="oe_snippet_thumbnail_img" src="/website_twitter/static/src/img/twitter_scroll.png"/>