summaryrefslogtreecommitdiff
path: root/addons/website/static/src
diff options
context:
space:
mode:
authorChristophe Matthieu <chm@odoo.com>2015-07-07 16:02:53 +0200
committerChristophe Matthieu <chm@odoo.com>2015-07-10 17:00:11 +0200
commit8c559044a5e1be111dcb577ad7e5ab462c1002a0 (patch)
treeba1602e15b2bca38babd6cca63a41da1d05b4321 /addons/website/static/src
parenta616c57c609da0e5e56835dcb45e1c05590d25b8 (diff)
[IMP] web_editor: split website into web_editor (to use editor in backend for html field) and website
Diffstat (limited to 'addons/website/static/src')
-rw-r--r--addons/website/static/src/css/snippets.css722
-rw-r--r--addons/website/static/src/css/snippets.sass579
-rw-r--r--addons/website/static/src/css/website.backend.css31
-rw-r--r--addons/website/static/src/css/website.css249
-rw-r--r--addons/website/static/src/css/website.editor.css263
-rw-r--r--addons/website/static/src/css/website.editor.sass234
-rw-r--r--addons/website/static/src/css/website.sass181
-rw-r--r--addons/website/static/src/img/drag_here.pngbin619 -> 0 bytes
-rw-r--r--addons/website/static/src/img/edit_here.pngbin491 -> 0 bytes
-rw-r--r--addons/website/static/src/js/openerp.define.js107
-rw-r--r--addons/website/static/src/js/summernote.js2248
-rw-r--r--addons/website/static/src/js/website.backend.iframe.js75
-rw-r--r--addons/website/static/src/js/website.backend.js153
-rw-r--r--addons/website/static/src/js/website.editor.js2453
-rw-r--r--addons/website/static/src/js/website.js264
-rw-r--r--addons/website/static/src/js/website.snippets.animation.js72
-rw-r--r--addons/website/static/src/js/website.snippets.editor.js1667
-rw-r--r--addons/website/static/src/js/website.theme.js2
-rw-r--r--addons/website/static/src/js/website.tour.rte.js340
-rw-r--r--addons/website/static/src/js/website.translator.js254
-rw-r--r--addons/website/static/src/xml/website.backend.xml6
-rw-r--r--addons/website/static/src/xml/website.contentMenu.xml6
-rw-r--r--addons/website/static/src/xml/website.editor.xml607
-rw-r--r--addons/website/static/src/xml/website.gallery.xml2
-rw-r--r--addons/website/static/src/xml/website.snippets.xml74
-rw-r--r--addons/website/static/src/xml/website.translator.xml8
26 files changed, 755 insertions, 9842 deletions
diff --git a/addons/website/static/src/css/snippets.css b/addons/website/static/src/css/snippets.css
index 4d3f2c6c5ff..eb0b4d3e69b 100644
--- a/addons/website/static/src/css/snippets.css
+++ b/addons/website/static/src/css/snippets.css
@@ -1,725 +1,3 @@
-/* ---- SNIPPET EDITOR ---- {{{ */
-#oe_snippets #o_left_bar, #oe_snippets #o_arrow {
- position: fixed;
- top: 34px;
- left: 0px;
- bottom: 0;
- 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 {
- z-index: 1009;
- width: 24px;
- opacity: 0.75;
-}
-#oe_snippets #o_arrow > * {
- position: absolute;
- color: white;
-}
-#oe_snippets #o_arrow div {
- -moz-transform: translateX(-36%) rotate(-90deg);
- -ms-transform: translateX(-36%) rotate(-90deg);
- -webkit-transform: translateX(-36%) rotate(-90deg);
- transform: translateX(-36%) rotate(-90deg);
- top: 50%;
- white-space: nowrap;
-}
-#oe_snippets #o_arrow .fa {
- width: 100%;
- left: 40%;
-}
-#oe_snippets #o_left_bar {
- left: -228px;
- z-index: 1010;
- width: 208px;
- -moz-transition: all 500ms ease;
- -o-transition: all 500ms ease;
- -webkit-transition: all 500ms ease;
- transition: all 500ms ease;
-}
-#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 .o_panel {
- margin: 0;
- border: 0;
- width: 208px;
-}
-#oe_snippets .o_panel_header {
- background: #dff0d8;
- padding: 1px 8px;
- color: #414141;
- text-align: center;
-}
-#oe_snippets .o_panel_header .fa-stack {
- overflow: hidden;
- font-size: 1em;
-}
-#oe_snippets .o_panel_body {
- white-space: normal;
- background: black;
- padding: 7px 3px;
-}
-#oe_snippets .o_panel_body > div {
- background: black;
-}
-#oe_snippets .o_panel_body > div label {
- width: 44px;
- color: #fff;
- padding-left: 10px;
-}
-#oe_snippets .o_panel_body > div label div {
- width: 100px;
- text-align: center;
- -moz-transform: translate(-39px, 44px);
- -webkit-transform: translate(-39px, 44px);
- transform: translate(-39px, 44px);
- -moz-transform-origin: 50% 50%;
- -ms-transform-origin: 50% 50%;
- -webkit-transform-origin: 50% 50%;
- transform-origin: 50% 50%;
-}
-
-.oe_snippet {
- display: inline-block;
- vertical-align: top;
- width: 93px;
- margin-left: 3px;
- margin-right: 3px;
- margin-top: 1px;
- position: relative;
- overflow: hidden;
- -moz-user-select: -moz-none;
- -ms-user-select: none;
- -webkit-user-select: none;
- user-select: none;
- cursor: move;
-}
-.oe_snippet .oe_snippet_thumbnail {
- text-align: center;
- height: 100%;
- background: transparent;
- color: white;
- position: relative;
-}
-.oe_snippet .oe_snippet_thumbnail:hover .oe_snippet_thumbnail_img {
- -moz-transform: scale(0.95, 0.95);
- -ms-transform: scale(0.95, 0.95);
- -webkit-transform: scale(0.95, 0.95);
- transform: scale(0.95, 0.95);
-}
-.oe_snippet .oe_snippet_thumbnail .oe_snippet_thumbnail_title {
- font-size: 12px;
- display: block;
- text-shadow: 0 0 2px black;
-}
-.oe_snippet .oe_snippet_thumbnail .oe_snippet_thumbnail_img {
- height: 74px;
- width: 92px;
- background-size: cover;
- -moz-transform: scale(1, 1);
- -ms-transform: scale(1, 1);
- -webkit-transform: scale(1, 1);
- transform: scale(1, 1);
-}
-.oe_snippet .oe_snippet_thumbnail span, .oe_snippet .oe_snippet_thumbnail div {
- line-height: 18px;
-}
-.oe_snippet > :not(.oe_snippet_thumbnail) {
- display: none !important;
-}
-.oe_snippet.disable .oe_snippet_thumbnail {
- background-color: rgba(255, 0, 0, 0.75);
-}
-.oe_snippet.disable .oe_snippet_thumbnail_img {
- opacity: 0.8;
-}
-
-#oe_snippets .oe_snippet_thumbnail {
- background: #747474, url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHJhZGlhbEdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgY3g9IjUwJSIgY3k9IjUwJSIgcj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuNCIvPjwvcmFkaWFsR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
- background: #747474, -moz-radial-gradient(rgba(0, 0, 0, 0.25), rgba(0, 0, 0, 0.4));
- background: #747474, -webkit-radial-gradient(rgba(0, 0, 0, 0.25), rgba(0, 0, 0, 0.4));
- background: #747474, radial-gradient(rgba(0, 0, 0, 0.25), rgba(0, 0, 0, 0.4));
-}
-
-/* ---- SNIPPETS DROP ZONES ---- {{{ */
-.oe_drop_zone.oe_insert {
- display: block;
- height: 48px;
- margin: 0px;
- margin-top: -4px;
- margin-bottom: -44px;
- -moz-transition: margin 250ms linear;
- -o-transition: margin 250ms linear;
- -webkit-transition: margin 250ms linear;
- transition: margin 250ms linear;
- width: 100%;
- position: absolute;
- z-index: 1000;
-}
-.oe_drop_zone.oe_insert:not(.oe_vertical):before {
- content: "";
- display: block;
- border-top: dashed 2px rgba(209, 178, 255, 0.72);
- position: relative;
- top: 0px;
-}
-.oe_drop_zone.oe_insert.oe_hover:before {
- border-top: dashed 2px rgba(116, 255, 161, 0.72);
-}
-.oe_drop_zone.oe_insert.oe_vertical {
- width: 48px;
- float: left;
- position: relative;
- margin: 0px -24px !important;
-}
-.oe_drop_zone.oe_insert.oe_vertical_text {
- width: 48px;
- float: none;
- display: inline-block;
- position: relative;
- margin: 0px -24px !important;
-}
-.oe_drop_zone.oe_insert.oe_overlay {
- -moz-border-radius: 3px;
- -webkit-border-radius: 3px;
- border-radius: 3px;
- background: rgba(153, 0, 255, 0.5);
-}
-
-.oe_drop_zone, .oe_drop_zone_style {
- border: none;
- background: rgba(153, 0, 255, 0.3);
- -moz-border-radius: 4px;
- -webkit-border-radius: 4px;
- border-radius: 4px;
-}
-.oe_drop_zone.oe_hover, .oe_drop_zone_style.oe_hover {
- background: rgba(0, 255, 133, 0.3);
- z-index: 1001;
-}
-
-.oe_drop_zone_style {
- color: white;
- height: 48px;
- margin-bottom: 32px;
- padding-top: 12px;
-}
-
-/* ---- SNIPPET MANIPULATOR ---- {{{ */
-.resize_editor_busy {
- background-color: rgba(0, 0, 0, 0.3);
-}
-
-.oe_overlay {
- display: none;
- height: 0;
- position: absolute;
- background: transparent;
- z-index: 1001;
- -moz-border-radius: 3px;
- -webkit-border-radius: 3px;
- border-radius: 3px;
- -moz-transition: opacity 100ms linear;
- -o-transition: opacity 100ms linear;
- -webkit-transition: opacity 100ms linear;
- transition: opacity 100ms linear;
- -moz-box-sizing: border-box;
- -webkit-box-sizing: border-box;
- box-sizing: border-box;
-}
-.oe_overlay.oe_active {
- display: block;
-}
-.oe_overlay .oe_handle {
- display: block !important;
- position: absolute;
- top: 50%;
- left: 50%;
- -moz-box-sizing: border-box;
- -webkit-box-sizing: border-box;
- box-sizing: border-box;
- width: 16px;
- height: 16px;
- margin: -2px;
-}
-.oe_overlay .oe_handle > div {
- z-index: 1;
- position: absolute;
- border-style: dashed;
- border-width: 1px;
- border-color: #666666;
- -moz-box-shadow: 0px 0px 0px 1px rgba(255, 255, 255, 0.5), 0px 0px 0px 1px rgba(255, 255, 255, 0.5) inset;
- -webkit-box-shadow: 0px 0px 0px 1px rgba(255, 255, 255, 0.5), 0px 0px 0px 1px rgba(255, 255, 255, 0.5) inset;
- box-shadow: 0px 0px 0px 1px rgba(255, 255, 255, 0.5), 0px 0px 0px 1px rgba(255, 255, 255, 0.5) inset;
-}
-.oe_overlay .oe_handle.e:before, .oe_overlay .oe_handle.w:before, .oe_overlay .oe_handle.s:before, .oe_overlay .oe_handle.n:before, .oe_overlay .oe_handle.size .oe_handle_button {
- z-index: 2;
- position: relative;
- top: 50%;
- left: 50%;
- display: block;
- background: white;
- border: solid 1px rgba(0, 0, 0, 0.2);
- -moz-border-radius: 5px;
- -webkit-border-radius: 5px;
- border-radius: 5px;
- width: 18px;
- height: 18px;
- margin: -9px;
- padding-left: 1px;
- font-size: 14px;
- line-height: 14px;
- font-family: FontAwesome;
- color: rgba(0, 0, 0, 0.5);
- -moz-transition: background 100ms linear;
- -o-transition: background 100ms linear;
- -webkit-transition: background 100ms linear;
- transition: background 100ms linear;
-}
-.oe_overlay .oe_handle.e:hover:before, .oe_overlay .oe_handle.w:hover:before, .oe_overlay .oe_handle.s:hover:before, .oe_overlay .oe_handle.n:hover:before {
- background: rgba(0, 0, 0, 0.5);
- color: #fff;
- -moz-box-shadow: 0 0 5px 3px rgba(255, 255, 255, 0.7);
- -webkit-box-shadow: 0 0 5px 3px rgba(255, 255, 255, 0.7);
- box-shadow: 0 0 5px 3px rgba(255, 255, 255, 0.7);
-}
-.oe_overlay .oe_handle.e, .oe_overlay .oe_handle.w {
- top: 4px;
- height: 100%;
-}
-.oe_overlay .oe_handle.e:before, .oe_overlay .oe_handle.w:before {
- content: "";
- line-height: 16px;
-}
-.oe_overlay .oe_handle.e > div, .oe_overlay .oe_handle.w > div {
- width: 0;
- height: 100%;
- top: 2px;
- left: 8px;
-}
-.oe_overlay .oe_handle.e {
- left: auto;
- right: -6px;
- cursor: w-resize;
-}
-.oe_overlay .oe_handle.w {
- left: -6px;
- cursor: e-resize;
-}
-.oe_overlay .oe_handle.s, .oe_overlay .oe_handle.n {
- left: 2px;
- width: 100%;
-}
-.oe_overlay .oe_handle.s:before, .oe_overlay .oe_handle.n:before {
- content: "";
- text-align: center;
- padding: 1px;
-}
-.oe_overlay .oe_handle.s > div, .oe_overlay .oe_handle.n > div {
- width: 100%;
- height: 0;
- top: 7px;
- left: 1px;
-}
-.oe_overlay .oe_handle.s {
- top: auto;
- cursor: n-resize;
-}
-.oe_overlay .oe_handle.n {
- cursor: s-resize;
-}
-.oe_overlay .oe_handle.n > div {
- top: 5px;
-}
-.oe_overlay .oe_handle.size {
- z-index: 3;
- top: auto;
- left: 50%;
- bottom: -6px;
- margin-left: -50px;
-}
-.oe_overlay .oe_handle.size .oe_handle_button {
- position: relative;
- z-index: 3;
- text-align: center;
- margin-left: -52px;
- margin-top: -10px;
- left: 0px;
-}
-.oe_overlay .oe_handle.size .oe_handle_button:hover {
- background: rgba(30, 30, 30, 0.8);
- color: #fff;
- -moz-box-shadow: 0 0 5px 3px rgba(255, 255, 255, 0.7);
- -webkit-box-shadow: 0 0 5px 3px rgba(255, 255, 255, 0.7);
- box-shadow: 0 0 5px 3px rgba(255, 255, 255, 0.7);
-}
-.oe_overlay .oe_handle.size .size {
- position: absolute;
- width: 64px;
- cursor: row-resize;
- top: 9px;
- margin-left: 52px;
- padding: 0 5px;
-}
-.oe_overlay .oe_handle.size .auto_size {
- position: absolute;
- width: 100px;
- top: 9px;
- cursor: pointer;
-}
-.oe_overlay .oe_handle.readonly {
- cursor: auto !important;
-}
-.oe_overlay .oe_handle.readonly:before, .oe_overlay .oe_handle.readonly.size {
- display: none !important;
-}
-.oe_overlay .icon.btn {
- display: inline-block;
-}
-.oe_overlay .oe_overlay_options {
- position: absolute;
- left: 50% !important;
- text-align: center;
- top: -20px;
- z-index: 1002;
-}
-.oe_overlay .oe_overlay_options > .btn-group {
- left: -50%;
- white-space: nowrap;
-}
-.oe_overlay .oe_overlay_options > .btn-group > a {
- cursor: pointer;
- display: inline-block;
- float: none;
- margin: 0 -3px;
-}
-.oe_overlay .oe_overlay_options > .btn-group > div {
- float: none;
-}
-.oe_overlay .oe_overlay_options .btn, .oe_overlay .oe_overlay_options a {
- cursor: pointer;
-}
-.oe_overlay .oe_overlay_options .dropdown {
- display: inline-block;
-}
-.oe_overlay .oe_overlay_options .dropdown-menu {
- text-align: left;
- min-width: 180px;
-}
-.oe_overlay .oe_overlay_options .dropdown-menu select, .oe_overlay .oe_overlay_options .dropdown-menu input {
- display: block;
-}
-.oe_overlay.block-w-left .w:before {
- content: "" !important;
-}
-.oe_overlay.block-w-right .w:before {
- content: "" !important;
-}
-.oe_overlay.block-w-left.block-w-right .w:before {
- display: none !important;
-}
-.oe_overlay.block-e-left .e:before {
- content: "" !important;
-}
-.oe_overlay.block-e-right .e:before {
- content: "" !important;
-}
-.oe_overlay.block-e-left.block-e-right .e:before {
- display: none !important;
-}
-.oe_overlay.block-s-top .s:before {
- content: "" !important;
-}
-.oe_overlay.block-s-bottom .s:before {
- content: "" !important;
-}
-.oe_overlay.block-n-top .n:before {
- content: "" !important;
-}
-.oe_overlay.block-n-bottom .n:before {
- content: "" !important;
-}
-.oe_overlay.o_keypress {
- opacity: 0;
- -webkit-transition: 0.8s;
- -moz-transition: 0.8s;
- -o-transition: 0.8s;
- -transition: 0.8s;
-}
-
-.s-resize-important, .s-resize-important * {
- cursor: s-resize !important;
-}
-
-.n-resize-important, .n-resize-important * {
- cursor: n-resize !important;
-}
-
-.e-resize-important, .e-resize-important * {
- cursor: e-resize !important;
-}
-
-.w-resize-important, .w-resize-important * {
- cursor: w-resize !important;
-}
-
-.move-important, .move-important * {
- cursor: move !important;
-}
-
-/* add CSS for bootstrap dropdown multi level */
-.dropdown-submenu {
- position: relative;
- z-index: 1000;
-}
-
-.dropdown-submenu > .dropdown-menu {
- top: 0;
- left: 100%;
- margin-top: -6px;
- margin-left: -1px;
- -webkit-border-radius: 0 6px 6px 6px;
- -moz-border-radius: 0 6px 6px 6px;
- border-radius: 0 6px 6px 6px;
-}
-.dropdown-submenu:hover > .dropdown-menu {
- display: block;
-}
-.dropdown-submenu:hover > a:after {
- border-left-color: #ffffff;
-}
-.dropdown-submenu > a:after {
- display: block;
- content: " ";
- float: right;
- width: 0;
- height: 0;
- border-color: transparent;
- border-style: solid;
- border-width: 5px 0 5px 5px;
- border-left-color: #cccccc;
- margin-top: 5px;
- margin-right: -10px;
-}
-.dropdown-submenu.pull-left {
- float: none;
-}
-.dropdown-submenu.pull-left > .dropdown-menu {
- left: -100%;
- margin-left: 10px;
- -webkit-border-radius: 6px 0 6px 6px;
- -moz-border-radius: 6px 0 6px 6px;
- border-radius: 6px 0 6px 6px;
-}
-
-.oe_snippet_list {
- width: auto;
- white-space: nowrap;
- margin-left: 20px;
-}
-
-.oe_snippet_editor {
- position: fixed;
- z-index: 1000;
- bottom: 0;
- left: 0;
- right: 0;
- height: 214px;
- background: #a0a0a0;
- box-shadow: 0 1px 3px #646464 inset;
-}
-.oe_snippet_editor .oe_snippet {
- box-sizing: border-box;
- display: inline-block;
- width: 220px;
- height: 160px;
- border-radius: 3px;
- background: white;
- margin: 20px 20px 20px 0;
- cursor: pointer;
- border: 2px solid transparent;
- box-shadow: 0 1px 3px #646464;
- position: relative;
- top: 0;
- overflow: hidden;
- vertical-align: top;
- user-select: none;
- white-space: normal;
-}
-.oe_snippet_editor .oe_snippet:after {
- content: attr(name);
- position: absolute;
- bottom: 0px;
- left: 0px;
- right: 0px;
- background: rgba(255, 255, 255, 0.8);
- text-align: center;
- color: black;
- padding: 8px;
-}
-.oe_snippet_editor .oe_snippet.oe_selected, .oe_snippet_editor .oe_snippet.oe_active {
- border: 2px solid #9789ff;
- box-shadow: 0px 3px 17px rgba(99, 53, 150, 0.59);
-}
-.oe_snippet_editor .oe_snippet > * {
- margin-top: 16px;
- line-height: 1em;
- zoom: 0.6;
-}
-.oe_snippet_editor .oe_snippet > .container {
- margin-top: 15px;
- zoom: 0.17;
- line-height: 0.999em;
- line-height: 1em;
-}
-.oe_snippet_editor .oe_snippet > .row {
- margin-top: 0px;
- zoom: 0.23;
- line-height: 0.999em;
-}
-.oe_snippet_editor .oe_snippet > .span6 {
- margin-top: 18px;
- zoom: 0.34;
-}
-.oe_snippet_editor .oe_snippet > .span12 {
- margin-top: 16px;
- zoom: 0.23;
-}
-.oe_snippet_editor .oe_snippet > p {
- position: absolute;
- top: 0;
- right: 0;
- left: 0;
- bottom: 0;
- font-size: 20px;
- padding: 16px;
- zoom: 1;
- margin: 0px;
-}
-.oe_snippet_editor .oe_snippet.oe_new {
- background: gray;
- box-shadow: 0px 1px 3px #5a5a5a inset;
- border: 0px;
-}
-.oe_snippet_editor .oe_snippet.oe_new.oe_selected, .oe_snippet_editor .oe_snippet.oe_new.oe_active {
- box-shadow: 0px 2px 0px 0px #9789ff inset, 0px 3px 17px rgba(99, 53, 150, 0.59) inset;
-}
-.oe_snippet_editor .oe_snippet.oe_new > * {
- zoom: 1;
- margin: 0;
- line-height: 160px;
- text-align: center;
- color: white;
- font-size: 48px;
-}
-.oe_snippet_editor .oe_snippet.oe_new:after {
- position: absolute;
- left: 0px;
- right: 0px;
- top: 0px;
- bottom: 0px;
- background: transparent;
- color: white;
- text-shadow: 0px 1px 3px black;
- line-height: 160px;
- padding: 0px;
-}
-
-.oe_snippet_drop {
- position: relative;
- border: 2px dashed #ae34ff;
- background: rgba(147, 52, 255, 0.1);
- min-height: 28px;
- margin: -16px auto;
- border-radius: 5px;
- max-width: 50%;
-}
-.oe_snippet_drop.oe_accepting {
- border: 2px dashed #34ffa6;
- background: rgba(52, 255, 190, 0.1);
-}
-
-#website-top-edit li.oe_snippet_editorbar {
- padding: 1px 8px 2px;
- font: normal normal normal 12px Arial, Helvetica, Tahoma, Verdana, Sans-Serif;
- float: left;
- margin-top: 6px;
- border: 1px solid #a6a6a6;
- border-bottom-color: #979797;
- background: #eeeeee;
- border-radius: 3px;
-}
-#website-top-edit li.oe_snippet_editorbar > * {
- display: inline-block;
- height: 22px;
- padding: 4px 6px;
- outline: 0;
- border: 0;
-}
-#website-top-edit li.oe_snippet_editorbar a.button .icon {
- cursor: inherit;
- background-repeat: no-repeat;
- margin-top: 1px;
- width: 16px;
- height: 16px;
- display: inline-block;
-}
-
-/* ---- COLOR-PICKER ---- {{{ */
-.colorpicker {
- margin: 0 auto;
- background: transparent;
- border: 0;
-}
-.colorpicker td {
- padding: 0;
- background: transparent;
-}
-.colorpicker td > * {
- width: 16px;
- height: 16px;
- border-radius: 2px;
- margin: 3px;
- padding: 0;
- border-width: 1px;
- display: block;
-}
-.colorpicker .only-text {
- display: none;
-}
-.colorpicker .automatic-color {
- background: #fff;
- border-left: 7px solid #f33;
- border-top: 7px solid #0e0;
- border-right: 8px solid #33f;
- border-bottom: 8px solid #fe0;
- margin: 4px 3px 3px 3px;
- width: 0;
- height: 0;
-}
-
/* ---- Table Snippet ---- {{{ */
.table_desc {
margin: 0 0 20px 0;
diff --git a/addons/website/static/src/css/snippets.sass b/addons/website/static/src/css/snippets.sass
index 62a3040c19c..cb18e21db53 100644
--- a/addons/website/static/src/css/snippets.sass
+++ b/addons/website/static/src/css/snippets.sass
@@ -2,585 +2,6 @@
@import "compass/css3/user-interface"
@import "compass/css3/transition"
-
-/* ---- SNIPPET EDITOR ---- {{{ */
-
-#oe_snippets
- #o_left_bar, #o_arrow
- position: fixed
- top: 34px
- left: 0px
- bottom: 0
- background: rgb(40,40,40)
- +box-shadow(0px 10px 10px -10px black inset)
- #o_arrow
- z-index: 1009
- width: 24px
- opacity: 0.75
- > *
- position: absolute
- color: white
- div
- @include transform( translateX(-36%) rotate(-90deg) )
- top: 50%
- white-space: nowrap
- .fa
- width: 100%
- left: 40%
- #o_left_bar
- left: -228px
- z-index: 1010
- width: 208px
- @include transition(all 500ms ease)
- 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
- .o_panel
- margin: 0
- border: 0
- 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
- padding: 7px 3px
- > div
- background: rgb(0,0,0)
- label
- width: 44px
- color: #fff
- padding-left: 10px
-
- div
- width: 100px
- text-align: center
- @include transform( translate(-39px, 44px) , rotate(-90deg) )
- @include transform-origin(50%)
-
-.oe_snippet
- display: inline-block
- vertical-align: top
- width: 93px
- margin-left: 3px
- margin-right: 3px
- margin-top: 1px
- position: relative
- overflow: hidden
- +user-select(none)
- cursor: move
- .oe_snippet_thumbnail
- text-align: center
- height: 100%
- background: transparent
- color: white
- position: relative
- &:hover
- .oe_snippet_thumbnail_img
- @include transform( scale(.95,.95))
- .oe_snippet_thumbnail_title
- font-size: 12px
- display: block
- +text-shadow(0 0 2px rgb(0,0,0))
- .oe_snippet_thumbnail_img
- height: 74px
- width: 92px
- background-size: cover
- @include transform( scale(1,1))
- span, div
- line-height: 18px
- & > :not(.oe_snippet_thumbnail)
- display: none !important
- &.disable
- .oe_snippet_thumbnail
- background-color: rgba(255, 0, 0, 0.75)
- .oe_snippet_thumbnail_img
- opacity: 0.8
-#oe_snippets .oe_snippet_thumbnail
- @include background(#747474, radial-gradient(rgba(0,0,0,0.25),rgba(0,0,0,0.4)))
-
-// }}}}
-
-/* ---- SNIPPETS DROP ZONES ---- {{{ */
-
-.oe_drop_zone.oe_insert
- display: block
- height: 48px
- margin: 0px
- margin-top: -4px
- margin-bottom: -44px
- @include transition(margin 250ms linear)
- width: 100%
- position: absolute
- z-index: 1000
- &:not(.oe_vertical):before
- content: ""
- display: block
- border-top: dashed 2px rgba(209, 178, 255, 0.72)
- position: relative
- top: 0px
- &.oe_hover:before
- border-top: dashed 2px rgba(116, 255, 161, 0.72)
- &.oe_vertical
- width: 48px
- float: left
- position: relative
- margin: 0px -24px !important
- &.oe_vertical_text
- width: 48px
- float: none
- display: inline-block
- position: relative
- margin: 0px -24px !important
- &.oe_overlay
- +border-radius(3px)
- //@include background-image( repeating-linear-gradient(45deg, rgba(255,255,255,.1) ,rgba(255,255,255,.1) 35px, rgba(0,0,0,.1) 35px, rgba(0,0,0,.1) 75px))
- //background-size: 100px 100px
- background: rgba(153, 0, 255,.5)
-
-.oe_drop_zone, .oe_drop_zone_style
- border: none
- //@include background-image( repeating-linear-gradient(45deg, rgba(255,255,255,.1) ,rgba(255,255,255,.1) 35px, rgba(0,0,0,.1) 35px, rgba(0,0,0,.1) 75px))
- //background-size: 100px 100px
- background: rgba(153, 0, 255, .3)
- +border-radius(4px)
- &.oe_hover
- background: rgba(0, 255, 133, .3)
- z-index: 1001
-
-.oe_drop_zone_style
- color: white
- height: 48px
- margin-bottom: 32px
- padding-top: 12px
-
-// }}}
-
-/* ---- SNIPPET MANIPULATOR ---- {{{ */
-
-.resize_editor_busy
- background-color: rgba(0,0,0,0.3)
-
-.oe_overlay
- display: none
- height: 0
- position: absolute
- background: transparent
- z-index: 1001
- //@include background-image( repeating-linear-gradient(45deg, rgba(255,255,255,.02) ,rgba(255,255,255,.02) 35px, rgba(0,0,0,.02) 35px, rgba(0,0,0,.02) 75px))
- +border-radius(3px)
- @include transition(opacity 100ms linear)
- +box-sizing(border-box)
- &.oe_active
- display: block
- .oe_handle
- display: block !important
- position: absolute
- top: 50%
- left: 50%
- +box-sizing(border-box)
- width: 16px
- height: 16px
- margin: -2px
- > div
- z-index: 1
- position: absolute
- border-style: dashed
- border-width: 1px
- border-color: #666666
- +box-shadow(0px 0px 0px 1px rgba(255,255,255,0.5), 0px 0px 0px 1px rgba(255,255,255,0.5) inset)
- &.e:before, &.w:before, &.s:before, &.n:before, &.size .oe_handle_button
- z-index: 2
- position: relative
- top: 50%
- left: 50%
- display: block
- background: rgba(255, 255, 255, 1)
- border: solid 1px rgba(0, 0, 0, .2)
- +border-radius(5px)
- width: 18px
- height: 18px
- margin: -9px
- padding-left: 1px
- font-size: 14px
- line-height: 14px
- font-family: FontAwesome
- color: rgba(0,0,0,.5)
- @include transition(background 100ms linear)
- &.e, &.w, &.s, &.n
- &:hover:before
- background: rgba(0, 0, 0, .5)
- color: #fff
- +box-shadow(0 0 5px 3px rgba(255,255,255,.7))
- &.e, &.w
- top: 4px
- height: 100%
- &:before
- content: "\f07e"
- line-height: 16px
- > div
- width: 0
- height: 100%
- top: 2px
- left: 8px
- &.e
- left: auto
- right: -6px
- cursor: w-resize
- &.w
- left: -6px
- cursor: e-resize
- &.s, &.n
- left: 2px
- width: 100%
- &:before
- content: "\f07d"
- text-align: center
- padding: 1px
- > div
- width: 100%
- height: 0
- top: 7px
- left: 1px
- &.s
- top: auto
- cursor: n-resize
- &.n
- cursor: s-resize
- > div
- top: 5px
- &.size
- z-index: 3
- top: auto
- left: 50%
- bottom: -6px
- margin-left: -50px
- .oe_handle_button
- position: relative
- z-index: 3
- text-align: center
- margin-left: -52px
- margin-top: -10px
- left: 0px
- &:hover
- background: rgba(30, 30, 30, .8)
- color: #fff
- +box-shadow(0 0 5px 3px rgba(255,255,255,.7))
- .size
- position: absolute
- width: 64px
- cursor: row-resize
- top: 9px
- margin-left: 52px
- padding: 0 5px
- .auto_size
- position: absolute
- width: 100px
- top: 9px
- cursor: pointer
- &.readonly
- cursor: auto !important
- &:before, &.size
- display: none !important
-
- .icon.btn
- display: inline-block
-
- .oe_overlay_options
- position: absolute
- left: 50% !important
- text-align: center
- top: -20px
- z-index: 1002
- > .btn-group
- left: -50%
- white-space: nowrap
- > a
- cursor: pointer
- display: inline-block
- float: none
- margin: 0 -3px
- > div
- float: none
- .btn, a
- cursor: pointer
- .dropdown
- display: inline-block
- .dropdown-menu
- text-align: left
- min-width: 180px
- .dropdown-menu select,.dropdown-menu input
- display: block
-
- &.block-w-left .w:before
- content: "\F061" !important
- &.block-w-right .w:before
- content: "\F060" !important
- &.block-w-left.block-w-right .w:before
- display: none !important
- &.block-e-left .e:before
- content: "\F061" !important
- &.block-e-right .e:before
- content: "\F060" !important
- &.block-e-left.block-e-right .e:before
- display: none !important
-
- &.block-s-top .s:before
- content: "\F063" !important
- &.block-s-bottom .s:before
- content: "\f062" !important
- &.block-n-top .n:before
- content: "\F063" !important
- &.block-n-bottom .n:before
- content: "\f062" !important
-
- &.o_keypress
- opacity: 0
- -webkit-transition: .8s
- -moz-transition: .8s
- -o-transition: .8s
- -transition: .8s
-
-
-.s-resize-important, .s-resize-important *
- cursor: s-resize !important
-.n-resize-important, .n-resize-important *
- cursor: n-resize !important
-.e-resize-important, .e-resize-important *
- cursor: e-resize !important
-.w-resize-important, .w-resize-important *
- cursor: w-resize !important
-.move-important, .move-important *
- cursor: move !important
-
-// }}}
-
-
-/* add CSS for bootstrap dropdown multi level */
-.dropdown-submenu
- position: relative
- z-index: 1000
-.dropdown-submenu
- &>.dropdown-menu
- top: 0
- left: 100%
- margin-top: -6px
- margin-left: -1px
- -webkit-border-radius: 0 6px 6px 6px
- -moz-border-radius: 0 6px 6px 6px
- border-radius: 0 6px 6px 6px
- &:hover
- &>.dropdown-menu
- display: block
- &>a:after
- border-left-color: #ffffff
- &>a:after
- display: block
- content: " "
- float: right
- width: 0
- height: 0
- border-color: transparent
- border-style: solid
- border-width: 5px 0 5px 5px
- border-left-color: #cccccc
- margin-top: 5px
- margin-right: -10px
- &.pull-left
- float: none
- &>.dropdown-menu
- left: -100%
- margin-left: 10px
- -webkit-border-radius: 6px 0 6px 6px
- -moz-border-radius: 6px 0 6px 6px
- border-radius: 6px 0 6px 6px
-
-.oe_snippet_list
- width: auto
- white-space: nowrap
- margin-left: 20px
-
-.oe_snippet_editor
- position: fixed
- z-index: 1000
- bottom: 0
- left: 0
- right: 0
- height: 214px
- background: rgb(160,160,160)
- box-shadow: 0 1px 3px rgb(100,100,100) inset
- .oe_snippet
- box-sizing: border-box
- display: inline-block
- width: 220px
- height: 160px
- border-radius: 3px
- background: white
- margin: 20px 20px 20px 0
- cursor: pointer
- border: 2px solid transparent
- box-shadow: 0 1px 3px rgb(100,100,100)
- position: relative
- top: 0
- overflow: hidden
- vertical-align: top
- user-select: none
- white-space: normal
- &:after
- content: attr(name)
- position: absolute
- bottom: 0px
- left: 0px
- right: 0px
- background: rgba(255,255,255,0.8)
- text-align: center
- color: black
- padding: 8px
- &.oe_selected, &.oe_active
- border: 2px solid rgb(151, 137, 255)
- box-shadow: 0px 3px 17px rgba(99, 53, 150, 0.59)
- & > *
- margin-top: 16px
- line-height: 1em
- zoom: 0.6
- & > .container
- margin-top: 15px
- zoom: 0.17
- line-height: 0.999em
- line-height: 1em
- & > .row
- margin-top: 0px
- zoom: 0.23
- line-height: 0.999em
- & > .span6
- margin-top: 18px
- zoom: 0.34
- & > .span12
- margin-top: 16px
- zoom: 0.23
- & > p
- position: absolute
- top: 0
- right: 0
- left: 0
- bottom: 0
- font-size: 20px
- padding: 16px
- zoom: 1
- margin: 0px
- &.oe_new
- background: gray
- box-shadow: 0px 1px 3px rgb(90,90,90) inset
- border: 0px
- &.oe_selected, &.oe_active
- box-shadow: 0px 2px 0px 0px rgb(151,137,255) inset, 0px 3px 17px rgba(99, 53, 150, 0.59) inset
- & > *
- zoom: 1
- margin: 0
- line-height: 160px
- text-align: center
- color: white
- font-size: 48px
- &:after
- position: absolute
- left: 0px
- right: 0px
- top: 0px
- bottom: 0px
- background: transparent
- color: white
- text-shadow: 0px 1px 3px black
- line-height: 160px
- padding: 0px
-
-.oe_snippet_drop
- position: relative
- border: 2px dashed rgb(174, 52, 255)
- background: rgba(147, 52, 255, 0.1)
- min-height: 28px
- margin: -16px auto
- border-radius: 5px
- max-width: 50%
- &.oe_accepting
- border: 2px dashed rgb(52, 255, 166)
- background: rgba(52, 255, 190, 0.1)
-
-#website-top-edit
- li.oe_snippet_editorbar
- padding: 1px 8px 2px
- font: normal normal normal 12px Arial,Helvetica,Tahoma,Verdana,Sans-Serif
- float: left
- margin-top: 6px
- border: 1px solid #a6a6a6
- border-bottom-color: #979797
- background: #eeeeee
- border-radius: 3px
- & > *
- display: inline-block
- height: 22px
- padding: 4px 6px
- outline: 0
- border: 0
-
- a.button .icon
- cursor: inherit
- background-repeat: no-repeat
- margin-top: 1px
- width: 16px
- height: 16px
- display: inline-block
-
-/* ---- COLOR-PICKER ---- {{{ */
-
-.colorpicker
- margin: 0 auto
- background: transparent
- border: 0
- td
- padding: 0
- background: transparent
- > *
- width: 16px
- height: 16px
- border-radius: 2px
- margin: 3px
- padding: 0
- border-width: 1px
- display: block
- .only-text
- display: none
- .automatic-color
- background: #fff
- border-left: 7px solid #f33
- border-top: 7px solid #0e0
- border-right: 8px solid #33f
- border-bottom: 8px solid #fe0
- margin: 4px 3px 3px 3px
- width: 0
- height: 0
-
-// }}}
-
/* ---- Table Snippet ---- {{{ */
.table_desc
diff --git a/addons/website/static/src/css/website.backend.css b/addons/website/static/src/css/website.backend.css
index 333118ce1b3..927b3907d6f 100644
--- a/addons/website/static/src/css/website.backend.css
+++ b/addons/website/static/src/css/website.backend.css
@@ -3,35 +3,4 @@
}
.oe_button_box .oe_stat_button .o_stat_info.published > .o_stat_text.oe_unpublish {
display: none;
-}
-.oe_form_field.oe_form_field_html_frame {
- display: block;
-}
-.oe_form_field_html_frame iframe {
- display: block;
- width: 100%;
- border: 0;
- padding: 0;
- margin: 0;
- min-height: 300px;
-}
-.o_form_FieldTextHtml_fullscreen .oe_form_field_html_frame 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_frame 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;
} \ No newline at end of file
diff --git a/addons/website/static/src/css/website.css b/addons/website/static/src/css/website.css
index 40febaf9b1b..642113e179b 100644
--- a/addons/website/static/src/css/website.css
+++ b/addons/website/static/src/css/website.css
@@ -1,158 +1,10 @@
-@charset "UTF-8";
+@charset "utf-8";
/* THIS CSS FILE IS FOR WEBSITE THEMING CUSTOMIZATION ONLY
*
* css for editor buttons, openerp widget included in the website and other
* stuff must go to the editor.css
*
*/
-/* ----- GENERIC LAYOUTING HELPERS ---- */
-/* Vertical Spacing */
-.mt128 {
- margin-top: 128px !important;
-}
-
-.mt92 {
- margin-top: 92px !important;
-}
-
-.mt64 {
- margin-top: 64px !important;
-}
-
-.mt48 {
- margin-top: 48px !important;
-}
-
-.mt32 {
- margin-top: 32px !important;
-}
-
-.mt16 {
- margin-top: 16px !important;
-}
-
-.mt8 {
- margin-top: 8px !important;
-}
-
-.mt4 {
- margin-top: 4px !important;
-}
-
-.mt0 {
- margin-top: 0px !important;
-}
-
-.mb128 {
- margin-bottom: 128px !important;
-}
-
-.mb92 {
- margin-bottom: 92px !important;
-}
-
-.mb64 {
- margin-bottom: 64px !important;
-}
-
-.mb48 {
- margin-bottom: 48px !important;
-}
-
-.mb32 {
- margin-bottom: 32px !important;
-}
-
-.mb16 {
- margin-bottom: 16px !important;
-}
-
-.mb8 {
- margin-bottom: 8px !important;
-}
-
-.mb4 {
- margin-bottom: 4px !important;
-}
-
-.mb0 {
- margin-bottom: 0px !important;
-}
-
-.ml8 {
- margin-left: 8px !important;
-}
-
-.ml4 {
- margin-left: 4px !important;
-}
-
-.ml0 {
- margin-left: 0px !important;
-}
-
-.mr8 {
- margin-right: 8px !important;
-}
-
-.mr4 {
- margin-right: 4px !important;
-}
-
-.mr0 {
- margin-right: 0px !important;
-}
-
-img.padding-small, .img.padding-small, span.fa.padding-small, iframe.padding-small {
- padding: 4px;
-}
-img.padding-medium, .img.padding-medium, span.fa.padding-medium, iframe.padding-medium {
- padding: 8px;
-}
-img.padding-large, .img.padding-large, span.fa.padding-large, iframe.padding-large {
- padding: 16px;
-}
-img.padding-xl, .img.padding-xl, span.fa.padding-xl, iframe.padding-xl {
- padding: 32px;
-}
-
-div.media_iframe_video.padding-small iframe {
- padding: 4px;
-}
-div.media_iframe_video.padding-medium iframe {
- padding: 8px;
-}
-div.media_iframe_video.padding-large iframe {
- padding: 16px;
-}
-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;
}
@@ -247,12 +99,6 @@ font[style*='background'], font[class*='bg-'] {
}
/* Extra Styles */
-img.shadow {
- -moz-box-shadow: 0px 3px 8px rgba(0, 0, 0, 0.2);
- -webkit-box-shadow: 0px 3px 8px rgba(0, 0, 0, 0.2);
- box-shadow: 0px 3px 8px rgba(0, 0, 0, 0.2);
-}
-
h1.text-muted, h2.text-muted, h3.text-muted {
margin-top: 10px;
}
@@ -269,19 +115,6 @@ hr {
padding-bottom: 10px;
}
-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 {
font-size: 120%;
@@ -294,11 +127,6 @@ td {
margin-right: auto;
}
-/* ----- EDITOR ----- */
-.css_non_editable_mode_hidden {
- display: none !important;
-}
-
/* ----- BOOTSTRAP FIX ----- */
.container .container, .readable .container {
padding-left: 0;
@@ -363,26 +191,6 @@ body > nav.navbar {
width: 100%;
}
}
-/* ---- 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;
-}
-
-.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: " ";
- text-align: center;
- display: block;
- min-height: 1em;
- color: grey;
- font-size: 24px;
- padding-top: 160px;
-}
-
-.css_editable_display {
- display: none;
-}
-
-/* ---- HACK FOR COVERING UP EDITOR BOGUS P INSERTION --- */
.navbar .nav > li > p {
margin-bottom: 0px;
}
@@ -844,17 +652,6 @@ table.well tr td {
color: white;
}
-address .fa.fa-mobile-phone {
- margin: 0 3px 0 2px;
-}
-address .fa.fa-file-text-o {
- margin-right: 1px;
-}
-
-span[data-oe-type="monetary"] {
- white-space: nowrap;
-}
-
.oe_template_fallback {
-moz-column-count: 3;
-webkit-column-count: 3;
@@ -879,49 +676,6 @@ span[data-oe-type="monetary"] {
text-align: center;
}
-div.media_iframe_video {
- margin: 0 auto;
- text-align: center;
- position: relative;
- overflow: hidden;
-}
-div.media_iframe_video iframe {
- width: 100%;
- height: 100%;
- top: 0;
- position: absolute;
- margin: 0 auto;
- margin-left: -50%;
-}
-div.media_iframe_video .media_iframe_video_size {
- padding-bottom: 66.5%;
- position: relative;
- width: 100%;
- height: 0;
-}
-div.media_iframe_video .css_editable_mode_display {
- position: absolute;
- width: 100%;
- height: 100%;
- display: none;
- z-index: 2;
-}
-
-html[data-browser^="msie"] div.media_iframe_video iframe {
- margin-left: 0;
-}
-
-/* Mobile view */
-@media (max-width: 768px) {
- img:not(.cke_iframe), .media_iframe_video, span.fa, i.fa {
- -webkit-transform: none !important;
- -moz-transform: none !important;
- -ms-transform: none !important;
- -o-transform: none !important;
- transform: none !important;
- }
-}
-/* Fix: backward compatibility saas-3 */
div.carousel .container > .carousel-caption {
position: absolute;
right: 50%;
@@ -1003,7 +757,6 @@ div.carousel .item.text_only .container > .carousel-image {
.container nav#oe_main_menu_navbar {
position: inherit;
}
-
.oe_search_clear {
position: absolute;
display:none;
diff --git a/addons/website/static/src/css/website.editor.css b/addons/website/static/src/css/website.editor.css
new file mode 100644
index 00000000000..69e6e451d6b
--- /dev/null
+++ b/addons/website/static/src/css/website.editor.css
@@ -0,0 +1,263 @@
+@charset "utf-8";
+/* ---- Common---- {{{ */
+.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {
+ min-height: 24px;
+}
+
+/* ---- MOBILE PREVIEW ---- {{{ */
+.oe_mobile_preview.modal .modal-content {
+ height: 660px;
+ background-color: #000000;
+ border: 2px solid #1C1F1F;
+ -moz-border-radius: 10px;
+ -webkit-border-radius: 10px;
+ border-radius: 10px;
+ margin: auto;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ max-width: 330px;
+}
+.oe_mobile_preview.modal .modal-content .modal-header {
+ background-color: #000000;
+ border-bottom: 0;
+ -moz-border-radius-topleft: 10px;
+ -webkit-border-top-left-radius: 10px;
+ border-top-left-radius: 10px;
+ -moz-border-radius-topright: 10px;
+ -webkit-border-top-right-radius: 10px;
+ border-top-right-radius: 10px;
+}
+.oe_mobile_preview.modal .modal-content .modal-header .modal-title {
+ color: #1C1F1F;
+}
+.oe_mobile_preview.modal .modal-content .modal-header .close {
+ color: lightgrey;
+ filter: progid:DXImageTransform.Microsoft.Alpha(enabled=false);
+ opacity: 1;
+}
+.oe_mobile_preview.modal .modal-content .modal-header .close:hover {
+ color: #E00101;
+ filter: progid:DXImageTransform.Microsoft.Alpha(enabled=false);
+ opacity: 1;
+}
+.oe_mobile_preview.modal .modal-content .modal-body {
+ background-color: #000000;
+ max-height: 600px;
+ padding: 0;
+ margin: 0;
+}
+.oe_mobile_preview.modal .modal-content .modal-body .oe_mobile_viewport {
+ width: 320px;
+ height: 568px;
+ padding: 5px;
+ border: none;
+}
+.oe_mobile_preview.modal .modal-content .modal-footer {
+ background-color: #000000;
+}
+
+/* ---- SEO TOOLS ---- {{{ */
+.oe_seo_configuration .modal-dialog {
+ width: 80%;
+}
+.oe_seo_configuration .oe_remove {
+ color: #E00101;
+}
+.oe_seo_configuration .oe_seo_suggestion {
+ cursor: pointer;
+}
+.oe_seo_configuration .oe_seo_keyword {
+ padding: 0.2em 0.4em 0.2em 0.5em;
+ -moz-border-radius: 0.4em;
+ -webkit-border-radius: 0.4em;
+ border-radius: 0.4em;
+}
+.oe_seo_configuration li.oe_seo_preview_g {
+ line-height: 1.2;
+ list-style: none;
+ list-style-image: none;
+ list-style-position: outside;
+ list-style-type: none;
+ font-size: small;
+ font-family: arial, sans-serif;
+}
+.oe_seo_configuration li.oe_seo_preview_g h3 {
+ font-size: medium;
+}
+.oe_seo_configuration li.oe_seo_preview_g .r {
+ margin: 0;
+ font-size: 16px;
+ font-style: normal;
+ font-weight: normal;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ -webkit-text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.oe_seo_configuration li.oe_seo_preview_g .r a {
+ color: #1e0fbe;
+ text-decoration: underline;
+ text-transform: none;
+}
+.oe_seo_configuration li.oe_seo_preview_g .r a em {
+ font-style: normal !important;
+}
+.oe_seo_configuration li.oe_seo_preview_g .s {
+ color: #444;
+ max-width: 42em;
+}
+.oe_seo_configuration li.oe_seo_preview_g .kv, .oe_seo_configuration li.oe_seo_preview_g .slp {
+ display: block;
+ margin-bottom: 1px;
+}
+.oe_seo_configuration li.oe_seo_preview_g .f {
+ color: #666;
+ margin-bottom: 1px;
+}
+.oe_seo_configuration li.oe_seo_preview_g .f cite {
+ color: #006621;
+ font-style: normal;
+ font-size: 14px;
+}
+.oe_seo_configuration li.oe_seo_preview_g .st {
+ line-height: 1.24;
+}
+
+/* ---- ACE EDITOR ---- {{{ */
+.oe_ace_view_editor {
+ position: fixed;
+ right: 0;
+ z-index: 1001;
+ height: 100%;
+ background: #2F3129;
+ color: white;
+}
+.oe_ace_view_editor .oe_ace_view_editor_title {
+ width: 100%;
+ padding-top: 0;
+ padding-left: 0;
+ height: 30px;
+}
+.oe_ace_view_editor .oe_ace_view_editor_title .oe_view_list {
+ width: 50%;
+ height: 30px;
+ font-size: 14px;
+ font-family: "Monaco", "Menlo", "Ubuntu Mono", "Consolas", "source-code-pro", monospace;
+ line-height: normal;
+}
+.oe_ace_view_editor .oe_ace_view_editor_title .btn {
+ height: 30px;
+ padding: 0 4px 0 4px;
+ font-size: 14px;
+ font-family: "Monaco", "Menlo", "Ubuntu Mono", "Consolas", "source-code-pro", monospace;
+ line-height: normal;
+}
+.oe_ace_view_editor .ace_editor {
+ position: absolute;
+ top: 50px;
+ right: 0;
+ left: 0;
+}
+.oe_ace_view_editor .ace_editor .ace_gutter {
+ cursor: ew-resize;
+}
+.oe_ace_view_editor #ace-view-id {
+ padding: 0 1em;
+}
+.oe_ace_view_editor.oe_ace_open {
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=97);
+ opacity: 0.97;
+}
+.oe_ace_view_editor.oe_ace_closed {
+ z-index: -1000;
+ filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);
+ opacity: 0;
+}
+
+.oe_include_bundles {
+ font-weight: normal;
+ padding: 0 8px;
+}
+
+/* ---- CUSTOMIZE THEME ---- {{{ */
+#theme_error {
+ background: #ffc;
+}
+
+#theme_customize_modal {
+ overflow: visible;
+ z-index: 1020;
+ background: transparent;
+ display: block;
+}
+#theme_customize_modal .modal-dialog {
+ top: 75px;
+ width: auto;
+ margin: 0;
+ position: absolute;
+ right: 10px;
+ font-family: "Lato-Regular";
+ font-weight: normal;
+ text-transform: capitalize;
+ letter-spacing: normal;
+}
+#theme_customize_modal .modal-h5 {
+ color: #ffffff;
+ font-family: "Lato-Regular";
+ font-weight: normal;
+ text-transform: uppercase;
+ letter-spacing: normal;
+ font-size: 14px;
+ color: white;
+ padding: 4px 0 4px 4px;
+ background-color: #bdc3c7;
+}
+#theme_customize_modal table {
+ width: 100%;
+ margin-bottom: 8px;
+}
+#theme_customize_modal label {
+ display: block;
+ text-align: center;
+}
+#theme_customize_modal label > div, #theme_customize_modal label > img {
+ border: 1px solid #fff;
+ line-height: 30px;
+ font-size: 0.9em;
+ margin: 2px 4px;
+}
+#theme_customize_modal label.checked > div, #theme_customize_modal label.checked > img {
+ box-shadow: 2px 2px 3px #888;
+ border: 1px solid #666;
+}
+#theme_customize_modal label img {
+ width: 60px;
+ height: 35px;
+ margin: 2px;
+ border: 1px solid rgba(136, 136, 136, 0.5);
+}
+#theme_customize_modal label input {
+ display: none;
+}
+#theme_customize_modal .loading_backdrop {
+ display: none;
+}
+#theme_customize_modal.loading .loading_backdrop {
+ display: block;
+ width: 100%;
+ height: 100%;
+ background: #000;
+ opacity: 0.3;
+ position: absolute;
+ z-index: 1;
+}
+
+/* ---- force the browse to re-compute the stylesheets ---- */
+body.theme_customize_css_loading {
+ magin-top: 1px;
+}
+body.theme_customize_css_loading #wrapwrap {
+ magin-top: -1px;
+}
diff --git a/addons/website/static/src/css/website.editor.sass b/addons/website/static/src/css/website.editor.sass
new file mode 100644
index 00000000000..911631bb8ee
--- /dev/null
+++ b/addons/website/static/src/css/website.editor.sass
@@ -0,0 +1,234 @@
+@charset "utf-8"
+@import "common"
+
+/* ---- Common---- {{{ */
+
+.col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12
+ min-height: 24px
+
+// }}}
+
+/* ---- MOBILE PREVIEW ---- {{{ */
+
+$mobile_preview_background: #000000
+$mobile_preview_border: #1C1F1F
+$icon_close: #E00101
+.oe_mobile_preview
+ &.modal .modal-content
+ height: 660px
+ background-color: $mobile_preview_background
+ border: 2px solid $mobile_preview_border
+ +border-radius(10px)
+ margin: auto
+ top: 0
+ left: 0
+ bottom: 0
+ right: 0
+ max-width: 330px
+ .modal-header
+ background-color: $mobile_preview_background
+ border-bottom: 0
+ +border-top-left-radius(10px)
+ +border-top-right-radius(10px)
+ .modal-title
+ color: $mobile_preview_border
+ .close
+ color: lightgrey
+ +opacity(1)
+ .close:hover
+ color: $icon_close
+ +opacity(1)
+ .modal-body
+ background-color: $mobile_preview_background
+ max-height: 600px
+ padding: 0
+ margin: 0
+ .oe_mobile_viewport
+ width: 320px
+ height: 568px
+ padding: 5px
+ border: none
+ .modal-footer
+ background-color: $mobile_preview_background
+
+// }}}
+
+/* ---- SEO TOOLS ---- {{{ */
+
+$remove_color: $icon_close
+$in_title_color: #5cb85c
+$in_description_color: #428bca
+$in_body_color: #5bc0de
+$highlighted_text_color: #ffffff
+.oe_seo_configuration
+ .modal-dialog
+ width: 80%
+ .oe_remove
+ color: $remove_color
+ .oe_seo_suggestion
+ cursor: pointer
+ .oe_seo_keyword
+ padding: .2em .4em .2em .5em
+ +border-radius(.4em)
+ li.oe_seo_preview_g
+ line-height: 1.2
+ list-style: none
+ list-style-image: none
+ list-style-position: outside
+ list-style-type: none
+ font-size: small
+ font-family: arial,sans-serif
+ h3
+ font-size: medium
+ .r
+ margin: 0
+ font-size: 16px
+ font-style: normal
+ font-weight: normal
+ overflow: hidden
+ text-overflow: ellipsis
+ -webkit-text-overflow: ellipsis
+ white-space: nowrap
+ a
+ color: rgb(30, 15, 190)
+ text-decoration: underline
+ text-transform: none
+ em
+ font-style: normal !important
+ .s
+ color: #444
+ max-width: 42em
+ .kv,.slp
+ display: block
+ margin-bottom: 1px
+ .f
+ color: #666
+ margin-bottom: 1px
+ cite
+ color: #006621
+ font-style: normal
+ font-size: 14px
+ .st
+ line-height: 1.24
+
+
+// }}}
+
+/* ---- ACE EDITOR ---- {{{ */
+
+$editorbar_height: 30px
+$infobar_height: 20px
+// TODO Fix => might break with themes
+
+.oe_ace_view_editor
+ position: fixed
+ // top property is set programmatically
+ right: 0
+ z-index: 1001
+ height: 100%
+ background: #2F3129
+ color: white
+ .oe_ace_view_editor_title
+ width: 100%
+ padding-top: 0
+ padding-left: 0
+ height: $editorbar_height
+ .oe_view_list
+ width: 50%
+ height: $editorbar_height
+ @include editor-font
+ .btn
+ height: $editorbar_height
+ padding: 0 4px 0 4px
+ @include editor-font
+ .ace_editor
+ position: absolute
+ top: $editorbar_height + $infobar_height
+ right: 0
+ // bottom property is set programmatically
+ left: 0
+ .ace_gutter
+ cursor: ew-resize
+ #ace-view-id
+ padding: 0 1em
+ &.oe_ace_open
+ +opacity(0.97)
+ &.oe_ace_closed
+ z-index: -1000
+ +opacity(0)
+
+.oe_include_bundles
+ font-weight: normal
+ padding: 0 8px
+
+// }}}
+
+/* ---- CUSTOMIZE THEME ---- {{{ */
+#theme_error
+ background: #ffc
+#theme_customize_modal
+ overflow: visible
+ z-index: 1020
+ background: transparent
+ display: block
+ .modal-dialog
+ top: 75px
+ width: auto
+ margin: 0
+ position: absolute
+ right: 10px
+ font-family: 'Lato-Regular'
+ font-weight: normal
+ text-transform: capitalize
+ letter-spacing: normal
+ .modal-h5
+ color: #ffffff
+ font-family: 'Lato-Regular'
+ font-weight: normal
+ text-transform: uppercase
+ letter-spacing: normal
+ font-size: 14px
+ color: white
+ padding: 4px 0 4px 4px
+ background-color: #bdc3c7
+ table
+ width: 100%
+ margin-bottom: 8px
+ label
+ display: block
+ text-align: center
+ > div, > img
+ border: 1px solid #fff
+ line-height: 30px
+ font-size: 0.9em
+ margin: 2px 4px
+ &.checked
+ > div, > img
+ box-shadow: 2px 2px 3px #888
+ border: 1px solid #666
+ img
+ width: 60px
+ height: 35px
+ margin: 2px
+ border: 1px solid rgba(136, 136, 136, 0.5)
+ input
+ display: none
+ .loading_backdrop
+ display: none
+ &.loading
+ .loading_backdrop
+ display: block
+ width: 100%
+ height: 100%
+ background: #000
+ opacity: 0.3
+ position: absolute
+ z-index: 1
+
+/* ---- force the browse to re-compute the stylesheets ---- */
+body.theme_customize_css_loading
+ magin-top: 1px
+ #wrapwrap
+ magin-top: -1px
+
+// }}}
diff --git a/addons/website/static/src/css/website.sass b/addons/website/static/src/css/website.sass
index cb526b29b01..f8f8c4fe05f 100644
--- a/addons/website/static/src/css/website.sass
+++ b/addons/website/static/src/css/website.sass
@@ -10,93 +10,6 @@
*
*/
-/* ----- GENERIC LAYOUTING HELPERS ---- */
-
-/* Vertical Spacing */
-.mt128
- margin-top: 128px !important
-.mt92
- margin-top: 92px !important
-.mt64
- margin-top: 64px !important
-.mt48
- margin-top: 48px !important
-.mt32
- margin-top: 32px !important
-.mt16
- margin-top: 16px !important
-.mt8
- margin-top: 8px !important
-.mt4
- margin-top: 4px !important
-.mt0
- margin-top: 0px !important
-
-.mb128
- margin-bottom: 128px !important
-.mb92
- margin-bottom: 92px !important
-.mb64
- margin-bottom: 64px !important
-.mb48
- margin-bottom: 48px !important
-.mb32
- margin-bottom: 32px !important
-.mb16
- margin-bottom: 16px !important
-.mb8
- margin-bottom: 8px !important
-.mb4
- margin-bottom: 4px !important
-.mb0
- margin-bottom: 0px !important
-
-.ml8
- margin-left: 8px !important
-.ml4
- margin-left: 4px !important
-.ml0
- margin-left: 0px !important
-
-.mr8
- margin-right: 8px !important
-.mr4
- margin-right: 4px !important
-.mr0
- margin-right: 0px !important
-
-img, .img, span.fa, iframe
- &.padding-small
- padding: 4px
- &.padding-medium
- padding: 8px
- &.padding-large
- padding: 16px
- &.padding-xl
- padding: 32px
-div.media_iframe_video
- &.padding-small iframe
- padding: 4px
- &.padding-medium iframe
- padding: 8px
- &.padding-large iframe
- padding: 16px
- &.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
@@ -158,9 +71,6 @@ font[style*='background'], font[class*='bg-']
/* Extra Styles */
-img.shadow
- +box-shadow(0px 3px 8px rgba(0, 0, 0, 0.2))
-
h1.text-muted, h2.text-muted, h3.text-muted
margin-top: 10px
@@ -175,17 +85,6 @@ hr
margin-bottom: 10px
padding-bottom: 10px
-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
@@ -197,11 +96,6 @@ td
margin-left: auto
margin-right: auto
-/* ----- EDITOR ----- */
-
-.css_non_editable_mode_hidden
- display: none !important
-
/* ----- BOOTSTRAP FIX ----- */
.container, .readable
@@ -241,7 +135,7 @@ body > nav.navbar
width: 100%
position: absolute
z-index: 10000
-@media (max-min: 767px)
+@media (min-width: 767px)
nav.navbar + #wrapwrap
padding-top: 34px
@@ -255,33 +149,9 @@ body > nav.navbar
.table .img-responsive
width: 100%
-/* ---- 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
-
-.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: ' '
- text-align: center
- display: block
- min-height: 1em
- color: grey
- font-size: 24px
- padding-top: 160px
-
-.css_editable_display
- display: none
-
-/* ---- HACK FOR COVERING UP EDITOR BOGUS P INSERTION --- */
-
.navbar .nav > li > p
margin-bottom: 0px
-// .navbar .nav > li a
-// text-shadow: none
-
-// .nav > li a
-// display: block
-
/* ---- HOMEPAGE THEME CUSTOMIZATION ---- */
.nav-hierarchy
@@ -659,15 +529,6 @@ table.well tr
a
color: white
-address
- .fa.fa-mobile-phone
- margin: 0 3px 0 2px
- .fa.fa-file-text-o
- margin-right: 1px
-
-span[data-oe-type="monetary"]
- white-space: nowrap
-
.oe_template_fallback
@include column-count(3)
@@ -685,46 +546,6 @@ span[data-oe-type="monetary"]
input
text-align: center
-div.media_iframe_video
- margin: 0 auto
- text-align: center
- position: relative
- overflow: hidden
- iframe
- width: 100%
- height: 100%
- top: 0
- position: absolute
- margin: 0 auto
- margin-left: -50%
- .media_iframe_video_size
- padding-bottom: 66.5%
- position: relative
- width: 100%
- height: 0
- .css_editable_mode_display
- position: absolute
- width: 100%
- height: 100%
- display: none
- z-index: 2
-
-html[data-browser^="msie"] div.media_iframe_video iframe
- margin-left: 0
-
-/* Mobile view */
-
-@media (max-width: 768px)
- img:not(.cke_iframe), .media_iframe_video, span.fa, i.fa
- -webkit-transform: none !important
- -moz-transform: none !important
- -ms-transform: none !important
- -o-transform: none !important
- transform: none !important
-
-
-/* Fix: backward compatibility saas-3 */
-
div.carousel
.container
> .carousel-caption
diff --git a/addons/website/static/src/img/drag_here.png b/addons/website/static/src/img/drag_here.png
deleted file mode 100644
index 335c3a571bb..00000000000
--- a/addons/website/static/src/img/drag_here.png
+++ /dev/null
Binary files differ
diff --git a/addons/website/static/src/img/edit_here.png b/addons/website/static/src/img/edit_here.png
deleted file mode 100644
index 77beff11c7b..00000000000
--- a/addons/website/static/src/img/edit_here.png
+++ /dev/null
Binary files differ
diff --git a/addons/website/static/src/js/openerp.define.js b/addons/website/static/src/js/openerp.define.js
deleted file mode 100644
index 85e0486546e..00000000000
--- a/addons/website/static/src/js/openerp.define.js
+++ /dev/null
@@ -1,107 +0,0 @@
-odoo.define('website.define', function () {
-'use strict';
-
-var containsDefine = typeof(define) !== "undefined" ? define : undefined;
-var scripts = {
- 'jquery': jQuery
-};
-
-function odoo_define(parse) {
- return function (name, list, callback) {
-
- var def = $.Deferred();
- def.openerpDefine = true;
-
- if (!callback) {
- callback = list;
- list = null;
- }
- if (!list) {
- list = name;
- if (odoo.website_next_define) {
- name = odoo.website_next_define;
- odoo.website_next_define = null;
- }
- }
-
- if (list instanceof Array) {
- var defs = [];
- var args = [];
- _.each(list, function (js, index) {
- var path = parse(js);
-
- if (!(path in scripts)) {
-
- scripts[path] = $.Deferred();
- scripts[path].openerpDefine = true;
-
- $.ajax({ 'url': path, 'dataType': 'html', 'async': false })
- .then(function (data) {
- var code = new Function("return "+data)();
- if (code.openerpDefine) {
- code.then(function (code) {
- scripts[path].resolve(code);
- scripts[path] = code;
- });
- } else {
- scripts[path].resolve(code);
- scripts[path] = code;
- }
- });
-
- }
-
- if (scripts[path] && scripts[path].openerpDefine) {
- scripts[path].then(function (code) {
- args[index] = code;
- });
- defs.push(scripts[path]);
- } else {
- args[index] = scripts[path] = scripts[path] || null;
- }
- });
-
- $.when.apply($, defs).then(function () {
- var result = callback.apply(window, args);
- if (name) {
- scripts[name] = scripts[parse(name)] = result;
- }
- def.resolve(result);
- });
-
- } else {
-
- def = scripts[name] = scripts[parse(name)] = scripts[name] || callback() || null;
-
- }
-
- return def;
- }
-}
-
-function enable() {
- window.define = odoo_define(function (id) {
-
- if (id.slice(0,10) === 'summernote') {
- return '/website/static/lib/summernote/src/js' + id.slice(10,Infinity) + '.js';
- }
- return id;
- });
-}
-
-function disable() {
- window.define = containsDefine;
-}
-
-odoo.website_next_define = undefined;
-odoo.enable_website_define = enable;
-odoo.disable_website_define = disable;
-
-return {
- enable: enable,
- disable: disable,
- define: odoo_define,
- scripts: scripts,
-};
-
-});
diff --git a/addons/website/static/src/js/summernote.js b/addons/website/static/src/js/summernote.js
deleted file mode 100644
index 5303837b26a..00000000000
--- a/addons/website/static/src/js/summernote.js
+++ /dev/null
@@ -1,2248 +0,0 @@
-odoo.define('website.summernote', function (require) {
-'use strict';
-
-var core = require('web.core');
-
-var _t = core._t;
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-/* Summernote Lib (neek hack to make accessible: method and object) */
-
-var agent = $.summernote.core.agent;
-var dom = $.summernote.core.dom;
-var range = $.summernote.core.range;
-var list = $.summernote.core.list;
-var key = $.summernote.core.key;
-var eventHandler = $.summernote.eventHandler;
-var editor = eventHandler.editor;
-var renderer = $.summernote.renderer;
-var options = $.summernote.options;
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-/* Add method to Summernote*/
-
-dom.hasContentAfter = function (node) {
- var next;
- while (node.nextSibling) {
- next = node.nextSibling;
- if (next.tagName || next.textContent.match(/\S|\u00A0/) || dom.isBR(next)) return next;
- node = next;
- }
-};
-dom.hasContentBefore = function (node) {
- var prev;
- while (node.previousSibling) {
- prev = node.previousSibling;
- if (prev.tagName || prev.textContent.match(/\S|\u00A0/) || dom.isBR(prev)) return prev;
- node = prev;
- }
-};
-dom.ancestorHaveNextSibling = function (node, pred) {
- pred = pred || dom.hasContentAfter;
- while (!node.nextSibling || !pred(node)) { node = node.parentNode; }
- return node;
-};
-dom.ancestorHavePreviousSibling = function (node, pred) {
- pred = pred || dom.hasContentBefore;
- while (!node.previousSibling || !pred(node)) { node = node.parentNode; }
- return node;
-};
-dom.nextElementSibling = function (node) {
- while (node) {
- node = node.nextSibling;
- if (node && node.tagName) {
- break;
- }
- }
- return node;
-};
-dom.previousElementSibling = function (node) {
- while (node) {
- node = node.previousSibling;
- if (node && node.tagName) {
- break;
- }
- }
- return node;
-};
-dom.lastChild = function (node) {
- while (node.lastChild) { node = node.lastChild; }
- return node;
-};
-dom.firstChild = function (node) {
- while (node.firstChild) { node = node.firstChild; }
- return node;
-};
-dom.lastElementChild = function (node, deep) {
- node = deep ? dom.lastChild(node) : node.lastChild;
- return !node || node.tagName ? node : dom.previousElementSibling(node);
-};
-dom.firstElementChild = function (node, deep) {
- node = deep ? dom.firstChild(node) : node.firstChild;
- return !node || node.tagName ? node : dom.nextElementSibling(node);
-};
-dom.isEqual = function (prev, cur) {
- if (prev.tagName !== cur.tagName) {
- return false;
- }
- if ((prev.attributes ? prev.attributes.length : 0) !== (cur.attributes ? cur.attributes.length : 0)) {
- return false;
- }
-
- function strip(text) {
- return text && text.replace(/^\s+|\s+$/g, '').replace(/\s+/g, ' ');
- }
- var att, att2;
- loop_prev:
- for(var a in prev.attributes) {
- att = prev.attributes[a];
- for(var b in cur.attributes) {
- att2 = cur.attributes[b];
- if (att.name === att2.name) {
- if (strip(att.value) != strip(att2.value)) return false;
- continue loop_prev;
- }
- }
- return false;
- }
- return true;
-};
-/**
- * Checks that the node only has a @style, not e.g. @class or whatever
- */
-dom.hasOnlyStyle = function (node) {
- for (var i = 0; i < node.attributes.length; i++) {
- var attr = node.attributes[i];
- if (attr.attributeName !== 'style') {
- return false;
- }
- }
- return true;
-};
-dom.hasProgrammaticStyle = function (node) {
- var styles = ["float", "display", "position", "top", "left", "right", "bottom"];
- for (var i = 0; i < node.style.length; i++) {
- var style = node.style[i];
- if (styles.indexOf(style) !== -1) {
- return true;
- }
- }
- return false;
-};
-dom.mergeFilter = function (prev, cur, parent) {
- // merge text nodes
- if (prev && (dom.isText(prev) || (dom.pasteTextApply.indexOf(prev.tagName) !== -1 && prev !== cur.parentNode)) && dom.isText(cur)) {
- return true;
- }
- if (prev && prev.tagName === "P" && dom.isText(cur)) {
- return true;
- }
- if (prev && dom.isText(cur) && !cur.textContent.match(/\S|\u00A0/) && (dom.isText(prev) || prev.textContent.match(/\S|\u00A0/))) {
- return true;
- }
- if (prev && !dom.isBR(prev) && dom.isEqual(prev, cur) &&
- ((prev.tagName && window.getComputedStyle(prev).display === "inline" &&
- cur.tagName && window.getComputedStyle(cur).display === "inline"))) {
- return true;
- }
- if (dom.isEqual(parent, cur) &&
- ((parent.tagName && window.getComputedStyle(parent).display === "inline" &&
- cur.tagName && window.getComputedStyle(cur).display === "inline"))) {
- return true;
- }
- if (parent && cur.tagName === "FONT" && (!cur.firstChild || (!cur.attributes.getNamedItem('style') && !cur.className.length))) {
- return true;
- }
- // On backspace, webkit browsers create a <span> with a bunch of
- // inline styles "remembering" where they come from.
- // chances are we had e.g.
- // <p>foo</p>
- // <p>bar</p>
- // merged the lines getting this in webkit
- // <p>foo<span>bar</span></p>
- if (parent && cur.tagName === "SPAN" && dom.hasOnlyStyle(cur) && !dom.hasProgrammaticStyle(cur)) {
- return true;
- }
-};
-dom.doMerge = function (prev, cur) {
- if (prev.tagName) {
- if (prev.childNodes.length && !prev.textContent.match(/\S/) && dom.firstElementChild(prev) && dom.isBR(dom.firstElementChild(prev))) {
- prev.removeChild(dom.firstElementChild(prev));
- }
- if (cur.tagName) {
- while (cur.firstChild) {
- prev.appendChild(cur.firstChild);
- }
- cur.parentNode.removeChild(cur);
- } else {
- prev.appendChild(cur);
- }
- } else {
- if (cur.tagName) {
- var deep = cur;
- while (deep.tagName && deep.firstChild) {deep = deep.firstChild;}
- prev.appendData(deep.textContent);
- cur.parentNode.removeChild(cur);
- } else {
- prev.appendData(cur.textContent);
- cur.parentNode.removeChild(cur);
- }
- }
-};
-dom.merge = function (node, begin, so, end, eo, mergeFilter, all) {
- mergeFilter = mergeFilter || dom.mergeFilter;
- var _merged = false;
- var add = all || false;
-
- if (!begin) {
- begin = node;
- while(begin.firstChild) {begin = begin.firstChild;}
- so = 0;
- } else if (begin.tagName && begin.childNodes[so]) {
- begin = begin.childNodes[so];
- so = 0;
- }
- if (!end) {
- end = node;
- while(end.lastChild) {end = end.lastChild;}
- eo = end.textContent.length-1;
- } else if (end.tagName) {
-
- } else if (end.tagName && end.childNodes[so]) {
- end = end.childNodes[so];
- so = 0;
- }
-
- begin = dom.firstChild(begin);
- if (dom.isText(begin) && so > begin.textContent.length) {
- so = 0;
- }
- end = dom.firstChild(end);
- if (dom.isText(end) && eo > end.textContent.length) {
- eo = 0;
- }
-
- function __merge (node) {
- var merged = false;
- var prev;
- for (var k=0; k<node.childNodes.length; k++) {
- var cur = node.childNodes[k];
-
- if (cur === begin) {
- if (!all) add = true;
- }
-
- __merge(cur);
- dom.orderClass(dom.node(cur));
-
- if (!add || !cur) continue;
- if (cur === end) {
- if (!all) add = false;
- }
-
- // create the first prev value
- if (!prev) {
- if (mergeFilter.call(dom, prev, cur, node)) {
- prev = prev || cur.previousSibling;
- dom.moveTo(cur, cur.parentNode, cur);
- k--;
- } else {
- prev = cur;
- }
- continue;
- } else if (mergeFilter.call(dom, null, cur, node)) { // merge with parent
- prev = prev || cur.previousSibling;
- dom.moveTo(cur, cur.parentNode, cur);
- k--;
- continue;
- }
-
- // merge nodes
- if (mergeFilter.call(dom, prev, cur, node)) {
- var p = prev;
- var c = cur;
- // compute prev/end and offset
- if (prev.tagName) {
- if (cur.tagName) {
- if (cur === begin) begin = prev;
- if (cur === end) end = prev;
- }
- } else {
- if (cur.tagName) {
- var deep = cur;
- while (deep.tagName && deep.lastChild) {deep = deep.lastChild;}
- if (deep === begin) {
- so += prev.textContent.length;
- begin = prev;
- }
- if (deep === end) {
- eo += prev.textContent.length;
- end = prev;
- }
- } else {
- // merge text nodes
- if (cur === begin) {
- so += prev.textContent.length;
- begin = prev;
- }
- if (cur === end) {
- eo += prev.textContent.length;
- end = prev;
- }
- }
- }
-
- dom.doMerge(p, c);
-
- merged = true;
- k--;
- continue;
- }
-
- prev = cur;
- }
-
- // an other loop to merge the new shibbing nodes
- if (merged) {
- _merged = true;
- __merge(node);
- }
- }
- if (node) {
- __merge(node);
- }
-
- return {
- merged: _merged,
- sc: begin,
- ec: end,
- so: so,
- eo: eo
- };
-};
-dom.autoMerge = function (target, previous) {
- var node = dom.lastChild(target);
- var nodes = [];
- var temp;
-
- while (node) {
- nodes.push(node);
- if (temp = (previous ? dom.hasContentBefore(node) : dom.hasContentAfter(node))) {
- if (!dom.isText(node) && !dom.isMergable(node) && temp.tagName !== node.tagName) {
- nodes = [];
- }
- break;
- }
- node = node.parentNode;
- }
-
- while (nodes.length) {
- node = nodes.pop();
- if (node && (temp = (previous ? dom.hasContentBefore(node) : dom.hasContentAfter(node))) &&
- temp.tagName === node.tagName &&
- !dom.isText(node) &&
- dom.isMergable(node) &&
- !dom.isNotBreakable(node) && !dom.isNotBreakable(previous ? dom.previousElementSibling(node) : dom.nextElementSibling(node))) {
-
- if (previous) {
- dom.doMerge(temp, node);
- } else {
- dom.doMerge(node, temp);
- }
- }
- }
-};
-dom.removeSpace = function (node, begin, so, end, eo) {
- var removed = false;
- var add = node === begin;
-
- if (node === begin && begin === end && dom.isBR(node)) {
- return {
- removed: removed,
- sc: begin,
- ec: end,
- so: so,
- eo: eo
- };
- }
-
- (function __remove_space (node) {
- if (!node) return;
- for (var k=0; k<node.childNodes.length; k++) {
- var cur = node.childNodes[k];
-
- if (cur === begin) add = true;
-
- if (cur.tagName && cur.tagName !== "SCRIPT" && cur.tagName !== "STYLE" && window.getComputedStyle(cur).whiteSpace !== "pre") {
- __remove_space(cur);
- }
-
- if (!add) continue;
- if (cur === end) add = false;
-
- // remove begin empty text node
- if (node.childNodes.length > 1 && dom.isText(cur) && !cur.textContent.match(/\S|\u00A0/)) {
- removed = true;
- if (cur === begin) {
- so = 0;
- begin = dom.lastChild(dom.hasContentBefore(dom.ancestorHavePreviousSibling(cur)));
- }
- if (cur === end) {
- eo = 1;
- end = dom.firstChild(dom.hasContentAfter(dom.ancestorHaveNextSibling(cur)));
- if (dom.isText(end)) {
- eo = end.textContent.length;
- }
- }
- cur.parentNode.removeChild(cur);
- begin = dom.lastChild(begin);
- end = dom.lastChild(end);
- k--;
- continue;
- }
-
- // convert HTML space
- if (dom.isText(cur)) {
- var text;
- var exp1 = /[\t\n\r ]+/g;
- var exp2 = /(?!([ ]|\u00A0)|^)\u00A0(?!([ ]|\u00A0)|$)/g;
- if (cur === begin) {
- var temp = cur.textContent.substr(0, so);
- var _temp = temp.replace(exp1, ' ').replace(exp2, ' ');
- so -= temp.length - _temp.length;
- }
- if (cur === end) {
- var temp = cur.textContent.substr(0, eo);
- var _temp = temp.replace(exp1, ' ').replace(exp2, ' ');
- eo -= temp.length - _temp.length;
- }
- var text = cur.textContent.replace(exp1, ' ').replace(exp2, ' ');
- removed = removed || cur.textContent.length !== text.length;
- cur.textContent = text;
- }
- }
- })(node);
-
- return {
- removed: removed,
- sc: begin,
- ec: end,
- so: !dom.isBR(begin) && so > 0 ? so : 0,
- eo: eo
- };
-};
-dom.node = function (node) {
- return node.tagName ? node : node.parentNode;
-};
-dom.pasteTextApply = "h1 h2 h3 h4 h5 h6 li p".split(" ");
-dom.pasteTextClose = "h1 h2 h3 h4 h5 h6 p b bold i u code sup strong small li pre".split(" ");
-dom.pasteText = function (textNode, offset, text, isOnlyText) {
- // clean the node
- var node = dom.node(textNode);
- var data = dom.merge(node.parentNode, textNode, offset, textNode, offset, null, true);
- data = dom.removeSpace(node.parentNode, data.sc, data.so, data.ec, data.eo);
- // Break the text node up
- if (data.sc.tagName) {
- if (node === data.sc.parentNode) {
- data.sc = node.insertBefore(document.createTextNode(" "), data.sc);
- } else if (node.firstChild && !dom.isBR(dom.firstChild(node))) {
- data.sc = node.insertBefore(document.createTextNode(" "), dom.firstChild(node));
- } else {
- data.sc = node.appendChild(document.createTextNode(" "));
- }
- data.so = 0;
- }
- data.sc.splitText(data.so);
- var first = data.sc;
- var last = data.sc.nextSibling;
-
- isOnlyText = isOnlyText || !text.match('\n');
-
- if (!isOnlyText) {
- // tag to close and open
- var tag = node.tagName.toLowerCase();
- if(dom.pasteTextApply.indexOf(tag) === -1) {
- text = text.split('\n').join("<br/>");
- } else {
- text = "<"+tag+">"+text.split('\n').join("</"+tag+"><"+tag+">")+"</"+tag+">";
- }
-
- var $text = $(text);
-
- // split parent node and insert text
- if(dom.pasteTextClose.indexOf(tag) !== -1) {
- var $next = $(node).clone().empty();
- $next.append( last );
- $(node).after( $next );
- $(node).after( $text );
- } else {
- $(data.sc).after( $text );
- }
- } else {
- first.appendData( text );
- }
-
- // clean the dom content
- data = dom.merge(node.parentNode.parentNode, last, 0, last, 0, null, true);
- data = dom.removeSpace(node.parentNode.parentNode, data.sc, data.so, data.ec, data.eo);
-
- // move caret
- range.create(data.sc, data.so, data.ec, data.eo).select();
-};
-dom.removeBetween = function (sc, so, ec, eo, towrite) {
- if (ec.tagName) {
- if (ec.childNodes[eo]) {
- ec = ec.childNodes[eo];
- eo = 0;
- } else {
- ec = dom.lastChild(ec);
- eo = dom.nodeLength(ec);
- }
- }
- if (sc.tagName) {
- sc = sc.childNodes[so] || dom.firstChild(ec);
- so = 0;
- if (!dom.hasContentBefore(sc) && towrite) {
- sc.parentNode.insertBefore(document.createTextNode('\u00A0'), sc);
- }
- }
- if (!eo && sc !== ec) {
- ec = dom.lastChild(dom.hasContentBefore(dom.ancestorHavePreviousSibling(ec)));
- eo = ec.textContent.length;
- }
-
- var ancestor = dom.commonAncestor(sc.tagName ? sc.parentNode : sc, ec.tagName ? ec.parentNode : ec) || dom.ancestor(sc, dom.isEditable);
-
- if (!dom.isContentEditable(ancestor)) {
- return {
- sc: sc,
- so: so,
- ec: sc,
- eo: eo
- };
- }
-
- if (ancestor.tagName) {
- var ancestor_sc = sc;
- var ancestor_ec = ec;
- while (ancestor !== ancestor_sc && ancestor !== ancestor_sc.parentNode) { ancestor_sc = ancestor_sc.parentNode; }
- while (ancestor !== ancestor_ec && ancestor !== ancestor_ec.parentNode) { ancestor_ec = ancestor_ec.parentNode; }
-
-
- var node = dom.node(sc);
- if (!dom.isNotBreakable(node)) {
- sc = dom.splitTree(ancestor_sc, {'node': sc, 'offset': so});
- }
- var before = dom.hasContentBefore(dom.ancestorHavePreviousSibling(sc));
-
- var after;
- if (ec.textContent.slice(eo, Infinity).match(/\S|\u00A0/)) {
- after = dom.splitTree(ancestor_ec, {'node': ec, 'offset': eo});
- } else {
- after = dom.hasContentAfter(dom.ancestorHaveNextSibling(ec));
- }
-
- var nodes = dom.listBetween(sc, ec);
-
- var ancestor_first_last = function (node) {
- return node === before || node === after;
- };
-
- for (var i=0; i<nodes.length; i++) {
- if (!dom.ancestor(nodes[i], ancestor_first_last) && !$.contains(nodes[i], before) && !$.contains(nodes[i], after)) {
- nodes[i].parentNode.removeChild(nodes[i]);
- }
- }
-
- sc = before ? dom.lastChild(before) : dom.firstChild(after);
- so = sc.textContent.length;
-
- if (towrite && !node.firstChild && node.parentNode && !dom.isNotBreakable(node)) {
- sc = $("<br/>")[0];
- so = 0;
- node.appendChild(br);
- } else if (!ancestor.children.length && !ancestor.textContent.match(/\S|\u00A0/)) {
- sc = $("<br/>")[0];
- so = 0;
- $(ancestor).prepend(sc);
- } else if (before) {
- var text = sc.textContent.replace(/[ \t\n\r]+$/, '\u00A0');
- so -= sc.textContent.length - text.length;
- sc.textContent = text;
- }
-
- } else {
-
- var text = ancestor.textContent;
- ancestor.textContent = text.slice(0, so) + text.slice(eo, Infinity).replace(/^[ \t\n\r]+/, '\u00A0');
-
- }
-
- eo = so;
- if(!dom.isBR(sc) && !sc.textContent.match(/\S|\u00A0/) && !dom.isText(dom.hasContentBefore(sc)) && !dom.isText(dom.hasContentAfter(sc))) {
- ancestor = dom.node(sc);
- var text = document.createTextNode('\u00A0');
- $(sc).before(text);
- sc = text;
- so = 0;
- eo = 1;
- }
- return {
- sc: sc,
- so: so,
- ec: sc,
- eo: eo
- };
-};
-dom.indent = function (node) {
- var margin = parseFloat(node.style.marginLeft || 0)+1.5;
- node.style.marginLeft = margin + "em";
- return margin;
-};
-dom.outdent = function (node) {
- var margin = parseFloat(node.style.marginLeft || 0)-1.5;
- node.style.marginLeft = margin > 0 ? margin + "em" : "";
- return margin;
-};
-dom.scrollIntoViewIfNeeded = function (node) {
- var node = dom.node(node);
-
- var $span;
- if (dom.isBR(node)) {
- $span = $('<span/>').text('\u00A0');
- $(node).after($span);
- node = $span[0];
- }
-
- if (node.scrollIntoViewIfNeeded) {
- node.scrollIntoViewIfNeeded(false);
- } else {
- var offsetParent = node.offsetParent;
- while (offsetParent) {
- var elY = 0;
- var elH = node.offsetHeight;
- var parent = node;
-
- while (offsetParent && parent) {
- elY += node.offsetTop;
-
- // get if a parent have a scrollbar
- parent = node.parentNode;
- while (parent != offsetParent &&
- (parent.tagName === "BODY" || ["auto", "scroll"].indexOf(window.getComputedStyle(parent).overflowY) === -1)) {
- parent = parent.parentNode;
- }
- node = parent;
-
- if (parent !== offsetParent) {
- elY -= parent.offsetTop;
- parent = null;
- }
-
- offsetParent = node.offsetParent;
- }
-
- if ((node.tagName === "BODY" || ["auto", "scroll"].indexOf(window.getComputedStyle(node).overflowY) !== -1) &&
- (node.scrollTop + node.clientHeight) < (elY + elH)) {
- node.scrollTop = (elY + elH) - node.clientHeight;
- }
- }
- }
-
- if ($span) {
- $span.remove();
- }
-
- return;
-};
-dom.moveTo = function (node, target, before) {
- var nodes = [];
- while (node.firstChild) {
- nodes.push(node.firstChild);
- if (before) {
- target.insertBefore(node.firstChild, before);
- } else {
- target.appendChild(node.firstChild);
- }
- }
- node.parentNode.removeChild(node);
- return nodes;
-};
-dom.isMergable = function (node) {
- return node.tagName && "h1 h2 h3 h4 h5 h6 p b bold i u code sup strong small li a ul ol font".indexOf(node.tagName.toLowerCase()) !== -1;
-};
-dom.isSplitable = function (node) {
- return node.tagName && "h1 h2 h3 h4 h5 h6 p b bold i u code sup strong small li a font".indexOf(node.tagName.toLowerCase()) !== -1;
-};
-dom.isRemovableEmptyNode = function (node) {
- return "h1 h2 h3 h4 h5 h6 p b bold i u code sup strong small li a ul ol font span br".indexOf(node.tagName.toLowerCase()) !== -1;
-};
-dom.isForbiddenNode = function (node) {
- return node.tagName === "BR" || $(node).is(".fa, img");
-};
-dom.listBetween = function (sc, ec) {
- var nodes = [];
- var ancestor = dom.commonAncestor(sc, ec);
- dom.walkPoint({'node': sc, 'offset': 0}, {'node': ec, 'offset': 0}, function (point) {
- if (ancestor !== point.node || ancestor === sc || ancestor === ec) {
- nodes.push(point.node);
- }
- });
- return list.unique(nodes);
-};
-dom.isNotBreakable = function (node, sc, so, ec, eo) {
- // avoid triple click => crappy dom
- return node === ec && !dom.isText(ec) && !dom.isBR(dom.firstChild(ec));
-};
-
-dom.isContentEditable = function (node) {
- return $(node).closest('[contenteditable]').is('[contenteditable="true"]');
-};
-
-dom.isFont = function (node) {
- var nodeName = node && node.nodeName.toUpperCase();
- return node && (nodeName === "FONT" ||
- (nodeName === "SPAN" && (
- node.className.match(/(^|\s)fa(\s|$)/i) ||
- node.className.match(/(^|\s)(text|bg)-/i) ||
- (node.attributes.style && node.attributes.style.value.match(/(^|\s)(color|background-color|font-size):/i)))) );
-};
-dom.isVisibleText = function (textNode) {
- return !!textNode.textContent.match(/\S|\u00A0/);
-};
-/**
- * order the style of the node to compare 2 nodes and remove attribute if empty
- *
- * @param {Node} node
- * @return {String} className
- */
-dom.orderStyle = function (node) {
- var style = node.getAttribute('style');
- if (!style) return null;
- style = style.replace(/[\s\n\r]+/, ' ').replace(/^ ?;? ?| ?;? ?$/g, '').replace(/ ?; ?/g, ';');
- if (!style.length) {
- node.removeAttribute("style");
- return null;
- }
- style = style.split(";");
- style.sort();
- style = style.join("; ")+";";
- node.setAttribute('style', style);
- return style;
-};
-/**
- * order the class of the node to compare 2 nodes and remove attribute if empty
- *
- * @param {Node} node
- * @return {String} className
- */
-dom.orderClass = function (node) {
- var className = node.getAttribute('class');
- if (!className) return null;
- className = className.replace(/[\s\n\r]+/, ' ').replace(/^ | $/g, '').replace(/ +/g, ' ');
- if (!className.length) {
- node.removeAttribute("class");
- return null;
- }
- className = className.split(" ");
- className.sort();
- className = className.join(" ");
- node.setAttribute('class', className);
- return className;
-};
-/**
- * return the current node (if text node, return parentNode)
- *
- * @param {Node} node
- * @return {Node} node
- */
-dom.node = function (node) {
- return dom.isText(node) ? node.parentNode : node;
-};
-/**
- * move all childNode to an other node
- *
- * @param {Node} from
- * @param {Node} to
- */
-dom.moveContent = function (from, to) {
- if (from === to) {
- return;
- }
- if (from.parentNode === to) {
- while (from.lastChild) {
- dom.insertAfter(from.lastChild, from);
- }
- } else {
- while (from.firstChild && from.firstChild != to) {
- to.appendChild(from.firstChild);
- }
- }
-};
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-range.WrappedRange.prototype.reRange = function (keep_end, isNotBreakable) {
- var sc = this.sc;
- var so = this.so;
- var ec = this.ec;
- var eo = this.eo;
- isNotBreakable = isNotBreakable || dom.isNotBreakable;
-
- // search the first snippet editable node
- var start = keep_end ? ec : sc;
- while (start) {
- if (isNotBreakable(start, sc, so, ec, eo)) {
- break;
- }
- start = start.parentNode;
- }
-
- // check if the end caret have the same node
- var lastFilterEnd;
- var end = keep_end ? sc : ec;
- while (end) {
- if (start === end) {
- break;
- }
- if (isNotBreakable(end, sc, so, ec, eo)) {
- lastFilterEnd = end;
- }
- end = end.parentNode;
- }
- if (lastFilterEnd) {
- end = lastFilterEnd;
- }
- if (!end) {
- end = document.getElementsByTagName('body')[0];
- }
-
- // if same node, keep range
- if (start === end || !start) {
- return this;
- }
-
- // reduce or extend the range to don't break a isNotBreakable area
- if ($.contains(start, end)) {
-
- if (keep_end) {
- sc = dom.lastChild(dom.hasContentBefore(dom.ancestorHavePreviousSibling(end)));
- so = sc.textContent.length;
- } else if (!eo) {
- ec = dom.lastChild(dom.hasContentBefore(dom.ancestorHavePreviousSibling(end)));
- eo = ec.textContent.length;
- } else {
- ec = dom.firstChild(dom.hasContentAfter(dom.ancestorHaveNextSibling(end)));
- eo = 0;
- }
- } else {
-
- if (keep_end) {
- sc = dom.firstChild(start);
- so = 0;
- } else {
- ec = dom.lastChild(start);
- eo = ec.textContent.length;
- }
- }
-
- return new range.WrappedRange(sc, so, ec, eo);
-};
-range.WrappedRange.prototype.deleteContents = function (towrite) {
- var prevBP = dom.removeBetween(this.sc, this.so, this.ec, this.eo, towrite);
-
- $(dom.node(prevBP.sc)).trigger("click"); // trigger click to disable and reanable editor and image handler
- return new range.WrappedRange(
- prevBP.sc,
- prevBP.so,
- prevBP.ec,
- prevBP.eo
- );
-};
-range.WrappedRange.prototype.clean = function (mergeFilter, all) {
- var node = dom.node(this.sc === this.ec ? this.sc : this.commonAncestor());
- if (node.childNodes.length <=1) {
- return this;
- }
-
- var merge = dom.merge(node, this.sc, this.so, this.ec, this.eo, mergeFilter, all);
- var rem = dom.removeSpace(node.parentNode, merge.sc, merge.so, merge.ec, merge.eo);
-
- if (merge.merged || rem.removed) {
- return range.create(rem.sc, rem.so, rem.ec, rem.eo);
- }
- return this;
-};
-range.WrappedRange.prototype.remove = function (mergeFilter) {
-};
-range.WrappedRange.prototype.isOnCellFirst = function () {
- var node = dom.ancestor(this.sc, function (node) {return ["LI", "DIV", "TD","TH"].indexOf(node.tagName) !== -1;});
- return node && ["TD","TH"].indexOf(node.tagName) !== -1;
-};
-range.WrappedRange.prototype.isContentEditable = function () {
- return dom.isContentEditable(this.sc) && (this.sc === this.ec || dom.isContentEditable(this.ec));
-};
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-renderer.tplButtonInfo.fontsize = function (lang, options) {
- var items = options.fontSizes.reduce(function (memo, v) {
- return memo + '<li><a data-event="fontSize" href="#" data-value="' + v + '">' +
- '<i class="fa fa-check"></i> ' + v +
- '</a></li>';
- }, '');
-
- var sLabel = '<span class="note-current-fontsize">11</span>';
- return renderer.getTemplate().button(sLabel, {
- title: lang.font.size,
- dropdown: '<ul class="dropdown-menu">' + items + '</ul>'
- });
-};
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-/* add some text commands */
-
-key.nameFromCode[46] = 'DELETE';
-key.nameFromCode[27] = 'ESCAPE';
-
-options.keyMap.pc['BACKSPACE'] = 'backspace';
-options.keyMap.pc['DELETE'] = 'delete';
-options.keyMap.pc['ENTER'] = 'enter';
-options.keyMap.pc['ESCAPE'] = 'cancel';
-options.keyMap.mac['SHIFT+TAB'] = 'untab';
-
-options.keyMap.mac['BACKSPACE'] = 'backspace';
-options.keyMap.mac['CMD+BACKSPACE'] = 'delete';
-options.keyMap.mac['SHIFT+BACKSPACE'] = 'delete';
-options.keyMap.mac['ENTER'] = 'enter';
-options.keyMap.mac['ESCAPE'] = 'cancel';
-
-$.summernote.pluginEvents.insertTable = function (event, editor, layoutInfo, sDim) {
- var $editable = layoutInfo.editable();
- var dimension = sDim.split('x');
- var rng = range.create();
- rng = rng.deleteContents();
-
- var isBodyContainer = dom.isBodyContainer;
- dom.isBodyContainer = dom.isNotBreakable;
- rng.insertNode(editor.table.createTable(dimension[0], dimension[1]));
- dom.isBodyContainer = isBodyContainer;
-
- editor.afterCommand($editable);
- event.preventDefault();
- return false;
-};
-$.summernote.pluginEvents.tab = function (event, editor, layoutInfo, outdent) {
- var $editable = layoutInfo.editable();
- var r = range.create();
- var outdent = outdent || false;
-
- if (r.isCollapsed()) {
- if (r.isOnCell() && r.isOnCellFirst()) {
- var td = dom.ancestor(r.sc, dom.isCell);
- if (!outdent && !dom.nextElementSibling(td) && !dom.nextElementSibling(td.parentNode)) {
- range.create(td.lastChild, td.lastChild.textContent.length, td.lastChild, td.lastChild.textContent.length).select();
- $.summernote.pluginEvents.enter(event, editor, layoutInfo);
- } else if (outdent && !dom.previousElementSibling(td) && !$(td.parentNode).text().match(/\S/)) {
- $.summernote.pluginEvents.backspace(event, editor, layoutInfo);
- } else {
- $editable.data('NoteHistory').splitNext();
- editor.table.tab(r, outdent);
- }
- event.preventDefault();
- return false;
- }
-
- if (!r.sc.textContent.slice(0,r.so).match(/\S/) && r.isOnList()) {
- if (outdent) {
- $.summernote.pluginEvents.outdent(event, editor, layoutInfo);
- } else {
- $.summernote.pluginEvents.indent(event, editor, layoutInfo);
- }
- } else {
- if (!outdent){
- var next = r.sc.splitText(r.so);
- editor.typing.insertTab($editable, r, options.tabsize);
- r = range.create(next, 0, next, 0);
- r = dom.merge(r.sc.parentNode, r.sc, r.so, r.ec, r.eo, null, true);
- range.create(r.sc, r.so, r.ec, r.eo).select();
- } else {
- r = dom.merge(r.sc.parentNode, r.sc, r.so, r.ec, r.eo, null, true);
- r = range.create(r.sc, r.so, r.ec, r.eo);
- var next = r.sc.splitText(r.so);
- r.sc.textContent = r.sc.textContent.replace(/(\u00A0)+$/g, '');
- next.textContent = next.textContent.replace(/^(\u00A0)+/g, '');
- range.create(r.sc, r.sc.textContent.length, r.sc, r.sc.textContent.length).select();
- }
- event.preventDefault();
- return false;
- }
- }
- event.preventDefault();
- return false;
-};
-$.summernote.pluginEvents.untab = function (event, editor, layoutInfo) {
- return $.summernote.pluginEvents.tab(event, editor, layoutInfo, true);
-};
-$.summernote.pluginEvents.enter = function (event, editor, layoutInfo) {
- var $editable = layoutInfo.editable();
- $editable.data('NoteHistory').recordUndo($editable, 'enter');
-
- var r = range.create();
- if (!r.isContentEditable()) {
- event.preventDefault();
- return false;
- }
- if (!r.isCollapsed()) {
- r = r.deleteContents();
- r.select();
- }
-
- var br = $("<br/>")[0];
-
- // table: add a tr
- var td = dom.ancestor(r.sc, dom.isCell);
- if (td && (r.sc === td || r.sc === td.lastChild || (dom.isBR(td.lastChild) && r.sc === td.lastChild.previousSibling)) && r.so === r.sc.textContent.length && r.isOnCell() && !dom.nextElementSibling(td)) {
- var $node = $(td.parentNode);
- var $clone = $node.clone();
- $clone.children().html(dom.blank);
- $node.after($clone);
- var node = dom.firstElementChild($clone[0]) || $clone[0];
- range.create(node, 0, node, 0).select();
- dom.scrollIntoViewIfNeeded(br);
- event.preventDefault();
- return false;
- }
-
- var contentBefore = r.sc.textContent.slice(0,r.so).match(/\S|\u00A0/);
- if (!contentBefore && dom.isText(r.sc)) {
- var node = r.sc.previousSibling;
- while (!contentBefore && node && dom.isText(node)) {
- contentBefore = dom.isVisibleText(node);
- node = node.previousSibling;
- }
- }
-
- var node = dom.node(r.sc);
- var last = node;
- while (node && dom.isSplitable(node) && !dom.isList(node) && !dom.isEditable(node)) {
- last = node;
- node = node.parentNode;
- }
-
- if (last === node && !dom.isBR(node)) {
- node = r.insertNode(br, true);
- do {
- node = dom.hasContentAfter(node);
- } while (node && dom.isBR(node));
-
- // create an other br because the user can't see the new line with only br in a block
- if (!node) {
- $(br).before($("<br/>")[0]);
- }
- node = br.nextSibling || br;
- } else if (last === node && dom.isBR(node)) {
- $(node).after(br);
- node = br;
- } else if (!r.so && r.isOnList() && !r.sc.textContent.length && !dom.ancestor(r.sc, dom.isLi).nextElementSibling) {
- // double enter on the end of a list = new line out of the list
- node = $('<p></p>').append(br).insertAfter(dom.ancestor(r.sc, dom.isList))[0];
- node = br;
- } else if (last === r.sc) {
- if (dom.isBR(last)) {
- last = last.parentNode;
- }
- var $node = $(last);
- var $clone = $node.clone().text("");
- $node.after($clone);
- node = dom.node(dom.firstElementChild($clone[0]) || $clone[0]);
- $(node).html(br);
- node = br;
- } else {
- node = dom.splitTree(last, {'node': r.sc, 'offset': r.so});
- if (!contentBefore) {
- var cur = dom.node(dom.lastChild(node.previousSibling));
- if (!dom.isBR(cur)) {
- $(cur).html(br);
- }
- }
- if (!node.textContent.match(/\S|\u00A0/)) {
- node = dom.firstChild(node);
- $(dom.node( dom.isBR(node) ? node.parentNode : node )).html(br);
- node = br;
- }
- }
-
- if (node) {
- node = dom.firstChild(node);
- if (dom.isBR(node)) {
- range.createFromNode(node).select();
- } else {
- range.create(node,0).select();
- }
- dom.scrollIntoViewIfNeeded(node);
- }
- event.preventDefault();
- return false;
-};
-$.summernote.pluginEvents.visible = function (event, editor, layoutInfo) {
- var $editable = layoutInfo.editable();
- $editable.data('NoteHistory').recordUndo($editable, "visible");
-
- var r = range.create();
- if (r && !r.isCollapsed()) {
- r = r.deleteContents(true);
- r.select();
- }
-
- // don't write in forbidden tag (like span for font awsome)
- var node = dom.firstChild(r.sc.tagName && r.so ? r.sc.childNodes[r.so] : r.sc);
- while (node.parentNode) {
- if (dom.isForbiddenNode(node)) {
- var text = node.previousSibling;
- if (text && dom.isText(text) && text.textContent.match(/\S|\u00A0/)) {
- range.create(text, text.textContent.length, text, text.textContent.length).select();
- } else {
- text = node.parentNode.insertBefore(document.createTextNode( "." ), node);
- range.create(text, 1, text, 1).select();
- setTimeout(function () {
- var text = range.create().sc;
- text.textContent = text.textContent.replace(/^./, '');
- range.create(text, text.textContent.length, text, text.textContent.length).select();
- },0);
- }
- break;
- }
- node = node.parentNode;
- }
-
- return true;
-};
-
-function summernote_keydown_clean (field) {
- setTimeout(function () {
- var r = range.create();
- if (!r) return;
- var node = r[field];
- while (dom.isText(node)) {node = node.parentNode;}
- node = node.parentNode;
- var data = dom.merge(node, r.sc, r.so, r.ec, r.eo, null, true);
- data = dom.removeSpace(node.parentNode, data.sc, data.so, data.sc, data.so);
-
- range.create(data.sc, data.so, data.sc, data.so).select();
- },0);
-}
-
-function remove_table_content(sc, ec) {
- var nodes = dom.listBetween(sc, ec);
- nodes.push(dom.node(sc), dom.node(ec));
- for (var i in nodes) {
- if (dom.isCell(nodes[i])) {
- $(nodes[i]).html("<br/>");
- }
- }
- event.preventDefault();
- return false;
-}
-
-$.summernote.pluginEvents.delete = function (event, editor, layoutInfo) {
- var $editable = layoutInfo.editable();
- $editable.data('NoteHistory').recordUndo($editable, "delete");
-
- var r = range.create();
- if (!r.isContentEditable()) {
- return false;
- }
- if (!r.isCollapsed()) {
- if (dom.isCell(dom.node(r.sc)) || dom.isCell(dom.node(r.ec))) {
- return remove_table_content(r.sc, r.ec);
- }
- r = r.deleteContents();
- r.select();
- }
-
- var target = r.ec;
- var offset = r.eo;
- if (target.tagName && target.childNodes[offset]) {
- target = target.childNodes[offset];
- offset = 0;
- }
-
- var node = dom.node(target);
- var data = dom.merge(node, target, offset, target, offset, null, true);
- data = dom.removeSpace(node.parentNode, data.sc, data.so, data.ec, data.eo);
- r = range.create(data.sc, data.so);
- r.select();
- target = r.sc;
- offset = r.so;
-
- while (!dom.hasContentAfter(node) && !dom.hasContentBefore(node) && !dom.isImg(node)) {node = node.parentNode;}
-
- var contentAfter = target.textContent.slice(offset,Infinity).match(/\S|\u00A0/);
- var content = target.textContent.replace(/[ \t\r\n]+$/, '');
- var temp;
- var temp2;
-
- // media
- if (dom.isImg(node) || (!contentAfter && dom.isImg(dom.hasContentAfter(node)))) {
- var parent;
- var index;
- if (!dom.isImg(node)) {
- node = dom.hasContentAfter(node);
- }
- while (dom.isImg(node)) {
- parent = node.parentNode;
- index = dom.makeOffsetPath(parent, node)[0];
- if (index>0) {
- var next = node.previousSibling;
- range.create(next,next.textContent.length).select();
- }
- if (!dom.hasContentAfter(node) && !dom.hasContentBefore(node)) {
- parent.appendChild($('<br/>')[0]);
- }
- parent.removeChild(node);
- node = parent;
- }
- }
- // empty tag
- else if (!content.length && target.tagName && dom.isRemovableEmptyNode(dom.isBR(target) ? target.parentNode : target)) {
- if (node === $editable[0] || $.contains(node, $editable[0])) {
- event.preventDefault();
- return false;
- }
- var before = false;
- var next = dom.hasContentAfter(dom.ancestorHaveNextSibling(node));
- if (!dom.isContentEditable(next)) {
- before = true;
- next = dom.hasContentBefore(dom.ancestorHavePreviousSibling(node));
- }
- dom.removeSpace(next.parentNode, next, 0, next, 0); // clean before jump for not select invisible space between 2 tag
- next = dom.firstChild(next);
- node.parentNode.removeChild(node);
- range.create(next, before ? next.textContent.length : 0).select();
- }
- // normal feature if same tag and not the end
- else if (contentAfter) {
- return true;
- }
- // merge with the next text node
- else if (dom.isText(target) && (temp = dom.hasContentAfter(target)) && dom.isText(temp)) {
- return true;
- }
- //merge with the next block
- else if ((temp = dom.ancestorHaveNextSibling(target)) &&
- dom.isMergable(temp) &&
- dom.isMergable(temp2 = dom.hasContentAfter(temp)) &&
- temp.tagName === temp2.tagName &&
- (temp.tagName !== "LI" || !$('ul,ol', temp).length) && (temp2.tagName !== "LI" || !$('ul,ol', temp2).length) && // protect li
- !dom.isNotBreakable(temp) &&
- !dom.isNotBreakable(temp2)) {
- dom.autoMerge(target, false);
- var next = dom.firstChild(dom.hasContentAfter(dom.ancestorHaveNextSibling(target)));
- if (dom.isBR(next)) {
- range.create(next.previousSibling, next.previousSibling.textContent.length).select();
- next.parentNode.removeChild(next);
- } else {
- range.create(next, 0).select();
- }
- }
- // jump to next node for delete
- else if ((temp = dom.ancestorHaveNextSibling(target)) && (temp2 = dom.hasContentAfter(temp)) && dom.isContentEditable(temp2)) {
-
- dom.removeSpace(temp2.parentNode, temp2, 0, temp, 0); // clean before jump for not select invisible space between 2 tag
- temp2 = dom.firstChild(temp2);
-
- r = range.create(temp2, 0);
- r.select();
-
- if ((dom.isText(temp) || window.getComputedStyle(temp).display === "inline") && (dom.isText(temp2) || window.getComputedStyle(temp2).display === "inline")) {
- if (dom.isText(temp2)) {
- temp2.textContent = temp2.textContent.replace(/^\s*\S/, '');
- } else {
- $.summernote.pluginEvents.delete(event, editor, layoutInfo);
- }
- }
- }
-
- $(dom.node(r.sc)).trigger("click"); // trigger click to disable and reanable editor and image handler
- event.preventDefault();
- return false;
-};
-$.summernote.pluginEvents.backspace = function (event, editor, layoutInfo) {
- var $editable = layoutInfo.editable();
- $editable.data('NoteHistory').recordUndo($editable, "backspace");
-
- var r = range.create();
- if (!r.isContentEditable()) {
- event.preventDefault();
- return false;
- }
- if (!r.isCollapsed()) {
- if (dom.isCell(dom.node(r.sc)) || dom.isCell(dom.node(r.ec))) {
- return remove_table_content(r.sc, r.ec);
- }
- r = r.deleteContents();
- r.select();
- }
-
- var target = r.sc;
- var offset = r.so;
- if (target.tagName && target.childNodes[offset]) {
- target = target.childNodes[offset];
- offset = 0;
- }
-
- var node = dom.node(target);
- var data = dom.merge(node, target, offset, target, offset, null, true);
- data = dom.removeSpace(node.parentNode, data.sc, data.so, data.ec, data.eo);
- r = range.create(data.sc, data.so);
- r.select();
- target = r.sc;
- offset = r.so;
-
- while (node.parentNode && !dom.hasContentAfter(node) && !dom.hasContentBefore(node) && !dom.isImg(node)) {node = node.parentNode;}
-
- var contentBefore = target.textContent.slice(0,offset).match(/\S|\u00A0/);
- var content = target.textContent.replace(/[ \t\r\n]+$/, '');
- var temp;
- var temp2;
-
- // delete media
- if (dom.isImg(node) || (!contentBefore && dom.isImg(dom.hasContentBefore(node)))) {
- if (!dom.isImg(node)) {
- node = dom.hasContentBefore(node);
- }
- range.createFromNode(node).select();
- $.summernote.pluginEvents.delete(event, editor, layoutInfo);
- }
- // table tr td
- else if (r.isOnCell() && !offset && (target === (temp = dom.ancestor(target, dom.isCell)) || target === temp.firstChild)) {
- if (dom.previousElementSibling(temp)) {
- var td = dom.previousElementSibling(temp);
- node = td.lastChild || td;
- } else {
- var tr = temp.parentNode;
- var prevTr = dom.previousElementSibling(tr);
- if (!$(temp.parentNode).text().match(/\S|\u00A0/)) {
- if (prevTr) {
- tr.parentNode.removeChild(tr);
- node = (dom.lastElementChild(prevTr).lastChild && dom.lastElementChild(prevTr).lastChild.tagName ? dom.lastElementChild(prevTr).lastChild.previousSibling : dom.lastElementChild(prevTr).lastChild) || dom.lastElementChild(prevTr);
- range.create(node, node.textContent.length, node, node.textContent.length).select();
- }
- } else {
- node = dom.lastElementChild(prevTr).lastChild || dom.lastElementChild(prevTr);
- }
- }
- if (dom.isBR(node)) {
- range.createFromNode(node).select();
- } else {
- range.create(node, dom.nodeLength(node)).select();
- }
- }
- // empty tag
- else if (!content.length && target.tagName && dom.isRemovableEmptyNode(target)) {
- if (node === $editable[0] || $.contains(node, $editable[0])) {
- event.preventDefault();
- return false;
- }
- var before = true;
- var prev = dom.hasContentBefore(dom.ancestorHavePreviousSibling(node));
- if (!dom.isContentEditable(prev)) {
- before = false;
- prev = dom.hasContentAfter(dom.ancestorHaveNextSibling(node));
- }
- dom.removeSpace(prev.parentNode, prev, 0, prev, 0); // clean before jump for not select invisible space between 2 tag
- prev = dom.lastChild(prev);
- node.parentNode.removeChild(node);
- range.createFromNode(prev).select();
- range.create(prev, before ? prev.textContent.length : 0).select();
- }
- // normal feature if same tag and not the begin
- else if (contentBefore) {
- return true;
- }
- // merge with the previous text node
- else if (dom.isText(target) && (temp = dom.hasContentBefore(target)) && (dom.isText(temp) || dom.isBR(temp))) {
- return true;
- }
- //merge with the previous block
- else if ((temp = dom.ancestorHavePreviousSibling(target)) &&
- dom.isMergable(temp) &&
- dom.isMergable(temp2 = dom.hasContentBefore(temp)) &&
- temp.tagName === temp2.tagName &&
- (temp.tagName !== "LI" || !$('ul,ol', temp).length) && (temp2.tagName !== "LI" || !$('ul,ol', temp2).length) && // protect li
- !dom.isNotBreakable(temp) &&
- !dom.isNotBreakable(temp2)) {
- var prev = dom.firstChild(target);
- dom.autoMerge(target, true);
- range.create(prev, 0).select();
- }
- // jump to previous node for delete
- else if ((temp = dom.ancestorHavePreviousSibling(target)) && (temp2 = dom.hasContentBefore(temp)) && dom.isContentEditable(temp2)) {
-
- dom.removeSpace(temp2.parentNode, temp2, 0, temp, 0); // clean before jump for not select invisible space between 2 tag
- temp2 = dom.lastChild(temp2);
-
- r = range.create(temp2, temp2.textContent.length, temp2, temp2.textContent.length);
- r.select();
-
- if ((dom.isText(temp) || window.getComputedStyle(temp).display === "inline") && (dom.isText(temp2) || window.getComputedStyle(temp2).display === "inline")) {
- if (dom.isText(temp2)) {
- temp2.textContent = temp2.textContent.replace(/\S\s*$/, '');
- } else {
- $.summernote.pluginEvents.backspace(event, editor, layoutInfo);
- }
- }
- }
-
- var rng = range.create();
- if (rng) {
- $(dom.node(rng.sc)).trigger("click"); // trigger click to disable and reanable editor and image handler
- dom.scrollIntoViewIfNeeded(rng.sc.parentNode.previousElementSibling || rng.sc);
- }
-
- event.preventDefault();
- return false;
-};
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-/* add list command (create a uggly dom for chrome) */
-
-function isFormatNode(node) {
- return node.tagName && options.styleTags.indexOf(node.tagName.toLowerCase()) !== -1;
-}
-
-$.summernote.pluginEvents.insertUnorderedList = function (event, editor, layoutInfo, sorted) {
- var $editable = layoutInfo.editable();
- $editable.data('NoteHistory').recordUndo($editable);
-
- var parent;
- var rng = range.create();
- var node = rng.sc;
- while (node && node !== $editable[0]) {
-
- parent = node.parentNode;
- if (node.tagName === (sorted ? "UL" : "OL")) {
-
- var ul = document.createElement(sorted ? "ol" : "ul");
- ul.className = node.className;
- parent.insertBefore(ul, node);
- while (node.firstChild) {
- ul.appendChild(node.firstChild);
- }
- parent.removeChild(node);
- rng.select();
- return;
-
- } else if (node.tagName === (sorted ? "OL" : "UL")) {
-
- var lis = [];
- for (var i=0; i<node.children.length; i++) {
- lis.push(node.children[i]);
- }
-
- if (parent.tagName === "LI") {
- node = parent;
- parent = node.parentNode;
- _.each(lis, function (li) {
- parent.insertBefore(li, node);
- });
- } else {
- _.each(lis, function (li) {
- while (li.firstChild) {
- parent.insertBefore(li.firstChild, node);
- }
- });
- }
-
- parent.removeChild(node);
- rng.select();
- return;
-
- }
- node = parent;
- }
-
- var p0 = rng.sc;
- while (p0 && p0.parentNode && p0.parentNode !== $editable[0] && !isFormatNode(p0)) {
- p0 = p0.parentNode;
- }
- if (!p0) return;
- var p1 = rng.ec;
- while (p1 && p1.parentNode && p1.parentNode !== $editable[0] && !isFormatNode(p1)) {
- p1 = p1.parentNode;
- }
- if (!p0.parentNode || p0.parentNode !== p1.parentNode) {
- return;
- }
-
- var parent = p0.parentNode;
- var ul = document.createElement(sorted ? "ol" : "ul");
- parent.insertBefore(ul, p0);
- var childNodes = parent.childNodes;
- var brs = [];
- var begin = false;
- for (var i=0; i<childNodes.length; i++) {
- if (begin && dom.isBR(childNodes[i])) {
- parent.removeChild(childNodes[i]);
- i--;
- }
- if ((!dom.isText(childNodes[i]) && !isFormatNode(childNodes[i])) || (!ul.firstChild && childNodes[i] !== p0) ||
- $.contains(ul, childNodes[i]) || (dom.isText(childNodes[i]) && !childNodes[i].textContent.match(/\S|u00A0/))) {
- continue;
- }
- begin = true;
- var li = document.createElement('li');
- ul.appendChild(li);
- li.appendChild(childNodes[i]);
- if (li.firstChild === p1) {
- break;
- }
- i--;
- }
- if (dom.isBR(childNodes[i])) {
- parent.removeChild(childNodes[i]);
- }
-
- for (var i=0; i<brs.length; i++) {
- parent.removeChild(brs[i]);
- }
- rng.clean().select();
- event.preventDefault();
- return false;
-};
-$.summernote.pluginEvents.insertOrderedList = function (event, editor, layoutInfo) {
- return $.summernote.pluginEvents.insertUnorderedList(event, editor, layoutInfo, true);
-};
-$.summernote.pluginEvents.indent = function (event, editor, layoutInfo, outdent) {
- var $editable = layoutInfo.editable();
- $editable.data('NoteHistory').recordUndo($editable);
- var r = range.create();
-
- var flag = false;
- function indentUL (UL, start, end) {
- var next;
- var tagName = UL.tagName;
- var node = UL.firstChild;
- var parent = UL.parentNode;
- var ul = document.createElement(tagName);
- var li = document.createElement("li");
- li.style.listStyle = "none";
- li.appendChild(ul);
-
- if (flag) {
- flag = 1;
- }
-
- // create and fill ul into a li
- while (node) {
- if (flag === 1 || node === start || $.contains(node, start)) {
- flag = true;
- node.parentNode.insertBefore(li, node);
- }
- next = dom.nextElementSibling(node);
- if (flag) {
- ul.appendChild(node);
- }
- if (node === end || $.contains(node, end)) {
- flag = false;
- break;
- }
- node = next;
- }
-
- var temp;
- var prev = dom.previousElementSibling(li);
- if (prev && prev.tagName === "LI" && (temp = dom.firstElementChild(prev)) && temp.tagName === tagName && ((dom.firstElementChild(prev) || prev.firstChild) !== ul)) {
- dom.doMerge(dom.firstElementChild(prev) || prev.firstChild, ul);
- li = prev;
- li.parentNode.removeChild(dom.nextElementSibling(li));
- }
- var next = dom.nextElementSibling(li);
- if (next && next.tagName === "LI" && (temp = dom.firstElementChild(next)) && temp.tagName === tagName && (dom.firstElementChild(li) !== dom.firstElementChild(next))) {
- dom.doMerge(dom.firstElementChild(li), dom.firstElementChild(next));
- li.parentNode.removeChild(dom.nextElementSibling(li));
- }
- }
- function outdenttUL (UL, start, end) {
- var next;
- var tagName = UL.tagName;
- var node = UL.firstChild;
- var parent = UL.parentNode;
- var li = UL.parentNode.tagName === "LI" ? UL.parentNode : UL;
- var ul = UL.parentNode.tagName === "LI" ? UL.parentNode.parentNode : UL.parentNode;
- start = dom.ancestor(start, dom.isLi);
- end = dom.ancestor(end, dom.isLi);
-
- if (ul.tagName !== "UL" && ul.tagName !== "OL") return;
-
- // create and fill ul into a li
- while (node) {
- if (node === start || $.contains(node, start)) {
- flag = true;
- if (dom.previousElementSibling(node) && li.tagName === "LI") {
- li = dom.splitTree(li, dom.prevPoint({'node': node, 'offset': 0}));
- }
- }
- next = dom.nextElementSibling(node);
- if (flag) {
- ul = node.parentNode;
- li.parentNode.insertBefore(node, li);
- if (!ul.children.length) {
- if (ul.parentNode.tagName === "LI") {
- ul = ul.parentNode;
- }
- ul.parentNode.removeChild(ul);
- }
- }
-
- if (node === end || $.contains(node, end)) {
- flag = false;
- break;
- }
- node = next;
- }
-
- dom.merge(parent, start, 0, end, 1, null, true);
- }
- function indentOther (p, start, end) {
- if (p === start || $.contains(p, start)) {
- flag = true;
- }
- if (flag) {
- if (outdent) {
- dom.outdent(p);
- } else {
- dom.indent(p);
- }
- }
- if (p === end || $.contains(p, end)) {
- flag = false;
- }
- }
-
- var ancestor = r.commonAncestor();
- var $dom = $(ancestor);
-
- if (!dom.isList(ancestor)) {
- $dom = $(ancestor).children();
- }
- if (!$dom.length) {
- $dom = $(dom.ancestor(r.sc, dom.isList));
- if (!$dom.length) {
- $dom = $(r.sc).closest(options.styleTags.join(','));
- }
- }
-
- $dom.each(function () {
- if (flag || $.contains(this, r.sc)) {
- if (dom.isList(this)) {
- if (outdent) {
- outdenttUL(this, r.sc, r.ec);
- } else {
- indentUL(this, r.sc, r.ec);
- }
- } else if (isFormatNode(this)) {
- indentOther(this, r.sc, r.ec);
- }
- }
- });
-
- if ($dom.length) {
- var $parent = $dom.parent();
-
- // remove text nodes between lists
- var $ul = $parent.find('ul, ol');
- if (!$ul.length) {
- $ul = $(dom.ancestor(r.sc, dom.isList));
- }
- $ul.each(function () {
- if (this.previousSibling &&
- this.previousSibling !== dom.previousElementSibling(this) &&
- !this.previousSibling.textContent.match(/\S/)) {
- this.parentNode.removeChild(this.previousSibling);
- }
- if (this.nextSibling &&
- this.nextSibling !== dom.nextElementSibling(this) &&
- !this.nextSibling.textContent.match(/\S/)) {
- this.parentNode.removeChild(this.nextSibling);
- }
- });
-
- // merge same ul or ol
- r = dom.merge($parent[0], r.sc, r.so, r.ec, r.eo, function (prev, cur) {
- if (prev && dom.isList(prev) && dom.isEqual(prev, cur)) {
- return true;
- }
- }, true);
- range.create(r.sc, r.so, r.ec, r.eo).select();
- }
- event.preventDefault();
- return false;
-};
-$.summernote.pluginEvents.outdent = function (event, editor, layoutInfo) {
- return $.summernote.pluginEvents.indent(event, editor, layoutInfo, true);
-};
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-$.summernote.pluginEvents.formatBlock = function (event, editor, layoutInfo, sTagName) {
- var $editable = layoutInfo.editable();
- $editable.data('NoteHistory').recordUndo($editable);
- event.preventDefault();
-
- var r = range.create();
- if (!r) {
- return;
- }
- r.reRange().select();
-
- if (sTagName === "blockquote" || sTagName === "pre") {
- sTagName = $.summernote.core.agent.isMSIE ? '<' + sTagName + '>' : sTagName;
- document.execCommand('FormatBlock', false, sTagName);
- return;
- }
-
- // 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);
- for (var i=0; i<nodes.length; i++) {
- if (dom.isBR(nodes[i]) || (dom.isText(nodes[i]) && nodes[i].textContent.match(/\S|\u00A0/)) || 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);
- if (!ancestor) {
- dom.wrap(nodes[i], sTagName);
- } else if (ancestor.tagName.toLowerCase() !== sTagName) {
- var tag = document.createElement(sTagName);
- ancestor.parentNode.insertBefore(tag, ancestor);
- dom.moveContent(ancestor, tag);
- if (ancestor.className) {
- tag.className = ancestor.className;
- }
- ancestor.parentNode.removeChild(ancestor);
- }
- }
- }
- r.select();
-};
-$.summernote.pluginEvents.removeFormat = function (event, editor, layoutInfo, value) {
- var $editable = layoutInfo.editable();
- $editable.data('NoteHistory').recordUndo($editable);
-
- var node = range.create().sc.parentNode;
- document.execCommand('removeFormat');
- document.execCommand('removeFormat'); // 2 times because some browser don't clean all in one time
- var r = range.create();
- r = dom.merge(node, r.sc, r.so, r.ec, r.eo, null, true);
- r = range.create(r.sc, r.so, r.ec, r.eo);
- r.select();
-
- $.summernote.pluginEvents.justify(event, editor, layoutInfo, "");
-
- r.clean().select();
-
- event.preventDefault();
- return false;
-};
-var fn_boutton_updateRecentColor = eventHandler.toolbar.button.updateRecentColor;
-eventHandler.toolbar.button.updateRecentColor = function (elBtn, sEvent, sValue) {
- fn_boutton_updateRecentColor.call(this, elBtn, sEvent, sValue);
- var font = $(elBtn).closest('.note-color').find('.note-recent-color i')[0];
-
- if (sEvent === "foreColor") {
- if (sValue.indexOf('text-') !== -1) {
- font.className += ' ' + sValue;
- font.style.color = '';
- } else {
- font.className = font.className.replace(/(^|\s+)text-\S+/);
- font.style.color = sValue !== 'inherit' ? sValue : "";
- }
- } else {
- if (sValue.indexOf('bg-') !== -1) {
- font.className += ' ' + sValue;
- font.style.backgroundColor = "";
- } else {
- font.className = font.className.replace(/(^|\s+)bg-\S+/);
- font.style.backgroundColor = sValue !== 'inherit' ? sValue : "";
- }
- }
- event.preventDefault();
- return false;
-};
-
-options.fontSizes = [_t('Default'), 8, 9, 10, 11, 12, 14, 18, 24, 36, 48, 62];
-$.summernote.pluginEvents.applyFont = function (event, editor, layoutInfo, color, bgcolor, size) {
- var $editable = layoutInfo.editable();
- $editable.data('NoteHistory').recordUndo($editable);
-
- var rng = range.create();
- var startPoint = rng.getStartPoint();
- var endPoint = rng.getEndPoint();
-
- if (rng.isCollapsed()) {
- return {
- sc: startPoint.node,
- so: startPoint.offset,
- ec: endPoint.node,
- offset: endPoint.offset
- };
- }
-
- if (startPoint.node.tagName && startPoint.node.childNodes[startPoint.offset]) {
- startPoint.node = startPoint.node.childNodes[startPoint.offset];
- startPoint.offset = 0;
- }
- if (endPoint.node.tagName && endPoint.node.childNodes[endPoint.offset]) {
- endPoint.node = endPoint.node.childNodes[endPoint.offset];
- endPoint.offset = 0;
- }
-
- // get first and last point
- if (endPoint.offset && endPoint.offset != dom.nodeLength(endPoint.node)) {
- var ancestor = dom.ancestor(endPoint.node, dom.isFont) || endPoint.node;
- dom.splitTree(ancestor, endPoint);
- }
- if (startPoint.offset && startPoint.offset != dom.nodeLength(startPoint.node)) {
- var ancestor = dom.ancestor(startPoint.node, dom.isFont) || startPoint.node;
- var node = dom.splitTree(ancestor, startPoint);
- if (endPoint.node === startPoint.node) {
- endPoint.node = node;
- endPoint.offset = dom.nodeLength(node);
- }
- startPoint.node = node;
- startPoint.offset = 0;
- }
-
- // get list of nodes to change
- var nodes = [];
- dom.walkPoint(startPoint, endPoint, function (point) {
- var node = point.node;
- if (((dom.isText(node) && dom.isVisibleText(node)) ||
- (dom.isFont(node) && !dom.isVisibleText(node))) &&
- (node != endPoint.node || endPoint.offset)) {
-
- nodes.push(point.node);
-
- }
- });
- nodes = list.unique(nodes);
-
- // apply font: foreColor, backColor, size (the color can be use a class text-... or bg-...)
- var node, font, $font, fonts = [], className;
- if (color || bgcolor || size) {
- for (var i=0; i<nodes.length; i++) {
- node = nodes[i];
-
- font = dom.ancestor(node, dom.isFont);
- if (!font) {
- if (node.textContent.match(/^[ ]|[ ]$/)) {
- node.textContent = node.textContent.replace(/^[ ]|[ ]$/g, '\u00A0');
- }
-
- font = dom.create("font");
- node.parentNode.insertBefore(font, node);
- font.appendChild(node);
- }
-
- fonts.push(font);
-
- className = font.className.split(/\s+/);
-
- if (color) {
- for (var k=0; k<className.length; k++) {
- if (!className[k].length && className[k].slice(0,5) === "text-") {
- className.splice(k,1);
- k--;
- }
- }
-
- if (color.indexOf('text-') !== -1) {
- font.className = className.join(" ") + " " + color;
- font.style.color = "inherit";
- } else {
- font.className = className.join(" ");
- font.style.color = color;
- }
- }
- if (bgcolor) {
- for (var k=0; k<className.length; k++) {
- if (className[k].length && className[k].slice(0,3) === "bg-") {
- className.splice(k,1);
- k--;
- }
- }
-
- if (bgcolor.indexOf('bg-') !== -1) {
- font.className = className.join(" ") + " " + bgcolor;
- font.style.backgroundColor = "inherit";
- } else {
- font.className = className.join(" ");
- font.style.backgroundColor = bgcolor;
- }
- }
- if (size) {
- font.style.fontSize = "inherit";
- if (!isNaN(size) && Math.abs(parseInt(window.getComputedStyle(font).fontSize, 10)-size)/size > 0.05) {
- font.style.fontSize = size + "px";
- }
- }
- }
- }
-
- // remove empty values
- // we must remove the value in 2 steps (applay inherit then remove) because some
- // browser like chrome have some time an error for the rendering and/or keep inherit
- for (var i=0; i<fonts.length; i++) {
- font = fonts[i];
- if (font.style.backgroundColor === "inherit") {
- font.style.backgroundColor = "";
- }
- if (font.style.color === "inherit") {
- font.style.color = "";
- }
- if (font.style.fontSize === "inherit") {
- font.style.fontSize = "";
- }
-
- $font = $(font);
-
- if (!$font.css("color") && !$font.css("background-color") && !$font.css("font-size")) {
- $font.removeAttr("style");
- }
- if (!font.className.length) {
- $font.removeAttr("class");
- }
- }
-
- // select nodes to clean (to remove empty font and merge same nodes)
- var nodes = [];
- dom.walkPoint(startPoint, endPoint, function (point) {
- nodes.push(point.node);
- });
- nodes = list.unique(nodes);
-
- function remove (node, to) {
- if (node === endPoint.node) {
- endPoint = dom.prevPoint(endPoint);
- }
- if (to) {
- dom.moveContent(node, to);
- }
- dom.remove(node);
- }
-
- // remove node without attributes (move content), and merge the same nodes
- var className2, style, style2, $prev;
- for (var i=0; i<nodes.length; i++) {
- node = nodes[i];
-
- if ((dom.isText(node) || dom.isBR(node)) && !dom.isVisibleText(node)) {
- remove(node);
- nodes.splice(i,1);
- i--;
- continue;
- }
-
- font = dom.ancestor(node, dom.isFont);
- node = font || dom.ancestor(node, dom.isSpan);
-
- if (!node) {
- continue;
- }
-
- $font = $(node);
- className = dom.orderClass(node);
- style = dom.orderStyle(node);
-
- if (!className && !style) {
- remove(node, node.parentNode);
- nodes.splice(i,1);
- i--;
- continue;
- }
-
- if (i>0 && (font = dom.ancestor(nodes[i-1], dom.isFont))) {
- className2 = font.getAttribute('class');
- style2 = font.getAttribute('style');
- if (node !== font && className == className2 && style == style2 && (node.parentNode === font.parentNode || node.parentNode === font)) {
- remove(node, font);
- nodes.splice(i,1);
- i--;
- continue;
- }
- }
- }
-
- range.create(startPoint.node, startPoint.offset, endPoint.node, endPoint.offset).select();
-};
-$.summernote.pluginEvents.fontSize = function (event, editor, layoutInfo, value) {
- var $editable = layoutInfo.editable();
- $editable.data('NoteHistory').recordUndo($editable);
-
- event.preventDefault();
- $.summernote.pluginEvents.applyFont(event, editor, layoutInfo, null, null, value);
- editor.afterCommand($editable);
-};
-$.summernote.pluginEvents.color = function (event, editor, layoutInfo, sObjColor) {
- var $editable = layoutInfo.editable();
- var oColor = JSON.parse(sObjColor);
- var foreColor = oColor.foreColor, backColor = oColor.backColor;
-
- if (foreColor) { $.summernote.pluginEvents.foreColor(event, editor, layoutInfo, foreColor); }
- if (backColor) { $.summernote.pluginEvents.backColor(event, editor, layoutInfo, backColor); }
-};
-$.summernote.pluginEvents.foreColor = function (event, editor, layoutInfo, foreColor) {
- var $editable = layoutInfo.editable();
- $.summernote.pluginEvents.applyFont(event, editor, layoutInfo, foreColor, null, null);
- editor.afterCommand($editable);
-};
-$.summernote.pluginEvents.backColor = function (event, editor, layoutInfo, backColor) {
- var $editable = layoutInfo.editable();
- var r = range.create();
- if (r.isCollapsed() && r.isOnCell()) {
- var cell = dom.ancestor(r.sc, dom.isCell);
- cell.className = cell.className.replace(new RegExp('(^|\\s+)bg-[^\\s]+(\\s+|$)', 'gi'), '');
- cell.style.backgroundColor = "";
- if (backColor.indexOf('bg-') !== -1) {
- cell.className += ' ' + backColor;
- } else if (backColor !== 'inherit') {
- cell.style.backgroundColor = backColor;
- }
- return;
- }
- $.summernote.pluginEvents.applyFont(event, editor, layoutInfo, null, backColor, null);
- editor.afterCommand($editable);
- };
-
- $.summernote.pluginEvents.justify = function (event, editor, layoutInfo, align) {
- var rng = range.create();
- var startPoint = rng.getStartPoint();
- var endPoint = rng.getEndPoint();
-
- // get list of nodes to change
- var nodes = [];
- nodes.push(dom.ancestor(startPoint.node, dom.isPara) || dom.ancestor(startPoint.node, dom.isCell));
- nodes.push(dom.ancestor(endPoint.node, dom.isPara) || dom.ancestor(endPoint.node, dom.isCell));
- dom.walkPoint(startPoint, endPoint, function (point) {
- var node = point.node;
- if (dom.isPara(node) || dom.isCell(node)) {
- nodes.push(point.node);
- }
- });
- nodes = list.unique(nodes);
-
- $(nodes).not(":has(div,p,li,h1,h2,h3,h4,h5,h6,h7,td,th)").each(function () {
- var $node = $(this).css('text-align', '');
- var css = window.getComputedStyle(this);
- var textAlign = css.textAlign;
- if (textAlign === "start") {
- textAlign = css.direction === "ltr" ? "left" : "right";
- }
- if(textAlign !== align) {
- $node.css('text-align', align);
- }
- }).find("*").css('text-align', "");
- };
- $.summernote.pluginEvents.justifyLeft = function (event, editor, layoutInfo) {
- var $editable = layoutInfo.editable();
- $editable.data('NoteHistory').recordUndo($editable);
- $.summernote.pluginEvents.justify(event, editor, layoutInfo, 'left');
- editor.afterCommand($editable);
- };
- $.summernote.pluginEvents.justifyCenter = function (event, editor, layoutInfo) {
- var $editable = layoutInfo.editable();
- $editable.data('NoteHistory').recordUndo($editable);
- $.summernote.pluginEvents.justify(event, editor, layoutInfo, 'center');
- editor.afterCommand($editable);
- };
- $.summernote.pluginEvents.justifyRight = function (event, editor, layoutInfo) {
- var $editable = layoutInfo.editable();
- $editable.data('NoteHistory').recordUndo($editable);
- $.summernote.pluginEvents.justify(event, editor, layoutInfo, 'right');
- editor.afterCommand($editable);
- };
- $.summernote.pluginEvents.justifyFull = function (event, editor, layoutInfo) {
- var $editable = layoutInfo.editable();
- $editable.data('NoteHistory').recordUndo($editable);
- $.summernote.pluginEvents.justify(event, editor, layoutInfo, 'justify');
- editor.afterCommand($editable);
-};
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-options.onCreateLink = function (sLinkUrl) {
- if (sLinkUrl.indexOf('mailto:') === 0) {
- // pass
- } else if (sLinkUrl.indexOf('@') !== -1 && sLinkUrl.indexOf(':') === -1) {
- sLinkUrl = 'mailto:' + sLinkUrl;
- } else if (sLinkUrl.indexOf('://') === -1 && sLinkUrl.indexOf('/') !== 0 && sLinkUrl.indexOf('#') !== 0) {
- sLinkUrl = 'http://' + sLinkUrl;
- }
- return sLinkUrl;
-};
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-/* table */
-
-function summernote_table_scroll (event) {
- if (range.create().isOnCell()) {
- $('.o_table_handler').remove();
- }
-}
-function summernote_table_update (oStyle) {
- var r = range.create();
- if (!r || !r.isOnCell() || !r.isOnCellFirst()) {
- $('.o_table_handler').remove();
- return;
- }
- var table = dom.ancestor(oStyle.range.sc, dom.isTable);
- var $editable = $(table).closest('.o_editable');
-
- $('.o_table_handler').remove();
-
- var $dels = $();
- var $adds = $();
- var $tds = $('tr:first', table).children();
- $tds.each(function () {
- var $td = $(this);
- var pos = $td.offset();
-
- var $del = $('<span class="o_table_handler fa fa-minus-square"/>').appendTo('body');
- $del.data('td', this);
- $dels = $dels.add($del);
- $del.css({
- left: ((pos.left + $td.outerWidth()/2)-6) + "px",
- top: (pos.top-6) + "px"
- });
-
- var $add = $('<span class="o_table_handler fa fa-plus-square"/>').appendTo('body');
- $add.data('td', this);
- $adds = $adds.add($add);
- $add.css({
- left: (pos.left-6) + "px",
- top: (pos.top-6) + "px"
- });
- });
-
- var $last = $tds.last();
- var pos = $last.offset();
- var $add = $('<span class="o_table_handler fa fa-plus-square"/>').appendTo('body');
- $adds = $adds.add($add);
- $add.css({
- left: (pos.left+$last.outerWidth()-6) + "px",
- top: (pos.top-6) + "px"
- });
-
- var $table = $(table);
- $dels.data('table', table).on('mousedown', function (event) {
- var td = $(this).data('td');
- $editable.data('NoteHistory').recordUndo($editable);
-
- var newTd;
- if ($(td).siblings().length) {
- var eq = $(td).index();
- $table.find('tr').each(function () {
- $('> td:eq('+eq+')', this).remove();
- });
- newTd = $table.find('tr:first > td:eq('+eq+'), tr:first > td:last').first();
- } else {
- var prev = dom.lastChild(dom.hasContentBefore(dom.ancestorHavePreviousSibling($table[0])));
- $table.remove();
- $('.o_table_handler').remove();
- r = range.create(prev, prev.textContent.length);
- r.select();
- $(r.sc).trigger('mouseup');
- return;
- }
-
- $('.o_table_handler').remove();
- range.create(newTd[0], 0, newTd[0], 0).select();
- newTd.trigger('mouseup');
- });
- $adds.data('table', table).on('mousedown', function (event) {
- var td = $(this).data('td');
- $editable.data('NoteHistory').recordUndo($editable);
-
- var newTd;
- if (td) {
- var eq = $(td).index();
- $table.find('tr').each(function () {
- $('td:eq('+eq+')', this).before('<td>'+dom.blank+'</td>');
- });
- newTd = $table.find('tr:first td:eq('+eq+')');
- } else {
- $table.find('tr').each(function () {
- $(this).append('<td>'+dom.blank+'</td>');
- });
- newTd = $table.find('tr:first td:last');
- }
-
- $('.o_table_handler').remove();
- range.create(newTd[0], 0, newTd[0], 0).select();
- newTd.trigger('mouseup');
- });
-
- $dels.css({
- 'position': 'absolute',
- 'cursor': 'pointer',
- 'background-color': '#fff',
- 'color': '#ff0000'
- });
- $adds.css({
- 'position': 'absolute',
- 'cursor': 'pointer',
- 'background-color': '#fff',
- 'color': '#00ff00'
- });
-}
-var fn_popover_update = eventHandler.popover.update;
-eventHandler.popover.update = function ($popover, oStyle, isAirMode) {
- fn_popover_update.call(this, $popover, oStyle, isAirMode);
- summernote_table_update(oStyle);
-};
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-function summernote_paste (event) {
- // keep norma feature if copy a picture
- var clipboardData = event.originalEvent.clipboardData;
- if (clipboardData.items) {
- var item = list.last(clipboardData.items);
- var isClipboardImage = item.kind === 'file' && item.type.indexOf('image/') !== -1;
- if (isClipboardImage) {
- return true;
- }
- }
-
- var $editable = $(event.currentTarget);
- $editable = $editable.is('[contenteditable]') ? $editable : $editable.find('[contenteditable]');
- $editable.data('NoteHistory').recordUndo($editable);
-
- if (["INPUT", "TEXTAREA"].indexOf(event.target.tagName) === -1) {
- var r = range.create();
- if (!r.isCollapsed()) {
- r = r.deleteContents();
- r.select();
- }
-
- var text = clipboardData.getData("text/plain").replace(/</g, "&lt;");
- dom.pasteText(r.sc, r.so, text);
- event.preventDefault();
- return false;
- }
-}
-
-var fn_attach = eventHandler.attach;
-eventHandler.attach = function (oLayoutInfo, options) {
- var $editable = oLayoutInfo.editor.hasClass('note-editable') ? oLayoutInfo.editor : oLayoutInfo.editor.find('.note-editable');
- fn_attach.call(this, oLayoutInfo, options);
- oLayoutInfo.editor.on("paste", summernote_paste);
- $editable.on("scroll", summernote_table_scroll);
-};
-var fn_dettach = eventHandler.dettach;
-eventHandler.dettach = function (oLayoutInfo, options) {
- var $editable = oLayoutInfo.editor.hasClass('note-editable') ? oLayoutInfo.editor : oLayoutInfo.editor.find('.note-editable');
- fn_dettach.call(this, oLayoutInfo, options);
- oLayoutInfo.editor.off("paste", summernote_paste);
- $editable.off("scroll", summernote_table_scroll);
-};
-
-});
diff --git a/addons/website/static/src/js/website.backend.iframe.js b/addons/website/static/src/js/website.backend.iframe.js
deleted file mode 100644
index 925fb6aa4b1..00000000000
--- a/addons/website/static/src/js/website.backend.iframe.js
+++ /dev/null
@@ -1,75 +0,0 @@
-odoo.define('website.backend.iframe', function (require) {
-'use strict';
-
-var editor = require('website.editor');
-var snippet_editor = require('website.snippets.editor');
-
-window.top.odoo[callback+"_set_value"] = function (value, fields_values) {
- var $editable = $("#wrapwrap .o_editable:first");
- if (value !== $editable.html()) {
- if ($('body').hasClass('editor_enable')) {
- editor.editor_bar.rte.historyRecordUndo($editable);
- editor.editor_bar.snippets.make_active(false);
- }
- $editable.html(value);
- }
-};
-
-editor.EditorBar.include({
- start: function () {
- var self = this;
- var res = this._super.apply(this, arguments);
- if (location.search.indexOf("enable_editor") !== -1) {
- this.on('rte:ready', this, function () {
- $("#website-top-edit").hide();
- setTimeout(function () {
- if (window.top.odoo[callback+"_editor"]) {
- window.top.odoo[callback+"_editor"](this);
- }
- }, 0);
-
- 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.odoo[callback+"_downup"]($editable.prop('innerHTML'));
- });
-
-
- $(window).on('keydown', function (event) {
- if(event.keyCode === 27 && $("body", window.top.document).hasClass("o_form_FieldTextHtml_fullscreen")) {
- $(".o_fullscreen").trigger("click");
- }
- $(window).trigger('resize');
- });
-
- });
-
- 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.odoo[callback+"_editor"]) {
- window.top.odoo[callback+"_editor"](this);
- }
- return res;
- },
- cancel: function () {
- return;
- },
-});
-
-snippet_editor.BuildingBlock.include({
- _get_snippet_url: function () {
- return snippets_url;
- }
-});
-
-});
diff --git a/addons/website/static/src/js/website.backend.js b/addons/website/static/src/js/website.backend.js
index fb93bf0dadf..f877c0e90fc 100644
--- a/addons/website/static/src/js/website.backend.js
+++ b/addons/website/static/src/js/website.backend.js
@@ -22,157 +22,4 @@ var WidgetWebsiteButton = form_common.AbstractField.extend({
core.form_widget_registry.add('website_button', WidgetWebsiteButton);
-var FieldWidget = form_common.AbstractField.extend(form_common.ReinitializeFieldMixin);
-
-
-var FieldTextHtmlFrame = FieldWidget.extend({
- template: 'FieldTextHtmlFrame',
- start: function () {
- var self = this;
-
- this.callback = _.uniqueId('FieldTextHtml_');
- odoo[this.callback+"_editor"] = function (EditorBar) {
- self.on_editor_loaded(EditorBar);
- };
- odoo[this.callback+"_content"] = function () {
- self.on_content_loaded();
- };
- odoo[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.$('iframe');
- this.document = null;
- this.$body = $();
- this.$content = $();
-
- // init resize
- this.resize = function resize() {
- if (self.get('effective_readonly')) {
- $("body").removeClass("o_form_FieldTextHtml_fullscreen");
- }
- 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 {
- 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 (core.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() {
- if (!this.get("effective_readonly")) {
- this.$iframe = this.$el.find('iframe');
- this.document = null;
- this.$body = $();
- this.$content = $();
- this.dirty = false;
- this.editor = false;
- odoo[this.callback+"_set_value"] = null;
- this.$iframe.attr("src", this.get_url());
- }
- },
- on_content_loaded: function () {
- 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();
- }
- });
-
- if (this.get('value') && window.odoo[this.callback+"_set_value"] && !(this.$content.prop('innerHTML')||"").length) {
- this.render_value();
- }
-
- 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>');
- $("#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() {
- var value = (this.get('value') || "").replace(/^<p[^>]*>\s*<\/p>$/, '');
- if (!this.get("effective_readonly")) {
- if (!this.$content) {
- return;
- }
- if(window.odoo[this.callback+"_set_value"]) {
- window.odoo[this.callback+"_set_value"](value || '', this.view.get_fields_values(), this.name);
- this.resize();
- }
- } else {
- this.$el.html(value);
- }
- },
- 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 () {
- $("body").removeClass("o_form_FieldTextHtml_fullscreen");
- $(window).off('resize', self.resize);
- $(window).off('keydown', self.escape);
- delete window.odoo[this.callback+"_content"];
- delete window.odoo[this.callback+"_downup"];
- delete window.odoo[this.callback+"_set_value"];
- }
-});
-
-core.form_widget_registry.add('html_frame', FieldTextHtmlFrame);
-
});
diff --git a/addons/website/static/src/js/website.editor.js b/addons/website/static/src/js/website.editor.js
index 67e9b3da734..b6f463b11ba 100644
--- a/addons/website/static/src/js/website.editor.js
+++ b/addons/website/static/src/js/website.editor.js
@@ -3,1145 +3,55 @@ odoo.define('website.editor', function (require) {
var ajax = require('web.ajax');
var core = require('web.core');
-var utils = require('web.utils');
var Widget = require('web.Widget');
+var base = require('web_editor.base');
+var editor = require('web_editor.editor');
+var widget = require('web_editor.widget');
var website = require('website.website');
+var qweb = core.qweb;
var _t = core._t;
+ajax.loadXML('/website/static/src/xml/website.editor.xml', qweb);
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-/* Summernote Lib (neek change to make accessible: method and object) */
-var dom = $.summernote.core.dom;
-var range = $.summernote.core.range;
-var eventHandler = $.summernote.eventHandler;
-var renderer = $.summernote.renderer;
-
-var tplButton = renderer.getTemplate().button;
-var tplIconButton = renderer.getTemplate().iconButton;
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-/* update and change the popovers content, and add history button */
-
-var fn_createPalette = renderer.createPalette;
-renderer.createPalette = function ($container, options) {
- fn_createPalette.call(this, $container, options);
-
- if (!core.qweb.has_template('website.colorpicker')) {
- return;
- }
-
- var $color = $container.find('.note-color');
- var html = core.qweb.render('website.colorpicker');
- $color.find('.note-color-palette').prepend(html);
- var $bg = $color.find('.colorpicker:first button');
- var $fore = $color.find('.colorpicker:last button');
-
- $bg.each(function () { $(this).attr('data-event', 'backColor').attr('data-value', $(this).attr('class')); });
- $fore.each(function () { $(this).attr('data-event', 'foreColor').attr('data-value', $(this).attr('class').replace(/bg-/, 'text-')); });
-};
-
-var fn_tplPopovers = renderer.tplPopovers;
-renderer.tplPopovers = function (lang, options) {
- var $popover = $(fn_tplPopovers.call(this, lang, options));
-
- var $imagePopover = $popover.find('.note-image-popover');
- 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
- $(tplIconButton('fa fa-align-center', {
- title: _t('Center'),
- event: 'floatMe',
- value: 'center'
- })).insertAfter($imagePopover.find('[data-event="floatMe"][data-value="left"]'));
- $imagePopover.find('button[data-event="removeMedia"]').parent().remove();
- $imagePopover.find('button[data-event="floatMe"][data-value="none"]').remove();
-
- var $alt = $('<div class="btn-group"/>');
- $alt.prependTo($imagePopover.find('.popover-content'));
- $alt.append('<button class="btn btn-default btn-sm btn-small" data-event="alt"><strong>Alt: </strong><span class="o_image_alt"></span></button>');
-
- // padding button
- var $padding = $('<div class="btn-group"/>');
- $padding.insertBefore($imagePopover.find('.btn-group:first'));
- var $button = $(tplIconButton('fa fa-plus-square-o', {
- title: _t('Padding'),
- dropdown: true
- })).appendTo($padding);
- var $ul = $('<ul class="dropdown-menu"/>').insertAfter($button);
- $ul.append('<li><a data-event="padding" href="#" data-value="">'+_t('None')+'</a></li>');
- $ul.append('<li><a data-event="padding" href="#" data-value="small">'+_t('Small')+'</a></li>');
- $ul.append('<li><a data-event="padding" href="#" data-value="medium">'+_t('Medium')+'</a></li>');
- $ul.append('<li><a data-event="padding" href="#" data-value="large">'+_t('Large')+'</a></li>');
- $ul.append('<li><a data-event="padding" href="#" data-value="xl">'+_t('Xl')+'</a></li>');
-
- // circle, boxed... options became toggled
- $imagePopover.find('[data-event="imageShape"]:not([data-value])').remove();
- $button = $(tplIconButton('fa fa-sun-o', {
- title: _t('Shadow'),
- event: 'imageShape',
- value: 'shadow'
- })).insertAfter($imagePopover.find('[data-event="imageShape"][data-value="img-circle"]'));
-
- // add spin for fa
- var $spin = $('<div class="btn-group hidden only_fa"/>').insertAfter($button.parent());
- $(tplIconButton('fa fa-refresh', {
- title: _t('Spin'),
- event: 'imageShape',
- value: 'fa-spin'
- })).appendTo($spin);
-
- // resize for fa
- var $resizefa = $('<div class="btn-group hidden only_fa"/>')
- .insertAfter($imagePopover.find('.btn-group:has([data-event="resize"])'));
- for (var size=1; size<=5; size++) {
- $(tplButton('<span class="note-fontsize-10">'+size+'x</span>', {
- title: size+"x",
- event: 'resizefa',
- value: size+''
- })).appendTo($resizefa);
- }
- var $colorfa = $airPopover.find('.note-color').clone();
- $colorfa.find(".btn-group:first").remove();
- $colorfa.find("ul.dropdown-menu").css('min-width', '172px');
- $colorfa.find('button[data-event="color"]').attr('data-value', '{"foreColor": "#f00"}')
- .find("i").css({'background': '', 'color': '#f00'});
- $resizefa.after($colorfa);
-
- // show dialog box and delete
- var $imageprop = $('<div class="btn-group"/>');
- $imageprop.appendTo($imagePopover.find('.popover-content'));
- $(tplIconButton('fa fa-picture-o', {
- title: _t('Edit'),
- event: 'showImageDialog'
- })).appendTo($imageprop);
- $(tplIconButton('fa fa-trash-o', {
- title: _t('Remove'),
- event: 'delete'
- })).appendTo($imageprop);
-
- $imagePopover.find('.popover-content').append($airPopover.find(".note-history").clone());
-
- $imagePopover.find('[data-event="showImageDialog"]').before($airPopover.find('[data-event="showLinkDialog"]').clone());
-
- //////////////// link popover
-
- $linkPopover.find('.popover-content').append($airPopover.find(".note-history").clone());
-
- $linkPopover.find('button[data-event="showLinkDialog"] i').attr("class", "fa fa-link");
- $linkPopover.find('button[data-event="unlink"]').before($airPopover.find('button[data-event="showImageDialog"]').clone());
-
- //////////////// text/air popover
-
- //// highlight the text format
- $airPopover.find('.note-style').on('mousedown', function () {
- var $format = $airPopover.find('[data-event="formatBlock"]');
- var node = range.create().sc;
- var formats = $format.map(function () { return $(this).data("value"); }).get();
- while (node && (!node.tagName || (!node.tagName || formats.indexOf(node.tagName.toLowerCase()) === -1))) {
- node = node.parentNode;
- }
- $format.parent().removeClass('active');
- $format.filter('[data-value="'+(node ? node.tagName.toLowerCase() : "p")+'"]')
- .parent().addClass("active");
- });
-
- //////////////// tooltip
-
- $airPopover.add($linkPopover).add($imagePopover).find("button")
- .tooltip('destroy')
- .tooltip({
- container: 'body',
- trigger: 'hover',
- placement: 'bottom'
- }).on('click', function () {$(this).tooltip('hide');});
-
- return $popover;
-};
-
-var fn_boutton_update = eventHandler.popover.button.update;
-eventHandler.popover.button.update = function ($container, oStyle) {
- // stop animation when edit content
- var previous = $(".note-control-selection").data('target');
- if (previous) {
- $(previous).css({"-webkit-animation-play-state": "", "animation-play-state": "", "-webkit-transition": "", "transition": "", "-webkit-animation": "", "animation": ""});
- }
- if (oStyle.image) {
- $(oStyle.image).css({"-webkit-animation": "none", "animation": "none"});
- }
- // end
-
- fn_boutton_update.call(this, $container, oStyle);
-
- $container.find('button[data-event="undo"]').attr('disabled', !history.hasUndo());
- $container.find('button[data-event="redo"]').attr('disabled', !history.hasRedo());
-
- if (oStyle.image) {
- $container.find('[data-event]').parent().removeClass("active");
-
- $container.find('a[data-event="padding"][data-value="small"]').parent().toggleClass("active", $(oStyle.image).hasClass("padding-small"));
- $container.find('a[data-event="padding"][data-value="medium"]').parent().toggleClass("active", $(oStyle.image).hasClass("padding-medium"));
- $container.find('a[data-event="padding"][data-value="large"]').parent().toggleClass("active", $(oStyle.image).hasClass("padding-large"));
- $container.find('a[data-event="padding"][data-value="xl"]').parent().toggleClass("active", $(oStyle.image).hasClass("padding-xl"));
- $container.find('a[data-event="padding"][data-value=""]').parent().toggleClass("active", !$container.find('.active a[data-event="padding"]').length);
-
- if (dom.isImgFont(oStyle.image)) {
-
- $container.find('.btn-group:not(.only_fa):has(button[data-event="resize"],button[data-event="imageShape"])').addClass("hidden");
- $container.find('.only_fa').removeClass("hidden");
- $container.find('button[data-event="resizefa"][data-value="2"]').toggleClass("active", $(oStyle.image).hasClass("fa-2x"));
- $container.find('button[data-event="resizefa"][data-value="3"]').toggleClass("active", $(oStyle.image).hasClass("fa-3x"));
- $container.find('button[data-event="resizefa"][data-value="4"]').toggleClass("active", $(oStyle.image).hasClass("fa-4x"));
- $container.find('button[data-event="resizefa"][data-value="5"]').toggleClass("active", $(oStyle.image).hasClass("fa-5x"));
- $container.find('button[data-event="resizefa"][data-value="1"]').toggleClass("active", !$container.find('.active[data-event="resizefa"]').length);
-
- $container.find('button[data-event="imageShape"][data-value="fa-spin"]').toggleClass("active", $(oStyle.image).hasClass("fa-spin"));
-
- $container.find('.note-color').removeClass("hidden");
-
- } else {
-
- $container.find('.hidden:not(.only_fa)').removeClass("hidden");
- $container.find('.only_fa').addClass("hidden");
- var width = ($(oStyle.image).attr('style') || '').match(/(^|;|\s)width:\s*([0-9]+%)/);
- if (width) {
- width = width[2];
- }
- $container.find('button[data-event="resize"][data-value="1"]').toggleClass("active", width === "100%");
- $container.find('button[data-event="resize"][data-value="0.5"]').toggleClass("active", width === "50%");
- $container.find('button[data-event="resize"][data-value="0.25"]').toggleClass("active", width === "25%");
-
- $container.find('button[data-event="imageShape"][data-value="shadow"]').toggleClass("active", $(oStyle.image).hasClass("shadow"));
-
- if (!$(oStyle.image).is("img")) {
- $container.find('.btn-group:has(button[data-event="imageShape"])').addClass("hidden");
- }
-
- $container.find('.note-color').addClass("hidden");
-
- }
-
- $container.find('button[data-event="floatMe"][data-value="left"]').toggleClass("active", $(oStyle.image).hasClass("pull-left"));
- $container.find('button[data-event="floatMe"][data-value="center"]').toggleClass("active", $(oStyle.image).hasClass("center-block"));
- $container.find('button[data-event="floatMe"][data-value="right"]').toggleClass("active", $(oStyle.image).hasClass("pull-right"));
-
- $(oStyle.image).trigger('attributes_change');
- }
-};
-
-var fn_popover_update = eventHandler.popover.update;
-eventHandler.popover.update = function ($popover, oStyle, isAirMode) {
- var $imagePopover = $popover.find('.note-image-popover');
- var $linkPopover = $popover.find('.note-link-popover');
- var $airPopover = $popover.find('.note-air-popover');
-
- fn_popover_update.call(this, $popover, oStyle, isAirMode);
-
- if (!isAirMode || $(oStyle.range.sc).closest('[data-oe-model]:not([data-oe-model="ir.ui.view"]):not([data-oe-type="html"])').length) {
- $imagePopover.hide();
- $linkPopover.hide();
- $airPopover.hide();
- return;
- }
-
- if (oStyle.image) {
- if (oStyle.image.parentNode.className.match(/(^|\s)media_iframe_video(\s|$)/i)) {
- oStyle.image = oStyle.image.parentNode;
- }
- var alt = $(oStyle.image).attr("alt");
-
- $imagePopover.find('.o_image_alt').text( (alt || "").replace(/&quot;/g, '"') ).parent().toggle(oStyle.image.tagName === "IMG");
- $imagePopover.show();
-
- range.createFromNode(dom.firstChild(oStyle.image)).select();
- } else {
- $(".note-control-selection").hide();
- }
-
- if (oStyle.image || (!oStyle.range.isCollapsed() || (oStyle.range.sc.tagName && !dom.isAnchor(oStyle.range.sc)) || (oStyle.image && !$(oStyle.image).closest('a').length))) {
- $linkPopover.hide();
- oStyle.anchor = false;
- }
-
- if (oStyle.image || oStyle.anchor || !$(oStyle.range.sc).closest('.note-editable').length) {
- $airPopover.hide();
- } else {
- $airPopover.show();
- }
-};
-
-eventHandler.handle.update = function ($handle, oStyle) {
- $handle.toggle(!!oStyle.image);
- if (oStyle.image) {
- var $selection = $handle.find('.note-control-selection');
- var $image = $(oStyle.image);
- var szImage = {
- w: parseInt($image.outerWidth(true), 10),
- h: parseInt($image.outerHeight(true), 10)
- };
- $selection.data('target', oStyle.image); // save current image element.
- var sSizing = szImage.w + 'x' + szImage.h;
- $selection.find('.note-control-selection-info').text(szImage.h > 50 ? sSizing : "");
-
- $selection.find('.note-control-sizing').toggleClass('note-control-sizing note-control-holder').css({
- 'border-top': 0,
- 'border-left': 0
- });
- }
-};
-
-$(document).on('click keyup', function () {
- $('button[data-event="undo"]').attr('disabled', !history.hasUndo());
- $('button[data-event="redo"]').attr('disabled', !history.hasRedo());
-});
-
-eventHandler.editor.undo = function ($popover) {
- if(!$popover.attr('disabled')) history.undo();
-};
-eventHandler.editor.redo = function ($popover) {
- if(!$popover.attr('disabled')) history.redo();
-};
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-/* hack for image and link editor */
-
-function getImgTarget () {
- return $(".note-control-selection").data('target');
-}
-eventHandler.editor.padding = function ($editable, sValue) {
- var $target = $(getImgTarget());
- var paddings = "small medium large xl".split(/\s+/);
- $editable.data('NoteHistory').recordUndo();
- if (sValue.length) {
- paddings.splice(paddings.indexOf(sValue),1);
- $target.toggleClass('padding-'+sValue);
- }
- $target.removeClass("padding-" + paddings.join(" padding-"));
-};
-eventHandler.editor.resize = function ($editable, sValue) {
- var $target = $(getImgTarget());
- $editable.data('NoteHistory').recordUndo();
- var width = ($target.attr('style') || '').match(/(^|;|\s)width:\s*([0-9]+)%/);
- if (width) {
- width = width[2]/100;
- }
- $(getImgTarget()).css('width', width != sValue ? (sValue * 100) + '%' : '');
-};
-eventHandler.editor.resizefa = function ($editable, sValue) {
- var $target = $(getImgTarget());
- $editable.data('NoteHistory').recordUndo();
- $target.attr('class', $target.attr('class').replace(/\s*fa-[0-9]+x/g, ''));
- if (+sValue > 1) {
- $target.addClass('fa-'+sValue+'x');
- }
-};
-eventHandler.editor.floatMe = function ($editable, sValue) {
- var $target = $(getImgTarget());
- $editable.data('NoteHistory').recordUndo();
- switch (sValue) {
- case 'center': $target.toggleClass('center-block').removeClass('pull-right pull-left'); break;
- case 'left': $target.toggleClass('pull-left').removeClass('pull-right center-block'); break;
- case 'right': $target.toggleClass('pull-right').removeClass('pull-left center-block'); break;
- }
-};
-eventHandler.editor.imageShape = function ($editable, sValue) {
- var $target = $(getImgTarget());
- $editable.data('NoteHistory').recordUndo();
- $target.toggleClass(sValue);
-};
-
-eventHandler.dialog.showLinkDialog = function ($editable, $dialog, linkInfo) {
- $editable.data('range').select();
- $editable.data('NoteHistory').recordUndo();
-
- var editor = new LinkDialog($editable, linkInfo);
- editor.appendTo(document.body);
-
- var def = new $.Deferred();
- editor.on("save", this, function (linkInfo) {
- linkInfo.range.select();
- $editable.data('range', linkInfo.range);
- def.resolve(linkInfo);
- $editable.data('NoteHistory').popUndo();
- $('.note-popover .note-link-popover').show();
- });
- editor.on("cancel", this, function () {
- def.reject();
- $editable.data('NoteHistory').popUndo();
- });
- return def;
-};
-eventHandler.dialog.showImageDialog = function ($editable) {
- var r = $editable.data('range');
- if (r.sc.tagName && r.sc.childNodes.length) {
- r.sc = r.sc.childNodes[r.so];
- }
- var editor = new MediaDialog($editable, dom.isImg(r.sc) ? r.sc : null);
- editor.appendTo(document.body);
- return new $.Deferred().reject();
-};
-$.summernote.pluginEvents.alt = function (event, editor, layoutInfo) {
- var $editable = layoutInfo.editable();
- var $selection = layoutInfo.handle().find('.note-control-selection');
- var media = $selection.data('target');
- new alt($editable, media).appendTo(document.body);
-};
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-dom.isVoid = function (node) {
- return node && /^BR|^IMG|^HR/.test(node.nodeName.toUpperCase()) || dom.isImg(node);
-};
-dom.isImg = function (node) {
- return dom.isImgFont(node) || (node && (node.nodeName === "IMG" || (node.className && node.className.match(/(^|\s)media_iframe_video(\s|$)/i)) ));
-};
-dom.isForbiddenNode = function (node) {
- return $(node).is(".media_iframe_video, .fa, img");
-};
-
-dom.isImgFont = function (node) {
- var nodeName = node && node.nodeName.toUpperCase();
- var className = (node && node.className || "");
- if (node && (nodeName === "SPAN" || nodeName === "I") && className.length) {
- var classNames = className.split(/\s+/);
- for (var k=0; k<fontIcons.length; k++) {
- if (_.intersection(fontIcons[k].icons, classNames).length) {
- return true;
- }
- }
- }
- return false;
-};
-// re-overwrite font to include theme icons
-var isFont = dom.isFont;
-dom.isFont = function (node) {
- return dom.isImgFont(node) || isFont(node);
-};
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-var fn_visible = $.summernote.pluginEvents.visible;
-$.summernote.pluginEvents.visible = function (event, editor, layoutInfo) {
- var res = fn_visible.call(this, event, editor, layoutInfo);
- var $node = $(dom.node(range.create().sc));
- if (($node.is('[data-oe-type="html"]') || $node.is('[data-oe-field="arch"]')) && $node.hasClass("o_editable") && !$node[0].children.length) {
- var p = $('<p><br/></p>')[0];
- $node.append( p );
- range.createFromNode(p.firstChild).select();
- }
- return res;
-};
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-/* fix ie and re-range to don't break snippet*/
-
-var initial_data = {};
-function reRangeSelectKey (event) {
- initial_data.range = null;
- if (event.shiftKey && event.keyCode >= 37 && event.keyCode <= 40 && !$(event.target).is("input, textarea, select")) {
- var r = range.create();
- if (r) {
- var rng = r.reRange(event.keyCode <= 38);
- if (r !== rng) {
- rng.select();
- }
- }
- }
-}
-function reRangeSelect (event, dx, dy) {
- var r = range.create();
- if (!r || r.isCollapsed()) return;
-
- // check if the user move the caret on up or down
- var data = r.reRange(dy < 0 || (dy === 0 && dx < 0));
-
- if (data.sc !== r.sc || data.so !== r.so || data.ec !== r.ec || data.eo !== r.eo) {
- setTimeout(function () {
- data.select();
- $(data.sc.parentNode).closest('.note-popover');
- },0);
- }
-
- $(data.sc).closest('.o_editable').data('range', r);
- return r;
-}
-function summernote_mouseup (event) {
- if ($(event.target).closest("#website-top-navbar, .note-popover").length) {
- return;
- }
- // don't rerange if simple click
- if (initial_data.event) {
- var dx = event.clientX - (event.shiftKey ? initial_data.rect.left : initial_data.event.clientX);
- var dy = event.clientY - (event.shiftKey ? initial_data.rect.top : initial_data.event.clientY);
- if (10 < Math.pow(dx, 2)+Math.pow(dy, 2)) {
- 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, .note-editor");
-
- 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) {
- 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, .note-toolbar, .modal').length) {
- if (!$(event.target).is('input, select, label, button, a')) {
- if (!remember_selection && $editable[0]) {
- remember_selection = range.create(dom.firstChild($editable[0]), 0);
- }
- try {
- remember_selection.select();
- } catch (e) {
- console.warn(e);
- }
- }
- } 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;
-var last_div_change;
-var last_editable;
-function summernote_ie_fix (event, pred) {
- var editable;
- var div;
- var node = event.target;
- while(node.parentNode) {
- if (!div && pred(node)) {
- div = node;
- }
- if(last_div !== node && (node.getAttribute('contentEditable')==='false' || node.className && (node.className.indexOf('o_not_editable') !== -1))) {
- break;
- }
- if (node.className && node.className.indexOf('o_editable') !== -1) {
- if (!div) {
- div = node;
- }
- editable = node;
- break;
- }
- node = node.parentNode;
- }
-
- if (!editable) {
- $(last_div_change).removeAttr("contentEditable").removeProp("contentEditable");
- $(last_editable).attr("contentEditable", "true").prop("contentEditable", "true");
- last_div_change = null;
- last_editable = null;
- return;
- }
-
- if (div === last_div) {
- return;
- }
-
- last_div = div;
-
- $(last_div_change).removeAttr("contentEditable").removeProp("contentEditable");
-
- if (last_editable !== editable) {
- if ($(editable).is("[contentEditable='true']")) {
- $(editable).removeAttr("contentEditable").removeProp("contentEditable");
- last_editable = editable;
- } else {
- last_editable = null;
- }
- }
- if (!$(div).attr("contentEditable") && !$(div).is("[data-oe-type='many2one'], [data-oe-type='contact']")) {
- $(div).attr("contentEditable", "true").prop("contentEditable", "true");
- last_div_change = div;
- } else {
- last_div_change = null;
- }
- return editable !== div ? div : null;
-}
-
-var fn_attach = eventHandler.attach;
-eventHandler.attach = function (oLayoutInfo, options) {
- fn_attach.call(this, oLayoutInfo, options);
- oLayoutInfo.editor.on('dragstart', 'img', function (e) { e.preventDefault(); });
- $(document).on('mousedown', summernote_mousedown);
- $(document).on('mouseup', summernote_mouseup);
- oLayoutInfo.editor.off('click').on('click', function (e) {e.preventDefault();}); // if the content editable is a link
- oLayoutInfo.editor.on('dblclick', 'img, .media_iframe_video, span.fa, i.fa, span.fa', function (event) {
- if (!$(event.target).closest(".note-toolbar").length) { // prevent icon edition of top bar for default summernote
- new MediaDialog(oLayoutInfo.editor, event.target).appendTo(document.body);
- }
- });
- $(document).on("keyup", reRangeSelectKey);
-
- var clone_data = false;
- var $node = oLayoutInfo.editor;
- if ($node.data('oe-model')) {
- $node.on('content_changed', function () {
-
- var $nodes = $('[data-oe-model]')
- .filter(function () { return this != $node[0];})
- .filter('[data-oe-model="'+$node.data('oe-model')+'"]')
- .filter('[data-oe-id="'+$node.data('oe-id')+'"]')
- .filter('[data-oe-field="'+$node.data('oe-field')+'"]');
- if ($node.data('oe-type')) $nodes = $nodes.filter('[data-oe-type="'+$node.data('oe-type')+'"]');
- if ($node.data('oe-expression')) $nodes = $nodes.filter('[data-oe-expression="'+$node.data('oe-expression')+'"]');
- if ($node.data('oe-xpath')) $nodes = $nodes.filter('[data-oe-xpath="'+$node.data('oe-xpath')+'"]');
- if ($node.data('oe-contact-options')) $nodes = $nodes.filter('[data-oe-contact-options="'+$node.data('oe-contact-options')+'"]');
-
- var nodes = $node.get();
-
- if ($node.data('oe-type') === "many2one") {
- $nodes = $nodes.add($('[data-oe-model]')
- .filter(function () { return this != $node[0] && nodes.indexOf(this) === -1; })
- .filter('[data-oe-many2one-model="'+$node.data('oe-many2one-model')+'"]')
- .filter('[data-oe-many2one-id="'+$node.data('oe-many2one-id')+'"]')
- .filter('[data-oe-type="many2one"]'));
-
- $nodes = $nodes.add($('[data-oe-model]')
- .filter(function () { return this != $node[0] && nodes.indexOf(this) === -1; })
- .filter('[data-oe-model="'+$node.data('oe-many2one-model')+'"]')
- .filter('[data-oe-id="'+$node.data('oe-many2one-id')+'"]')
- .filter('[data-oe-field="name"]'));
- }
-
- if (!clone_data) {
- clone_data = true;
- $nodes.html(this.innerHTML);
- clone_data = false;
- }
- });
- }
-};
-var fn_dettach = eventHandler.dettach;
-eventHandler.dettach = function (oLayoutInfo, options) {
- fn_dettach.call(this, oLayoutInfo, options);
- oLayoutInfo.editor.off("dragstart");
- $(document).off('mousedown', summernote_mousedown);
- $(document).off('mouseup', summernote_mouseup);
- oLayoutInfo.editor.off("dblclick");
- $(document).off("keyup", reRangeSelectKey);
-};
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-/* Translation for odoo */
-
-$.summernote.lang.odoo = {
- font: {
- bold: _t('Bold'),
- italic: _t('Italic'),
- underline: _t('Underline'),
- strikethrough: _t('Strikethrough'),
- subscript: _t('Subscript'),
- superscript: _t('Superscript'),
- clear: _t('Remove Font Style'),
- height: _t('Line Height'),
- name: _t('Font Family'),
- size: _t('Font Size')
- },
- image: {
- image: _t('Picture'),
- insert: _t('Insert Image'),
- resizeFull: _t('Resize Full'),
- resizeHalf: _t('Resize Half'),
- resizeQuarter: _t('Resize Quarter'),
- floatLeft: _t('Float Left'),
- floatRight: _t('Float Right'),
- floatNone: _t('Float None'),
- dragImageHere: _t('Drag an image here'),
- selectFromFiles: _t('Select from files'),
- url: _t('Image URL'),
- remove: _t('Remove Image')
- },
- link: {
- link: _t('Link'),
- insert: _t('Insert Link'),
- unlink: _t('Unlink'),
- edit: _t('Edit'),
- textToDisplay: _t('Text to display'),
- url: _t('To what URL should this link go?'),
- openInNewWindow: _t('Open in new window')
- },
- video: {
- video: _t('Video'),
- videoLink: _t('Video Link'),
- insert: _t('Insert Video'),
- url: _t('Video URL?'),
- providers: _t('(YouTube, Vimeo, Vine, Instagram, DailyMotion or Youku)')
- },
- table: {
- table: _t('Table')
- },
- hr: {
- insert: _t('Insert Horizontal Rule')
- },
- style: {
- style: _t('Style'),
- normal: _t('Normal'),
- blockquote: _t('Quote'),
- pre: _t('Code'),
- h1: _t('Header 1'),
- h2: _t('Header 2'),
- h3: _t('Header 3'),
- h4: _t('Header 4'),
- h5: _t('Header 5'),
- h6: _t('Header 6')
- },
- lists: {
- unordered: _t('Unordered list'),
- ordered: _t('Ordered list')
- },
- options: {
- help: _t('Help'),
- fullscreen: _t('Full Screen'),
- codeview: _t('Code View')
- },
- paragraph: {
- paragraph: _t('Paragraph'),
- outdent: _t('Outdent'),
- indent: _t('Indent'),
- left: _t('Align left'),
- center: _t('Align center'),
- right: _t('Align right'),
- justify: _t('Justify full')
- },
- color: {
- recent: _t('Recent Color'),
- more: _t('More Color'),
- background: _t('Background Color'),
- foreground: _t('Foreground Color'),
- transparent: _t('Transparent'),
- setTransparent: _t('Set transparent'),
- reset: _t('Reset'),
- resetToDefault: _t('Reset to default')
- },
- shortcut: {
- shortcuts: _t('Keyboard shortcuts'),
- close: _t('Close'),
- textFormatting: _t('Text formatting'),
- action: _t('Action'),
- paragraphFormatting: _t('Paragraph formatting'),
- documentStyle: _t('Document Style')
+/**
+ * Object who contains all method and bind for the top bar, the template is create server side.
+ */
+website.TopBar.include({
+ events: {
+ 'click [data-action="edit"]': 'edit',
},
- history: {
- undo: _t('Undo'),
- redo: _t('Redo')
- }
-};
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-/* Change History to have a global History for all summernote instances */
-
-var History = function History ($editable) {
- var aUndo = [];
- var pos = 0;
-
- this.makeSnap = function () {
- var rng = range.create(),
- elEditable = dom.ancestor(rng && rng.commonAncestor(), dom.isEditable) || $('.o_editable:first')[0];
- return {
- editable: elEditable,
- contents: elEditable.innerHTML,
- bookmark: rng && rng.bookmark(elEditable),
- scrollTop: $(elEditable).scrollTop()
- };
- };
-
- this.applySnap = function (oSnap) {
- var $editable = $(oSnap.editable);
-
- if (!!document.documentMode) {
- $editable.removeAttr("contentEditable").removeProp("contentEditable");
- }
-
- $editable.html(oSnap.contents).scrollTop(oSnap.scrollTop);
- $(".oe_overlay").remove();
- $(".note-control-selection").hide();
-
- $editable.trigger("content_changed");
-
- if (!oSnap.bookmark) {
- return;
- }
-
- try {
- var r = range.createFromBookmark(oSnap.editable, oSnap.bookmark);
- r.select();
- } catch(e) {
- console.error(e);
- return;
- }
-
- $(document).trigger("click");
- $(".o_editable *").filter(function () {
- var $el = $(this);
- if($el.data('snippet-editor')) {
- $el.removeData();
+ start: function () {
+ var self = this;
+ $("#wrapwrap").on('click', '.o_editable, [data-oe-model]', function (event) {
+ var $this = $(event.srcElement);
+ var tag = $this[0] && $this[0].tagName.toLowerCase();
+ if (!(tag === 'a' || tag === "button") && !$this.parents("a, button").length) {
+ self.$('[data-action="edit"]').parent().effect('bounce', {distance: 18, times: 5}, 250);
}
});
- setTimeout(function () {
- var target = dom.isBR(r.sc) ? r.sc.parentNode : dom.node(r.sc);
- if (!target) {
- return;
- }
- var evt = document.createEvent("MouseEvents");
- evt.initMouseEvent("mousedown", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, target);
- target.dispatchEvent(evt);
-
- var other_evt = document.createEvent("MouseEvents");
- other_evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, target);
- target.dispatchEvent(other_evt);
- },0);
- };
-
- this.undo = function () {
- if (!pos) { return; }
- last = null;
- if (!aUndo[pos]) aUndo[pos] = this.makeSnap();
- if (aUndo[pos-1].jump) pos--;
- this.applySnap(aUndo[--pos]);
- };
- this.hasUndo = function () {
- return pos > 0;
- };
-
- this.redo = function () {
- if (aUndo.length <= pos+1) { return; }
- if (aUndo[pos].jump) pos++;
- this.applySnap(aUndo[++pos]);
- };
- this.hasRedo = function () {
- return aUndo.length > pos+1;
- };
+ $("#wrapwrap").find("[data-oe-model] .oe_structure.oe_empty, [data-oe-model].oe_structure.oe_empty, [data-oe-type=html]:empty")
+ .addClass("oe_empty")
+ .attr("data-oe-placeholder", _t("Press The Top-Left Edit Button"));
- this.popUndo = function () {
- pos--;
- aUndo.pop();
- };
-
- var last;
- 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)
- aUndo.splice(pos, aUndo.length);
- var prev = aUndo[pos-1];
- aUndo[pos] = {
- editable: prev.editable,
- contents: $(prev.editable).html(),
- bookmark: prev.bookmark,
- scrollTop: prev.scrollTop,
- jump: true
- };
- pos++;
- }
- else if (event === last) return;
+ if (location.search.indexOf("enable_editor") >= 0 && $('html').attr('lang') === "en_US") {
+ this.$el.hide();
}
- last = event;
- aUndo.splice(pos, aUndo.length);
- aUndo[pos] = this.makeSnap($editable);
- pos++;
- };
-
- this.splitNext = function () {
- last = false;
- };
-};
-var history = new History();
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-// add focusIn to jQuery to allow to move caret into a div of a contentEditable area
-$.fn.extend({
- focusIn: function () {
- if (this.length) {
- range.create(dom.firstChild(this[0]), 0).select();
- }
- return this;
- },
- selectContent: function () {
- if (this.length) {
- var next = dom.lastChild(this[0]);
- range.create(dom.firstChild(this[0]), 0, next, next.textContent.length).select();
- }
- return this;
+ return this._super();
},
- activateBlock: function () {
- var target = snippet_editor.snippet.globalSelector.closest($(this))[0] || (dom.isBR(this) ? this.parentNode : dom.node(this));
- var evt = document.createEvent("MouseEvents");
- evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, target);
- target.dispatchEvent(evt);
- return this;
+ edit: function () {
+ this.$('button[data-action=edit]').prop('disabled', true);
+ this.$el.hide();
+ editor.editor_bar = new editor.Class(this);
+ editor.editor_bar.prependTo(document.body);
}
});
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-function change_default_bootstrap_animation_to_edit() {
- var fn_carousel = $.fn.carousel;
- $.fn.carousel = function () {
- var res = fn_carousel.apply(this, arguments);
- // off bootstrap keydown event to remove event.preventDefault()
- // and allow to change cursor position
- $(this).off('keydown.bs.carousel');
- return res;
- };
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-website.no_editor = !!$(document.documentElement).data('editable-no-editor');
-
-website.add_template_file('/website/static/src/xml/website.editor.xml');
-website.dom_ready.done(function () {
- website.ready().then(init_editor);
-
- $(document).on('click', 'a.js_link2post', function (ev) {
- ev.preventDefault();
- website.form(this.pathname, 'POST');
- });
-
- $(document).on('click', '.note-editable', function (ev) {
- ev.preventDefault();
- });
-
- $(document).on('submit', '.note-editable form .btn', 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
- && $(ev.target).has(ev.originalEvent.target).length
- && $(ev.originalEvent.target).is('[contenteditable]')) {
- ev.preventDefault();
- }
- });
-});
-
-
-/* ----- TOP EDITOR BAR FOR ADMIN ---- */
-var EditorBar = Widget.extend({
- template: 'website.editorbar',
- events: {
- 'click button[data-action=save]': 'save',
- 'click a[data-action=cancel]': 'cancel',
- },
- start: function() {
- var self = this;
- this.saving_mutex = new utils.Mutex();
-
- this.$buttons = {
- edit: this.$el.parents().find('button[data-action=edit]'),
- save: this.$('button[data-action=save]'),
- cancel: this.$('button[data-action=cancel]'),
- };
-
- this.$('#website-top-edit').hide();
- this.$('#website-top-view').show();
-
- var $edit_button = this.$buttons.edit
- .prop('disabled', website.no_editor);
- if (website.no_editor) {
- var help_text = $(document.documentElement).data('editable-no-editor');
- $edit_button.parent()
- // help must be set on form above button because it does
- // not appear on disabled button
- .attr('title', help_text);
- }
-
- $('.dropdown-toggle').dropdown();
-
- this.$buttons.edit.click(function(ev) {
- self.edit();
- });
-
- this.rte = new RTE(this);
- this.rte.on('change', this, this.proxy('rte_changed'));
- this.rte.on('rte:ready', this, function () {
- self.trigger('rte:ready');
- });
-
- this.rte.appendTo(this.$('#website-top-edit .nav.js_editor_placeholder'));
- return this._super.apply(this, arguments);
- },
- edit: function (no_editor) {
- this.$buttons.edit.prop('disabled', true);
- this.$('#website-top-view').hide();
- this.$el.show();
- this.$('#website-top-edit').show();
-
- if (!no_editor) {
- this.rte.start_edition();
- this.trigger('rte:called');
- }
-
- var flag = false;
- window.onbeforeunload = function(event) {
- if ($('.o_editable.o_dirty').length && !flag) {
- flag = true;
- setTimeout(function () {flag=false;},0);
- return _t('This document is not saved!');
- }
- };
- },
- rte_changed: function () {
- this.$buttons.save.prop('disabled', false);
- },
- _save: function () {
- var self = this;
-
- var saved = {}; // list of allready saved views and data
-
- var defs = $('.o_editable')
- .filter('.o_dirty')
- .removeAttr('contentEditable')
- .removeClass('o_dirty o_editable oe_carlos_danger o_is_inline_editable')
- .map(function () {
- var $el = $(this);
-
- // remove multi edition
- var key = $el.data('oe-model')+":"+$el.data('oe-id')+":"+$el.data('oe-field')+":"+$el.data('oe-type')+":"+$el.data('oe-expression');
- if (saved[key]) return true;
- saved[key] = true;
-
- // 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)
- .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('o_dirty oe_carlos_danger');
- $el.addClass(id);
- return $.Deferred().reject({
- id: id,
- error: response.data,
- });
- });
- });
- }).get();
- return $.when.apply(null, defs).then(function () {
- window.onbeforeunload = null;
- website.reload();
- }, function (failed) {
- // If there were errors, re-enable edition
- self.rte.start_edition(true);
- // jquery's deferred being a pain in the ass
- if (!_.isArray(failed)) { failed = [failed]; }
-
- _(failed).each(function (failure) {
- var html = failure.error.exception_type === "except_osv";
- if (html) {
- var msg = $("<div/>").text(failure.error.message).html();
- var data = msg.substring(3,msg.length-2).split(/', u'/);
- failure.error.message = '<b>' + data[0] + '</b>' + dom.blank + 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');
- });
- });
- },
- save: function () {
- return this._save().then(function () {
- website.reload();
- });
- },
- /**
- * Saves an RTE content, which always corresponds to a view section (?).
- */
- save_without_reload: function () {
- return this._save();
- },
- saveElement: function ($el) {
- var markup = $el.prop('outerHTML');
- return ajax.jsonRpc('/web/dataset/call', 'call', {
- model: 'ir.ui.view',
- method: 'save',
- args: [$el.data('oe-id'), markup,
- $el.data('oe-xpath') || null,
- website.get_context()],
- });
- },
- cancel: function () {
- new $.Deferred(function (d) {
- var $dialog = $(core.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 () {
- window.onbeforeunload = null;
- website.reload();
- });
- },
-});
+/* ----- Customize Template ---- */
-var EditorBarCustomize = Widget.extend({
+website.TopBarCustomize = Widget.extend({
events: {
'mousedown a.dropdown-toggle': 'load_menu',
'click ul a[data-view-id]': 'do_customize',
@@ -1183,349 +93,29 @@ var EditorBarCustomize = Widget.extend({
args: [],
kwargs: {
ids: [parseInt(view_id, 10)],
- context: website.get_context()
+ context: base.get_context()
}
}).then( function() {
window.location.reload();
});
},
});
-
-$(document).ready(function() {
- var editorBarCustomize = new EditorBarCustomize();
- editorBarCustomize.setElement($('li[id=customize-menu]'));
- editorBarCustomize.start();
-});
-
-/* ----- RICH TEXT EDITOR ---- */
-
-var RTE = Widget.extend({
- init: function (EditorBar) {
- this.EditorBar = EditorBar;
- $('.inline-media-link').remove();
- this._super.apply(this, arguments);
-
- computeFonts();
- },
- /**
- * Add a record undo to history
- * @param {DOM} target where the dom is changed is editable zone
- */
- historyRecordUndo: function ($target, internal_history) {
- var rng = range.create();
- var $editable = $($target || (rng && rng.sc)).closest(".o_editable");
- if ($editable.length) {
- rng = $editable.data('range') || rng;
- }
- if (!rng && $target.length) {
- rng = range.create($target.closest("*")[0],0);
- }
- if (rng) {
- try {
- rng.select();
- } catch (e) {
- console.error(e);
- }
- }
- $target = $(rng.sc);
- $target.mousedown();
- this.history.recordUndo($target, null, internal_history);
- $target.mousedown();
- },
- /**
- * 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;
-
- change_default_bootstrap_animation_to_edit();
-
- this.history = history;
-
- // handler for cancel editor
- $(document).on('keydown', function (event) {
- if (event.keyCode === 27 && !$('.modal-content:visible').length) {
- setTimeout(function () {
- $('#website-top-navbar [data-action="cancel"]').click();
- var $modal = $('.modal-content > .modal-body').parents(".modal:first");
- $modal.off('keyup.dismiss.bs.modal');
- setTimeout(function () {
- $modal.on('keyup.dismiss.bs.modal', function () {
- $(this).modal('hide');
- });
- },500);
- },0);
- }
- });
-
- // activate editor
- var $last;
- $(document).on('mousedown', function (event) {
- var $target = $(event.target);
- var $editable = $target.closest('.o_editable');
-
- if (!$editable.size()) {
- return;
- }
-
- if ($last && (!$editable.size() || $last[0] != $editable[0])) {
- var $destroy = $last;
- setTimeout(function () {$destroy.destroy();},150); // setTimeout to remove flickering when change to editable zone (re-create an editor)
- $last = null;
- }
- if ($editable.size() && (!$last || $last[0] != $editable[0]) &&
- ($target.closest('[contenteditable]').attr('contenteditable') || "").toLowerCase() !== 'false') {
- $editable.summernote(self._config());
- $editable.data('NoteHistory', self.history);
- $editable.data('rte', self);
- $last = $editable;
-
- // firefox & IE fix
- try {
- document.execCommand('enableObjectResizing', false, false);
- document.execCommand('enableInlineTableEditing', false, false);
- document.execCommand( '2D-position', false, false);
- } catch (e) {}
- document.body.addEventListener('resizestart', function (evt) {evt.preventDefault(); return false;});
- document.body.addEventListener('movestart', function (evt) {evt.preventDefault(); return false;});
- document.body.addEventListener('dragstart', function (evt) {evt.preventDefault(); return false;});
-
- if (!range.create()) {
- range.create($editable[0],0).select();
- }
-
- $target.trigger('mousedown'); // for activate selection on picture
- setTimeout(function () {
- self.historyRecordUndo($editable, true);
- },0);
- }
- });
-
- $('.o_not_editable').attr("contentEditable", false);
-
- $('#wrapwrap [data-oe-model]')
- .not('.o_not_editable')
- .filter(function () {
- return !$(this).closest('.o_not_editable').length;
- })
- .not('link, script')
- .not('[data-oe-readonly]')
- .not('img[data-oe-field="arch"], br[data-oe-field="arch"], input[data-oe-field="arch"]')
- .not('.oe_snippet_editor')
- .addClass('o_editable');
-
- $('.o_editable').each(function () {
- var node = this;
- var $node = $(node);
-
- // add class to display inline-block for empty t-field
- if(window.getComputedStyle(node).display === "inline" && $node.data('oe-type') !== "image") {
- $node.addClass('o_is_inline_editable');
- }
-
- // start element observation
- $(node).one('content_changed', function () {
- $node.addClass('o_dirty');
- });
- $(node).on('content_changed', function () {
- self.trigger('change');
- });
- });
-
- $(document).trigger('mousedown');
-
- if (!restart) {
- $('#wrapwrap, .o_editable').on('click', '*', function (event) {
- event.preventDefault();
- });
-
- $('body').addClass("editor_enable");
-
- $(document)
- .tooltip({
- selector: '[data-oe-readonly]',
- container: 'body',
- trigger: 'hover',
- delay: { "show": 1000, "hide": 100 },
- placement: 'bottom',
- title: _t("Readonly field")
- })
- .on('click', function () {
- $(this).tooltip('hide');
- });
-
- self.trigger('rte:ready');
- }
- },
-
- _config: function () {
- return {
- airMode : true,
- focus: false,
- airPopover: [
- ['style', ['style']],
- ['font', ['bold', 'italic', 'underline', 'clear']],
- ['fontsize', ['fontsize']],
- ['color', ['color']],
- ['para', ['ul', 'ol', 'paragraph']],
- ['table', ['table']],
- ['insert', ['link', 'picture']],
- ['history', ['undo', 'redo']],
- ],
- oninit: function() {
- },
- styleWithSpan: false,
- inlinemedia : ['p'],
- lang: "odoo"
- };
+website.TopBar.include({
+ start: function () {
+ this.customize_menu = new website.TopBarCustomize();
+ var def = this.customize_menu.attachTo($('#customize-menu'));
+ return $.when(this._super(), def);
}
});
/* ----- EDITOR: LINK & MEDIA ---- */
-var Dialog = Widget.extend({
- events: {
- 'hidden.bs.modal': 'destroy',
- 'click button.save': 'save',
- 'click button[data-dismiss="modal"]': 'cancel',
- },
- init: function () {
- this._super();
- },
- start: function () {
- var sup = this._super();
- this.$el.modal({backdrop: 'static'});
- this.$('input:first').focus();
- return sup;
- },
- save: function () {
- this.close();
- this.trigger("saved");
- },
- cancel: function () {
- this.trigger("cancel");
- },
- close: function () {
- this.$el.modal('hide');
- },
- destroy: function () {
- this.$el.modal('hide').remove();
- if($(".modal.in").length>0){
- $('body').addClass('modal-open');
- }
- },
-});
-
-var LinkDialog = Dialog.extend({
- template: 'website.editor.dialog.link',
- events: _.extend({}, Dialog.prototype.events, {
- 'change :input.url-source': 'changed',
- 'keyup :input.url': 'onkeyup',
- 'keyup :input': 'preview',
- 'click button.remove': 'remove_link',
- 'change input#link-text': function (e) {
- this.text = $(e.target).val();
- },
- 'change .link-style': function (e) {
- this.preview();
- },
- }),
- init: function (editable, linkInfo) {
- this._super(editable, linkInfo);
- this.editable = editable;
- this.data = linkInfo || {};
-
- this.data.className = "";
- if (this.data.range) {
- this.data.iniClassName = $(this.data.range.sc).filter("a").attr("class") || "";
- this.data.className = this.data.iniClassName.replace(/(^|\s+)btn(-[a-z0-9_-]*)?/gi, ' ');
-
- var is_link = this.data.range.isOnAnchor();
- var r = this.data.range;
-
- var sc = r.sc;
- var so = r.so;
- var ec = r.ec;
- var eo = r.eo;
-
- var nodes;
- if (!is_link) {
- if (sc.tagName) {
- sc = dom.firstChild(so ? sc.childNodes[so] : sc);
- so = 0;
- } else if (so !== sc.textContent.length) {
- if (sc === ec) {
- ec = sc = sc.splitText(so);
- eo -= so;
- } else {
- sc = sc.splitText(so);
- }
- so = 0;
- }
- if (ec.tagName) {
- ec = dom.lastChild(eo ? ec.childNodes[eo-1] : ec);
- eo = ec.textContent.length;
- } else if (eo !== ec.textContent.length) {
- ec.splitText(eo);
- }
-
- nodes = dom.listBetween(sc, ec);
-
- // browsers can't target a picture or void node
- if (dom.isVoid(sc) || dom.isImg(sc)) {
- so = dom.listPrev(sc).length-1;
- sc = sc.parentNode;
- }
- if (dom.isBR(ec)) {
- eo = dom.listPrev(ec).length-1;
- ec = ec.parentNode;
- } else if (dom.isVoid(ec) || dom.isImg(sc)) {
- eo = dom.listPrev(ec).length;
- ec = ec.parentNode;
- }
-
- this.data.range = range.create(sc, so, ec, eo);
- this.data.range.select();
- } else {
- nodes = dom.ancestor(sc, dom.isAnchor).childNodes;
- }
-
- if (dom.isImg(sc) && nodes.indexOf(sc) === -1) {
- nodes.push(sc);
- }
- if (nodes.length > 1 || dom.ancestor(nodes[0], dom.isImg)) {
- var text = "";
- this.data.images = [];
- for (var i=0; i<nodes.length; i++) {
- if (dom.ancestor(nodes[i], dom.isImg)) {
- this.data.images.push(dom.ancestor(nodes[i], dom.isImg));
- text += '[IMG]';
- } else if (!is_link && i===0) {
- text += nodes[i].textContent.slice(so, Infinity);
- } else if (!is_link && i===nodes.length-1) {
- text += nodes[i].textContent.slice(0, eo);
- } else {
- text += nodes[i].textContent;
- }
- }
- this.data.text = text;
- }
- }
-
- this.data.text = this.data.text.replace(/[ \t\r\n]+/g, ' ');
-
- // Store last-performed request to be able to cancel/abort it.
- this.page_exists_req = null;
- this.search_pages_req = null;
- this.bind_data();
- },
- start: function () {
+widget.LinkDialog.include({
+ bind_data: function () {
var self = this;
+ var href = this.data.url;
var last;
+
this.$('#link-page').select2({
minimumInputLength: 1,
placeholder: _t("New or existing page"),
@@ -1555,37 +145,24 @@ var LinkDialog = Dialog.extend({
});
},
});
- return this._super().then(this.proxy('bind_data'));
- },
- get_data: function (test) {
- var def = new $.Deferred(),
- $e = this.$('.active input.url-source').filter(':input'),
- val = $e.val(),
- label = this.$('#link-text').val() || val;
-
- if (label && this.data.images) {
- for(var i=0; i<this.data.images.length; i++) {
- label = label.replace(/</, "&lt;").replace(/>/, "&gt;").replace(/\[IMG\]/, this.data.images[i].outerHTML);
- }
- }
- if (!test && (!val || !$e[0].checkValidity())) {
- // FIXME: error message
- $e.closest('.form-group').addClass('has-error');
- $e.focus();
- def.reject();
+ if (href) {
+ this.page_exists(href).then(function (exist) {
+ if (exist) {
+ self.$('#link-page').select2('data', {'id': href, 'text': href}).change();
+ } else {
+ self.$('input.url').val(href).change();
+ self.$('input.window-new').closest("div").show();
+ }
+ });
}
-
- var style = this.$("input[name='link-style-type']:checked").val() || '';
- var size = this.$("input[name='link-style-size']:checked").val() || '';
- var classes = (this.data.className || "") + (style && style.length ? " btn " : "") + style + " " + size;
- var isNewWindow = this.$('input.window-new').prop('checked');
-
- if ($e.hasClass('email-address') && $e.val().indexOf("@") !== -1) {
- def.resolve(val.indexOf("mailto:") === 0 ? val : 'mailto:' + val, isNewWindow, label, classes);
- } else if ($e.val() && $e.val().length && $e.hasClass('page')) {
+ return this._super();
+ },
+ get_data_buy_url: function (def, $e, isNewWindow, label, classes) {
+ var val = $e.val();
+ if (val && val.length && $e.hasClass('page')) {
var data = $e.select2('data');
- if (test || !data.create) {
+ if (!data.create) {
def.resolve(data.id, isNewWindow, label || data.text, classes);
} else {
// Create the page, get the URL back
@@ -1598,76 +175,12 @@ var LinkDialog = Dialog.extend({
} else {
def.resolve(val, isNewWindow, label, classes);
}
- return def;
- },
- save: function () {
- var self = this;
- var _super = this._super.bind(this);
- return this.get_data()
- .then(function (url, new_window, label, classes) {
- self.data.url = url;
- self.data.newWindow = new_window;
- self.data.text = label;
- self.data.className = classes.replace(/\s+/gi, ' ').replace(/^\s+|\s+$/gi, '');
-
- self.trigger("save", self.data);
- }).then(_super);
- },
- bind_data: function () {
- var self = this;
- var href = this.data.url;
- var new_window = this.data.isNewWindow;
- var text = this.data.text;
- var classes = this.data.iniClassName;
-
- this.$('input#link-text').val(text);
- this.$('input.window-new').prop('checked', new_window);
-
- if (classes) {
- this.$('input[value!=""]').each(function () {
- var $option = $(this);
- if (classes.indexOf($option.val()) !== -1) {
- $option.attr("checked", "checked");
- }
- });
- }
-
- var match, $control;
- if (href && (match = /mailto:(.+)/.exec(href))) {
- this.$('input.email-address').val(match[1]).change();
- }
- if (href && !$control) {
- this.page_exists(href).then(function (exist) {
- if (exist) {
- self.$('#link-page').select2('data', {'id': href, 'text': href});
- } else {
- self.$('input.url').val(href).change();
- self.$('input.window-new').closest("div").show();
- }
- });
- }
-
- this.page_exists(href).then(function (exist) {
- if (exist) {
- self.$('#link-page').select2('data', {'id': href, 'text': href});
- } else {
- self.$('input.url').val(href).change();
- self.$('input.window-new').closest("div").show();
- }
- });
-
- this.preview();
},
changed: function (e) {
- var $e = $(e.target);
- this.$('.url-source').filter(':input').not($e).val('')
+ this.$('.url-source').filter(':input').not($(e.target)).val('')
.filter(function () { return !!$(this).data('select2'); })
.select2('data', null);
- $e.closest('.list-group-item')
- .addClass('active')
- .siblings().removeClass('active')
- .addBack().removeClass('has-error');
- this.preview();
+ this._super(e);
},
call: function (method, args, kwargs) {
var self = this;
@@ -1684,859 +197,15 @@ var LinkDialog = Dialog.extend({
},
page_exists: function (term) {
return this.call('page_exists', [null, term], {
- context: website.get_context(),
+ context: base.get_context(),
});
},
fetch_pages: function (term) {
return this.call('search_pages', [null, term], {
limit: 9,
- context: website.get_context(),
+ context: base.get_context(),
});
},
- onkeyup: function (e) {
- var $e = $(e.target);
- var is_link = ($e.val()||'').length && $e.val().indexOf("@") === -1;
- this.$('input.window-new').closest("div").toggle(is_link);
- this.preview();
- },
- preview: function () {
- var $preview = this.$("#link-preview");
- this.get_data(true).then(function (url, new_window, label, classes) {
- $preview.attr("target", new_window ? '_blank' : "")
- .attr("href", url && url.length ? url : "#")
- .html((label && label.length ? label : url))
- .attr("class", classes.replace(/pull-\w+/, ''));
- });
- }
});
-/**
- * alt widget. Lets users change a alt & title on a media
- */
-var alt = Dialog.extend({
- template: 'website.editor.dialog.alt',
- init: function ($editable, media) {
- this.$editable = $editable;
- this.media = media;
- this.alt = ($(this.media).attr('alt') || "").replace(/&quot;/g, '"');
- this.title = ($(this.media).attr('title') || "").replace(/&quot;/g, '"');
- return this._super();
- },
- save: function () {
- var self = this;
- range.createFromNode(self.media).select();
- this.$editable.data('NoteHistory').recordUndo();
- var alt = this.$('#alt').val();
- var title = this.$('#title').val();
- $(this.media).attr('alt', alt ? alt.replace(/"/g, "&quot;") : null).attr('title', title ? title.replace(/"/g, "&quot;") : null);
- setTimeout(function () {
- click_event(self.media, "mouseup");
- },0);
- return this._super();
- },
-});
-
-var click_event = function(el, type) {
- var evt = document.createEvent("MouseEvents");
- evt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, el);
- el.dispatchEvent(evt);
-};
-
-/**
- * MediaDialog widget. Lets users change a media, including uploading a
- * new image, font awsome or video and can change a media into an other
- * media
- *
- * options: select_images: allow the selection of more of one image
- */
-var MediaDialog = Dialog.extend({
- template: 'website.editor.dialog.media',
- events : _.extend({}, Dialog.prototype.events, {
- 'input input#icon-search': 'search',
- }),
- init: function ($editable, media, options) {
- this._super();
- if ($editable) {
- this.$editable = $editable;
- this.rte = this.$editable.rte || this.$editable.data('rte');
- }
- this.options = options || {};
- this.old_media = media;
- this.media = media;
- this.isNewMedia = !media;
- this.range = range.create();
- },
- start: function () {
- var self = this;
-
- this.only_images = this.options.only_images || this.options.select_images || (this.media && $(this.media).parent().data("oe-field") === "image");
- if (this.only_images) {
- this.$('[href="#editor-media-video"], [href="#editor-media-icon"]').addClass('hidden');
- }
-
- if (this.media) {
- if (this.media.nodeName === "IMG") {
- this.$('[href="#editor-media-image"]').tab('show');
- } else if (this.media.className.match(/(^|\s)media_iframe_video($|\s)/)) {
- this.$('[href="#editor-media-video"]').tab('show');
- } else if (this.media.parentNode.className.match(/(^|\s)media_iframe_video($|\s)/)) {
- this.media = this.media.parentNode;
- this.$('[href="#editor-media-video"]').tab('show');
- } else if (this.media.className.match(/(^|\s)fa($|\s)/)) {
- this.$('[href="#editor-media-icon"]').tab('show');
- }
- }
-
- this.imageDialog = new ImageDialog(this, this.media, this.options);
- this.imageDialog.appendTo(this.$("#editor-media-image"));
- this.iconDialog = new FontIconsDialog(this, this.media, this.options);
- this.iconDialog.appendTo(this.$("#editor-media-icon"));
- this.videoDialog = new VideoDialog(this, this.media, this.options);
- this.videoDialog.appendTo(this.$("#editor-media-video"));
-
- this.active = this.imageDialog;
-
- $('a[data-toggle="tab"]').on('shown.bs.tab', function (event) {
- if ($(event.target).is('[href="#editor-media-image"]')) {
- self.active = self.imageDialog;
- self.$('li.search, li.previous, li.next').removeClass("hidden");
- } else if ($(event.target).is('[href="#editor-media-icon"]')) {
- self.active = self.iconDialog;
- self.$('li.search, li.previous, li.next').removeClass("hidden");
- self.$('.nav-tabs li.previous, .nav-tabs li.next').addClass("hidden");
- } else if ($(event.target).is('[href="#editor-media-video"]')) {
- self.active = self.videoDialog;
- self.$('.nav-tabs li.search').addClass("hidden");
- }
- });
-
- return this._super();
- },
- save: function () {
- if (this.options.select_images) {
- this.trigger("saved", this.active.save());
- this.close();
- return;
- }
- if(this.rte) {
- this.range.select();
- this.rte.historyRecordUndo(this.media);
- }
-
- var self = this;
- if (self.media) {
- this.media.innerHTML = "";
- if (this.active !== this.imageDialog) {
- this.imageDialog.clear();
- }
- if (this.active !== this.iconDialog) {
- this.iconDialog.clear();
- }
- if (this.active !== this.videoDialog) {
- this.videoDialog.clear();
- }
- } else {
- this.media = document.createElement("img");
- this.range.insertNode(this.media, true);
- this.active.media = this.media;
- }
- this.active.save();
-
- if (this.active.add_class) {
- $(this.media).addClass(this.active.add_class);
- }
-
- $(document.body).trigger("media-saved", [self.active.media, self.old_media]);
- self.trigger("saved", [self.active.media, self.old_media]);
- setTimeout(function () {
- if (!self.active.media.parentNode) {
- return;
- }
- range.createFromNode(self.active.media).select();
- click_event(self.active.media, "mousedown");
- if (!this.only_images) {
- setTimeout(function () {
- if($(self.active.media).parent().data("oe-field") !== "image") {
- click_event(self.active.media, "click");
- }
- click_event(self.active.media, "mouseup");
- },0);
- }
- },0);
-
- this.close();
- },
- searchTimer: null,
- search: function () {
- var self = this;
- var needle = this.$("input#icon-search").val();
- clearTimeout(this.searchTimer);
- this.searchTimer = setTimeout(function () {
- self.active.search(needle || "");
- },250);
- }
-});
-
-/**
- * ImageDialog widget. Lets users change an image, including uploading a
- * new image in OpenERP or selecting the image style (if supported by
- * the caller).
- */
-var IMAGES_PER_ROW = 6;
-var IMAGES_ROWS = 2;
-var ImageDialog = Widget.extend({
- template: 'website.editor.dialog.image',
- events: _.extend({}, Dialog.prototype.events, {
- 'change .url-source': function (e) {
- this.changed($(e.target));
- },
- 'click button.filepicker': function () {
- var filepicker = this.$('input[type=file]');
- if (!_.isEmpty(filepicker)){
- filepicker[0].click();
- }
- },
- 'click .js_disable_optimization': function () {
- this.$('input[name="disable_optimization"]').val('1');
- var filepicker = this.$('button.filepicker');
- if (!_.isEmpty(filepicker)){
- filepicker[0].click();
- }
- },
- 'change input[type=file]': 'file_selection',
- 'submit form': 'form_submit',
- 'change input.url': "change_input",
- 'keyup input.url': "change_input",
- //'change select.image-style': 'preview_image',
- 'click .existing-attachments img': 'select_existing',
- 'click .existing-attachment-remove': 'try_remove',
- }),
- init: function (parent, media, options) {
- this._super();
- this.options = options || {};
- this.parent = parent;
- this.media = media;
- this.images = [];
- this.page = 0;
- },
- start: function () {
- this.$preview = this.$('.preview-container').detach();
- var self = this;
- var res = this._super();
- var o = { url: null, alt: null };
- // avoid typos, prevent addition of new properties to the object
- Object.preventExtensions(o);
-
- if ($(this.media).is("img")) {
- o.url = this.media.getAttribute('src');
- } else {
- this.add_class = "img-responsive pull-left";
- }
- this.parent.$(".pager > li").click(function (e) {
- e.preventDefault();
- var $target = $(e.currentTarget);
- if ($target.hasClass('disabled')) {
- return;
- }
- self.page += $target.hasClass('previous') ? -1 : 1;
- self.display_attachments();
- });
- this.set_image(o.url, o.alt);
- this.fetch_existing();
- return res;
- },
- push: function (url, alt, id) {
- if (this.options.select_images) {
- var img = _.select(this.images, function (v) { return v.url == url;});
- if (img.length) {
- this.images.splice(this.images.indexOf(img[0]),1);
- return;
- }
- } else {
- this.images = [];
- }
- this.images.push({'url': url, 'alt': alt, 'id': id});
- },
- save: function () {
- if (this.options.select_images) {
- this.parent.trigger("save", this.images);
- return this.images;
- }
- this.parent.trigger("save", this.media);
-
- var img = this.images[0] || {
- 'url': this.$(".existing-attachments img:first").attr('src'),
- 'alt': this.$(".existing-attachments img:first").attr('alt')
- };
-
- if (this.media.tagName !== "IMG") {
- var media = document.createElement('img');
- $(this.media).replaceWith(media);
- this.media = media;
- }
-
- $(this.media).attr('src', img.url).attr('alt', img.alt);
-
- var style = this.style;
- this.media.setAttribute('src', img.url);
- if (style) { this.media.addClass(style); }
-
- return this.media;
- },
- clear: function () {
- this.media.className = this.media.className.replace(/(^|\s)(img(\s|$)|img-[^\s]*)/g, ' ');
- },
- cancel: function () {
- this.trigger('cancel');
- },
- change_input: function (e) {
- var $input = $(e.target);
- var $button = $input.parent().find("button");
- if ($input.val() === "") {
- $button.addClass("btn-default").removeClass("btn-primary");
- } else {
- $button.removeClass("btn-default").addClass("btn-primary");
- }
- },
- search: function (needle) {
- var self = this;
- this.fetch_existing(needle).then(function () {
- self.selected_existing();
- });
- },
- set_image: function (url, alt) {
- var self = this;
- if (url) {
- this.push(url, alt);
- }
- this.$('input.url').val('');
- this.fetch_existing().then(function () {
- self.selected_existing();
- });
- },
- form_submit: function (event) {
- var self = this;
- var $form = this.$('form[action="/website/attach"]');
- if (!$form.find('input[name="upload"]').val().length) {
- $form.find('input[name="url"]').val();
- if (this.selected_existing().size()) {
- event.preventDefault();
- return false;
- }
- }
- $form.find('.well > div').hide().last().after('<span class="fa fa-spin fa-3x fa-refresh"/>');
-
- var callback = _.uniqueId('func_');
- this.$('input[name=func]').val(callback);
- window[callback] = function (attachments, error) {
- delete window[callback];
- $form.find('.well > span').remove();
- $form.find('.well > div').show();
- if (error || !attachments.length) {
- self.file_selected(null, error || !attachments.length);
- }
- for (var i=0; i<attachments.length; i++) {
- self.file_selected(attachments[i]['website_url'], error);
- }
- };
- },
- file_selection: function () {
- this.$el.addClass('nosave');
- this.$('form').removeClass('has-error').find('.help-block').empty();
- this.$('button.filepicker').removeClass('btn-danger btn-success');
- this.$('form').submit();
- },
- file_selected: function(url, error) {
- var $button = this.$('button.filepicker');
- if (!error) {
- $button.addClass('btn-success');
- } else {
- url = null;
- this.$('form').addClass('has-error')
- .find('.help-block').text(error);
- $button.addClass('btn-danger');
- }
- this.set_image(url, null, error);
-
- if (!this.options.select_images) {
- // auto save and close popup
- this.parent.save();
- }
- },
- fetch_existing: function (needle) {
- var domain = [['res_model', '=', 'ir.ui.view'], '|',
- ['mimetype', '=', false], ['mimetype', '=like', 'image/%']];
- if (needle && needle.length) {
- domain.push('|', ['datas_fname', 'ilike', needle], ['name', 'ilike', needle]);
- }
- return ajax.jsonRpc('/web/dataset/call_kw', 'call', {
- model: 'ir.attachment',
- method: 'search_read',
- args: [],
- kwargs: {
- domain: domain,
- fields: ['name', 'website_url'],
- order: 'id desc',
- context: website.get_context()
- }
- }).then(this.proxy('fetched_existing'));
- },
- fetched_existing: function (records) {
- this.records = records;
- this.display_attachments();
- },
- display_attachments: function () {
- this.$('.help-block').empty();
- 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()
- .slice(from, from + per_screen)
- .groupBy(function (_, index) { return Math.floor(index / IMAGES_PER_ROW); })
- .values()
- .value();
- this.$('.existing-attachments').replaceWith(
- core.qweb.render(
- 'website.editor.dialog.image.existing.content', {rows: rows}));
- this.parent.$('.pager')
- .find('li.previous').toggleClass('disabled', (from === 0)).end()
- .find('li.next').toggleClass('disabled', (from + per_screen >= records.length));
-
- this.selected_existing();
- },
- select_existing: function (e) {
- var $img = $(e.currentTarget);
- this.push($img.attr('src'), $img.attr('alt'), $img.data('id'));
- this.selected_existing();
- },
- selected_existing: function () {
- var self = this;
- this.$('.existing-attachment-cell.media_selected').removeClass("media_selected");
- var $select = this.$('.existing-attachment-cell img').filter(function () {
- var $img = $(this);
- var url = $img.attr("src");
- return !!_.select(self.images, function (v) {
- if (v.url === url) {
- if (!v.id) {
- v.id = $img.data('id');
- v.alt = $img.attr('alt');
- }
- return true;
- }
- }).length;
- });
- $select.parent().addClass("media_selected");
- return $select;
- },
- try_remove: function (e) {
- var $help_block = this.$('.help-block').empty();
- var self = this;
- var $a = $(e.target);
- var id = parseInt($a.data('id'), 10);
- var attachment = _.findWhere(this.records, {id: id});
- var $both = $a.parent().children();
-
- $both.css({borderWidth: "5px", borderColor: "#f00"});
-
- return ajax.jsonRpc('/web/dataset/call_kw', 'call', {
- model: 'ir.attachment',
- method: 'try_remove',
- args: [],
- kwargs: {
- ids: [id],
- context: website.get_context()
- }
- }).then(function (prevented) {
- if (_.isEmpty(prevented)) {
- self.records = _.without(self.records, attachment);
- self.display_attachments();
- return;
- }
- $both.css({borderWidth: "", borderColor: ""});
- $help_block.replaceWith(core.qweb.render(
- 'website.editor.dialog.image.existing.error', {
- views: prevented[id]
- }
- ));
- });
- },
-});
-
-
-var cacheCssSelectors = {};
-function getCssSelectors(filter) {
- var css = [];
- if (cacheCssSelectors[filter]) {
- return cacheCssSelectors[filter];
- }
- var sheets = document.styleSheets;
- for(var i = 0; i < sheets.length; i++) {
- try {
- var rules = sheets[i].rules || sheets[i].cssRules;
- } catch(e) {
- continue;
- }
- if (rules) {
- for(var r = 0; r < rules.length; r++) {
- var selectorText = rules[r].selectorText;
- if (selectorText) {
- var match = selectorText.match(filter);
- if (match) {
- css.push([match[1], rules[r].cssText.replace(/(^.*\{\s*)|(\s*\}\s*$)/g, '')]);
- }
- }
- }
- }
- }
- return cacheCssSelectors[filter] = css;
-}
-
-function computeFonts() {
- _.each(fontIcons, function (data) {
- data.icons = _.map(getCssSelectors(data.parser), function (css) {
- return css[0].slice(1, css[0].length).replace(/::?before$/, '');
- });
- });
-}
-
-/* list of font icons to load by editor. The icons are displayed in the media editor and
- * identified like font and image (can be colored, spinned, resized with fa classes).
- * To add font, push a new object {base, parser}
- * - base: class who appear on all fonts (eg: fa fa-refresh)
- * - parser: regular expression used to select all font in css style sheets
- */
-var fontIcons = [{'base': 'fa', 'parser': /(?=^|\s)(\.fa-[0-9a-z_-]+::?before)/i}];
-
-
-/**
- * FontIconsDialog widget. Lets users change a font awsome, suport all
- * font awsome loaded in the css files.
- */
-var FontIconsDialog = Widget.extend({
- template: 'website.editor.dialog.font-icons',
- events : _.extend({}, Dialog.prototype.events, {
- 'click .font-icons-icon': function (e) {
- e.preventDefault();
- e.stopPropagation();
-
- this.$('#fa-icon').val(e.target.getAttribute('data-id'));
- $(".font-icons-icon").removeClass("font-icons-selected");
- $(event.target).addClass("font-icons-selected");
- },
- }),
-
- // extract list of font (like awsome) from the cheatsheet.
- renderElement: function() {
- this.iconsParser = fontIcons;
- this.icons = _.flatten(_.map(fontIcons, function (data) {
- return data.icons;
- }));
- this._super();
- },
-
- init: function (parent, media) {
- this._super();
- this.parent = parent;
- this.media = media;
- },
- start: function () {
- return this._super().then(this.proxy('load_data'));
- },
- search: function (needle) {
- var iconsParser = this.iconsParser;
- if (needle) {
- var parser = [];
- var fontIcon;
-
- for (var k=0; k<fontIcons.length; k++) {
- fontIcon = fontIcons[k];
- var icons = _(fontIcon.icons).filter(function (icon) {
- return icon.indexOf(needle) !== -1;
- });
- if (icons.length) {
- parser.push({
- base: fontIcon.base,
- icons: icons
- });
- }
- }
- iconsParser = parser;
- }
- this.$('div.font-icons-icons').html(
- core.qweb.render('website.editor.dialog.font-icons.icons', {'iconsParser': iconsParser}));
- },
- /**
- * Removes existing FontAwesome classes on the bound element, and sets
- * all the new ones if necessary.
- */
- save: function () {
- var self = this;
- this.parent.trigger("save", this.media);
- var icons = this.icons;
- 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);
- });
- var final_classes = non_fa_classes.concat(this.get_fa_classes());
- if (this.media.tagName !== "SPAN") {
- var media = document.createElement('span');
- $(this.media).replaceWith(media);
- this.media = media;
- style = style.replace(/\s*width:[^;]+/, '');
- }
- $(this.media).attr("class", _.compact(final_classes).join(' ')).attr("style", style);
- },
- /**
- * return the data font object (with base, parser and icons) or null
- */
- getFont: function (classNames) {
- if (!(classNames instanceof Array)) {
- classNames = (classNames||"").split(/\s+/);
- }
- var fontIcon, className;
- for (var i=0; i<classNames.length; i++) {
- className = classNames[i];
- for (var k=0; k<fontIcons.length; k++) {
- fontIcon = fontIcons[k];
- if (className === fontIcon.base || fontIcon.icons.indexOf(className) !== -1) {
- return {
- 'base': fontIcon.base,
- 'parser': fontIcon.parser,
- 'icons': fontIcon.icons,
- 'font': className
- };
- }
- }
- }
- return null;
- },
-
- /**
- * Looks up the various FontAwesome classes on the bound element and
- * sets the corresponding template/form elements to the right state.
- * If multiple classes of the same category are present on an element
- * (e.g. fa-lg and fa-3x) the last one occurring will be selected,
- * which may not match the visual look of the element.
- */
- load_data: function () {
- var classes = (this.media&&this.media.className||"").split(/\s+/);
- for (var i = 0; i < classes.length; i++) {
- var cls = classes[i];
- switch(cls) {
- case 'fa-1x':case 'fa-2x':case 'fa-3x':case 'fa-4x':case 'fa-5x':
- // size classes
- this.$('#fa-size').val(cls);
- continue;
- case 'fa-spin':
- case 'fa-rotate-90':case 'fa-rotate-180':case 'fa-rotate-270':
- case 'fa-flip-horizontal':case 'fa-rotate-vertical':
- this.$('#fa-rotation').val(cls);
- continue;
- case 'fa-fw':
- continue;
- case 'fa-border':
- this.$('#fa-border').prop('checked', true);
- continue;
- case '': continue;
- default:
- $(".font-icons-icon").removeClass("font-icons-selected").filter("."+cls).addClass("font-icons-selected");
- for (var k=0; k<this.icons.length; k++) {
- if (this.icons.indexOf(cls) !== -1) {
- this.$('#fa-icon').val(cls);
- break;
- }
- }
- }
- }
- },
- /**
- * Serializes the dialog to an array of FontAwesome classes. Includes
- * the base ``fa``.
- */
- get_fa_classes: function () {
- var font = this.getFont(this.$('#fa-icon').val());
- return [
- font ? font.base : 'fa',
- font ? font.font : "",
- this.$('#fa-size').val(),
- this.$('#fa-rotation').val(),
- this.$('#fa-border').prop('checked') ? 'fa-border' : ''
- ];
- },
- clear: function () {
- this.media.className = this.media.className.replace(/(^|\s)(fa(\s|$)|fa-[^\s]*)/g, ' ');
- },
-});
-
-
-function createVideoNode(url) {
- // video url patterns(youtube, instagram, vimeo, dailymotion, youku)
- var ytRegExp = /^(?:(?:https?:)?\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/;
- var ytMatch = url.match(ytRegExp);
-
- var igRegExp = /\/\/instagram.com\/p\/(.[a-zA-Z0-9]*)/;
- var igMatch = url.match(igRegExp);
-
- var vRegExp = /\/\/vine.co\/v\/(.[a-zA-Z0-9]*)/;
- var vMatch = url.match(vRegExp);
-
- var vimRegExp = /\/\/(player.)?vimeo.com\/([a-z]*\/)*([0-9]{6,11})[?]?.*/;
- var vimMatch = url.match(vimRegExp);
-
- var dmRegExp = /.+dailymotion.com\/(video|hub)\/([^_]+)[^#]*(#video=([^_&]+))?/;
- var dmMatch = url.match(dmRegExp);
-
- var youkuRegExp = /\/\/v\.youku\.com\/v_show\/id_(\w+)\.html/;
- var youkuMatch = url.match(youkuRegExp);
-
- var $video = $('<iframe>');
- if (ytMatch && ytMatch[1].length === 11) {
- var youtubeId = ytMatch[1];
- $video = $('<iframe>')
- .attr('src', '//www.youtube.com/embed/' + youtubeId)
- .attr('width', '640').attr('height', '360');
- } else if (igMatch && igMatch[0].length) {
- $video = $('<iframe>')
- .attr('src', igMatch[0] + '/embed/')
- .attr('width', '612').attr('height', '710')
- .attr('scrolling', 'no')
- .attr('allowtransparency', 'true');
- } else if (vMatch && vMatch[0].length) {
- $video = $('<iframe>')
- .attr('src', vMatch[0] + '/embed/simple')
- .attr('width', '600').attr('height', '600')
- .attr('class', 'vine-embed');
- } else if (vimMatch && vimMatch[3].length) {
- $video = $('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>')
- .attr('src', '//player.vimeo.com/video/' + vimMatch[3])
- .attr('width', '640').attr('height', '360');
- } else if (dmMatch && dmMatch[2].length) {
- $video = $('<iframe>')
- .attr('src', '//www.dailymotion.com/embed/video/' + dmMatch[2])
- .attr('width', '640').attr('height', '360');
- } else if (youkuMatch && youkuMatch[1].length) {
- $video = $('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>')
- .attr('height', '498')
- .attr('width', '510')
- .attr('src', '//player.youku.com/embed/' + youkuMatch[1]);
- } else {
- // this is not a known video link. Now what, Cat? Now what?
- }
-
- $video.attr('frameborder', 0);
-
- return $video;
-}
-
-/**
- * VideoDialog widget. Lets users change a video, support all summernote
- * video, and embled iframe
- */
-var VideoDialog = Widget.extend({
- template: 'website.editor.dialog.video',
- events : _.extend({}, Dialog.prototype.events, {
- 'click input#urlvideo ~ button': 'get_video',
- 'click input#embedvideo ~ button': 'get_embed_video',
- 'change input#urlvideo': 'change_input',
- 'keyup input#urlvideo': 'change_input',
- 'change input#embedvideo': 'change_input',
- 'keyup input#embedvideo': 'change_input'
- }),
- init: function (parent, media) {
- this._super();
- this.parent = parent;
- this.media = media;
- },
- start: function () {
- this.$preview = this.$('.preview-container').detach();
- this.$iframe = this.$("iframe");
- var $media = $(this.media);
- if ($media.hasClass("media_iframe_video")) {
- var src = $media.data('src');
- this.$("input#urlvideo").val(src);
- this.$("#autoplay").attr("checked", src.indexOf('autoplay=1') != -1);
- this.get_video();
- } else {
- this.add_class = "pull-left";
- }
- return this._super();
- },
- change_input: function (e) {
- var $input = $(e.target);
- var $button = $input.parent().find("button");
- if ($input.val() === "") {
- $button.addClass("btn-default").removeClass("btn-primary");
- } else {
- $button.removeClass("btn-default").addClass("btn-primary");
- }
- },
- get_embed_video: function (event) {
- event.preventDefault();
- var embedvideo = this.$("input#embedvideo").val().match(/src=["']?([^"']+)["' ]?/);
- if (embedvideo) {
- this.$("input#urlvideo").val(embedvideo[1]);
- this.get_video(event);
- }
- return false;
- },
- get_video: function (event) {
- if (event) event.preventDefault();
- var $video = createVideoNode(this.$("input#urlvideo").val());
- this.$iframe.replaceWith($video);
- this.$iframe = $video;
- return false;
- },
- save: function () {
- this.parent.trigger("save", this.media);
- var video_id = this.$("#video_id").val();
- if (!video_id) {
- this.$("button.btn-primary").click();
- video_id = this.$("#video_id").val();
- }
- var video_type = this.$("#video_type").val();
- var $iframe = $(
- '<div class="media_iframe_video" data-src="'+this.$iframe.attr("src")+'">'+
- '<div class="css_editable_mode_display">&nbsp;</div>'+
- '<div class="media_iframe_video_size" contentEditable="false">&nbsp;</div>'+
- '<iframe src="'+this.$iframe.attr("src")+'" frameborder="0" allowfullscreen="allowfullscreen" contentEditable="false"></iframe>'+
- '</div>');
- $(this.media).replaceWith($iframe);
- this.media = $iframe[0];
- },
- clear: function () {
- if (this.media.dataset.src) {
- try {
- delete this.media.dataset.src;
- } catch(e) {
- this.media.dataset.src = undefined;
- }
- }
-
- this.media.className = this.media.className.replace(/(^|\s)media_iframe_video(\s|$)/g, ' ');
- },
-});
-
-var editor_bar = new EditorBar();
-function init_editor() {
- var $body = $(document.body);
- editor_bar.prependTo($body).then(function () {
- if (location.search.indexOf("enable_editor") >= 0) {
- editor_bar.edit();
- }
- });
-};
-
-return {
- EditorBar: EditorBar,
- editor_bar: editor_bar,
- LinkDialog: LinkDialog,
- Dialog: Dialog,
- MediaDialog: MediaDialog,
- getCssSelectors: getCssSelectors,
-};
-
-});
+}); \ No newline at end of file
diff --git a/addons/website/static/src/js/website.js b/addons/website/static/src/js/website.js
index a9f1f41d95c..728321b7e1f 100644
--- a/addons/website/static/src/js/website.js
+++ b/addons/website/static/src/js/website.js
@@ -3,10 +3,14 @@ odoo.define('website.website', function (require) {
var ajax = require('web.ajax');
var core = require('web.core');
+var Widget = require('web.Widget');
var session = require('web.session');
+var base = require('web_editor.base');
var Tour = require('web.Tour');
+var qweb = core.qweb;
var _t = core._t;
+base.url_translations = '/website/translations';
/* --- Set the browser into the dom for css selectors --- */
var browser;
@@ -18,66 +22,24 @@ else if ($.browser.mozilla) browser = "mozilla";
browser += ","+$.browser.version;
if (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase())) browser += ",mobile";
document.documentElement.setAttribute('data-browser', browser);
-/* ---------------------------------------------------- */
-
-
-var translatable = !!$('html').data('translatable');
-var data = {
- id: undefined,
- session: undefined,
-};
/* ----------------------------------------------------
Helpers
- ---------------------------------------------------- */
-function get_context(dict) {
+ ---------------------------------------------------- */
+
+var get_context = base.get_context;
+base.get_context = base.get_context = function (dict) {
var html = document.documentElement;
return _.extend({
- lang: html.getAttribute('lang').replace('-', '_'),
- website_id: html.getAttribute('data-website-id')|0
- }, dict);
-}
-
-function parseQS(qs) {
- var match,
- params = {},
- pl = /\+/g, // Regex for replacing addition symbol with a space
- search = /([^&=]+)=?([^&]*)/g;
-
- while ((match = search.exec(qs))) {
- var name = decodeURIComponent(match[1].replace(pl, " "));
- var value = decodeURIComponent(match[2].replace(pl, " "));
- params[name] = value;
- }
- return params;
-}
-
-var _parsedSearch;
-function parseSearch() {
- if (!_parsedSearch) {
- _parsedSearch = parseQS(window.location.search.substring(1));
- }
- return _parsedSearch;
-}
-
-function parseHash() {
- return parseQS(window.location.hash.substring(1));
-}
-
-function reload() {
- location.hash = "scrollTop=" + window.document.body.scrollTop;
- if (location.search.indexOf("enable_editor") > -1) {
- window.location.href = window.location.href.replace(/enable_editor(=[^&]*)?/g, '');
- } else {
- window.location.reload();
- }
-}
+ 'website_id': html.getAttribute('data-website-id')|0
+ }, get_context(dict), dict);
+};
/* ----------------------------------------------------
Widgets
---------------------------------------------------- */
-function prompt(options, qweb) {
+var prompt = function (options, _qweb) {
/**
* A bootstrapped version of prompt() albeit asynchronous
* This was built to quickly prompt the user with a single field.
@@ -111,8 +73,8 @@ function prompt(options, qweb) {
text: options
};
}
- if (_.isUndefined(qweb)) {
- qweb = 'website.prompt';
+ if (_.isUndefined(_qweb)) {
+ _qweb = 'website.prompt';
}
options = _.extend({
window_title: '',
@@ -127,7 +89,7 @@ function prompt(options, qweb) {
options.field_name = options.field_name || options[type];
var def = $.Deferred();
- var dialog = $(core.qweb.render(qweb, options)).appendTo("body");
+ var dialog = $(qweb.render(_qweb, options)).appendTo("body");
options.$dialog = dialog;
var field = dialog.find(options.field_type).first();
field.val(options['default']); // dict notation for IE<9
@@ -168,34 +130,34 @@ function prompt(options, qweb) {
});
}
return def;
-}
+};
-function error(data, url) {
- var $error = $(core.qweb.render('website.error_dialog', {
+var error = function(data, url) {
+ var $error = $(qweb.render('website.error_dialog', {
'title': data.data ? data.data.arguments[0] : "",
'message': data.data ? data.data.arguments[1] : data.statusText,
'backend_url': url
}));
$error.appendTo("body");
$error.modal('show');
-}
+};
-function form(url, method, params) {
- var htmlform = document.createElement('form');
- htmlform.setAttribute('action', url);
- htmlform.setAttribute('method', method);
+var form = function (url, method, params) {
+ var form = document.createElement('form');
+ form.setAttribute('action', url);
+ form.setAttribute('method', method);
_.each(params, function (v, k) {
var param = document.createElement('input');
param.setAttribute('type', 'hidden');
param.setAttribute('name', k);
param.setAttribute('value', v);
- htmlform.appendChild(param);
+ form.appendChild(param);
});
- document.body.appendChild(htmlform);
- htmlform.submit();
-}
+ document.body.appendChild(form);
+ form.submit();
+};
-function init_kanban($kanban) {
+var init_kanban = function ($kanban) {
$('.js_kanban_col', $kanban).each(function () {
var $col = $(this);
var $pagination = $('.pagination', $col);
@@ -223,7 +185,7 @@ function init_kanban($kanban) {
}
var page = +$a.attr("href").split(",").pop().split('-')[1];
- data.page = page;
+ data['page'] = page;
$.post('/website/kanban', data, function (col) {
$col.find("> .thumbnail").remove();
@@ -250,43 +212,9 @@ function init_kanban($kanban) {
});
});
-}
-
-/* ----------------------------------------------------
- Async Ready and Template loading
- ---------------------------------------------------- */
-var templates_def = $.Deferred().resolve();
-function add_template_file(template) {
- var def = $.Deferred();
- templates_def = templates_def.then(function() {
- core.qweb.add_template(template, function(err) {
- if (err) {
- def.reject(err);
- } else {
- def.resolve();
- }
- });
- return def;
- });
- return def;
-}
-
-add_template_file('/website/static/src/xml/website.xml');
+};
-var dom_ready = $.Deferred();
-$(document).ready(function () {
- dom_ready.resolve();
- // fix for ie
- if($.fn.placeholder) $('input, textarea').placeholder();
- $(".oe_search_box").on('input', function() {
- $(this).next('span').toggle(!!$(this).val());
- });
- $(".oe_search_clear").on('click', function() {
- $(this).prev('input').val('').focus();
- $(".oe_search_button").trigger("click");
- });
- $(".oe_search_clear").toggle(!!$('.oe_search_box').val());
-});
+ajax.loadXML('/website/static/src/xml/website.xml', qweb);
/**
* Execute a function if the dom contains at least one element matched
@@ -295,73 +223,38 @@ $(document).ready(function () {
* @param {String} selector A jQuery selector used to match the element(s)
* @param {Function} fn Callback to execute if at least one element has been matched
*/
-function if_dom_contains(selector, fn) {
- dom_ready.then(function () {
+var if_dom_contains = function(selector, fn) {
+ base.dom_ready.then(function () {
var elems = $(selector);
if (elems.length) {
fn(elems);
}
});
-}
+};
+
+/**
+ * Cancel the auto run of Tour (test) and launch the tour after tob bar all bind events
+ */
+
+Tour.autoRunning = false;
+base.ready().then(function () {
+ data.topBar = new TopBar();
+ data.topBar.attachTo($("#oe_main_menu_navbar"))
+ .then(function () {
+ setTimeout(Tour.running,0);
+ });
+});
-var all_ready = null;
/**
* Returns a deferred resolved when the templates are loaded
* and the Widgets can be instanciated.
*/
-function ready() {
- if (!all_ready) {
- all_ready = dom_ready.then(function () {
- return templates_def;
- }).then(function () {
- odoo.init();
-
- // display button if they are at least one editable zone in the page (check the branding)
- if ($('[data-oe-model]').size()) {
- $("#oe_editzone").show();
- }
-
- if ($('html').data('website-id')) {
- data.id = $('html').data('website-id');
- data.session = session;
-
- return ajax.jsonRpc('/website/translations', 'call', {'lang': get_context().lang})
- .then(function(trans) {
- _t.database.set_bundle(trans);});
- }
- }).then(function () {
- var templates = core.qweb.templates;
- var keys = _.keys(templates);
- for (var i = 0; i < keys.length; i++){
- treat_node(templates[keys[i]]);
- }
- }).promise();
- }
- return all_ready;
-}
-
-function treat_node(node){
- if(node.nodeType === 3) {
- if(node.nodeValue.match(/\S/)){
- var text_value = $.trim(node.nodeValue);
- var spaces = node.nodeValue.split(text_value);
- node.nodeValue = spaces[0] + _t(text_value) + spaces[1];
- }
- }
- else if(node.nodeType === 1 && node.hasChildNodes()) {
- _.each(node.childNodes, function(subnode) {treat_node(subnode);});
- }
-};
-
-
-function inject_tour() {
- // if a tour is active inject tour js
-}
-
-dom_ready.then(function () {
+
+base.dom_ready.then(function () {
/* ----- PUBLISHING STUFF ---- */
$(document).on('click', '.js_publish_management .js_publish_btn', function () {
var $data = $(this).parents(".js_publish_management:first");
+ var self=this;
ajax.jsonRpc($data.data('controller') || '/website/publish', 'call', {'id': +$data.data('id'), 'object': $data.data('object')})
.then(function (result) {
$data.toggleClass("css_unpublished css_published");
@@ -389,7 +282,7 @@ dom_ready.then(function () {
// retrieve the hash before the redirect
var redirect = {
lang: self.data('lang'),
- url: self.attr('href'),
+ url: encodeURIComponent(self.attr('href').replace(/[&?]edit_translations[^&?]+/, '')),
hash: location.hash
};
location.href = _.str.sprintf("/website/lang/%(lang)s?r=%(url)s%(hash)s", redirect);
@@ -412,48 +305,37 @@ dom_ready.then(function () {
window.document.body.scrollTop = +location.hash.match(/scrollTop=([0-9]+)/)[1];
}
},0);
+});
- /* ----- WEBSITE TOP BAR ---- */
- var $collapse = $('#oe_applications ul.dropdown-menu').clone()
- .attr("id", "oe_applications_collapse")
- .attr("class", "nav navbar-nav navbar-left navbar-collapse collapse");
- $('#oe_applications').before($collapse);
- $collapse.wrap('<div class="visible-xs"/>');
- $('[data-target="#oe_applications"]').attr("data-target", "#oe_applications_collapse");
- });
- Tour.autoRunning = false;
- ready().then(function () {
- setTimeout(Tour.running,0);
+/**
+ * Object who contains all method and bind for the top bar, the template is create server side.
+ */
+
+var TopBar = Widget.extend({
+ start: function () {
+ var $collapse = this.$('#oe_applications ul.dropdown-menu').clone()
+ .attr("id", "oe_applications_collapse")
+ .attr("class", "nav navbar-nav navbar-left navbar-collapse collapse");
+ this.$('#oe_applications').before($collapse);
+ $collapse.wrap('<div class="visible-xs"/>');
+ this.$('[data-target="#oe_applications"]').attr("data-target", "#oe_applications_collapse");
+
+ return this._super();
+ }
});
-return {
- translatable: translatable,
- get_context: get_context,
- parseQS: parseQS,
- parseSearch: parseSearch,
- parseHash: parseHash,
- reload: reload,
+
+var data = {
prompt: prompt,
- error: error,
form: form,
- init_kanban: init_kanban,
- add_template_file: add_template_file,
- dom_ready: dom_ready,
if_dom_contains: if_dom_contains,
- ready: ready,
- inject_tour: inject_tour,
-
- data: data,
+ TopBar: TopBar,
};
+return data;
});
-odoo.define('web.session', function (require) {
-"use strict";
-
-var Session = require('web.Session');
-
-return new Session(null, null, {modules: ['website']});
-
+$(function () {
+ odoo.init();
});
diff --git a/addons/website/static/src/js/website.snippets.animation.js b/addons/website/static/src/js/website.snippets.animation.js
index 0b1c7befaa1..fa65484aff5 100644
--- a/addons/website/static/src/js/website.snippets.animation.js
+++ b/addons/website/static/src/js/website.snippets.animation.js
@@ -25,42 +25,6 @@ function load_called_template () {
}
}
-function start_animation(editable_mode, $target) {
- for (var k in animationRegistry) {
- var Animation = animationRegistry[k];
- var selector = "";
- if (Animation.prototype.selector) {
- if (selector !== "") selector += ", ";
- selector += Animation.prototype.selector;
- }
- if ($target) {
- if ($target.is(selector)) selector = $target;
- else continue;
- }
-
- $(selector).each(function () {
- var $snipped_id = $(this);
- if ( !$snipped_id.parents("#oe_snippets").length &&
- !$snipped_id.parent("body").length &&
- !$snipped_id.data("snippet-view")) {
- readyAnimation.push($snipped_id);
- $snipped_id.data("snippet-view", new Animation($snipped_id, editable_mode));
- } else if ($snipped_id.data("snippet-view")) {
- $snipped_id.data("snippet-view").start(editable_mode);
- }
- });
- }
-}
-
-function stop_animation() {
- $(readyAnimation).each(function() {
- var $snipped_id = $(this);
- if ($snipped_id.data("snippet-view")) {
- $snipped_id.data("snippet-view").stop();
- }
- });
-}
-
$(document).ready(function () {
load_called_template(); // if asset is placed into head, move this call into $(document).ready
@@ -68,35 +32,9 @@ $(document).ready(function () {
// load gallery modal template
website.add_template_file('/website/static/src/xml/website.gallery.xml');
}
-
- start_animation();
});
-
-var Animation = core.Class.extend({
- selector: false,
- $: function () {
- return this.$el.find.apply(this.$el, arguments);
- },
- init: function (dom, editable_mode) {
- this.$el = this.$target = $(dom);
- this.start(editable_mode);
- },
- /*
- * start
- * This method is called after init
- */
- start: function () {
- },
- /*
- * stop
- * This method is called to stop the animation (e.g.: when rte is launch)
- */
- stop: function () {
- },
-});
-
animationRegistry.slider = Animation.extend({
selector: ".carousel",
start: function () {
@@ -272,7 +210,6 @@ animationRegistry.gallery = Animation.extend({
}
} // click_handler
});
-
animationRegistry.gallery_slider = Animation.extend({
selector: ".o_slideshow",
start: function() {
@@ -321,13 +258,4 @@ animationRegistry.gallery_slider = Animation.extend({
}
});
-return {
- Animation: Animation,
- readyAnimation: readyAnimation,
- start_animation: start_animation,
- stop_animation: stop_animation,
- registry: animationRegistry,
-};
-
});
-
diff --git a/addons/website/static/src/js/website.snippets.editor.js b/addons/website/static/src/js/website.snippets.editor.js
index 3be81da11ce..d9e41badd8e 100644
--- a/addons/website/static/src/js/website.snippets.editor.js
+++ b/addons/website/static/src/js/website.snippets.editor.js
@@ -1,1066 +1,19 @@
odoo.define('website.snippets.editor', function (require) {
'use strict';
-var ajax = require('web.ajax');
-var Class = require('web.Class');
-var core = require('web.core');
-var Widget = require('web.Widget');
-var editor = require('website.editor');
+var widget = require('web_editor.widget');
+var animation = require('web_editor.snippets.animation');
+var options = require('web_editor.snippets.options');
+var snippet_editor = require('web_editor.snippet.editor');
-var animation = require('website.snippets.animation');
-var website = require('website.website');
-
-var dummy = function () {};
-
-var options = {};
-
-var templateOptions = [];
-var globalSelector = {
- closest: function () { return $(); },
- all: function () { return $(); },
- is: function () { return false; },
-};
-var selector = [];
-
-website.add_template_file('/website/static/src/xml/website.snippets.xml');
-
-editor.EditorBar.include({
- start: function () {
- var self = this;
- $(document).on('click', '.o_editable', function (event) {
- var $this = $(event.srcElement);
- var tag = $this[0] && $this[0].tagName.toLowerCase();
- if (!(tag === 'a' || tag === "button") && !$this.parents("a, button").length) {
- self.$('[data-action="edit"]').parent().effect('bounce', {distance: 18, times: 5}, 250);
- }
- });
- return this._super();
- },
- edit: function () {
- var self = this;
- animation.stop_animation();
- this.on('rte:ready', this, function () {
- var $editable = $(".o_editable");
- window.snippets = this.snippets = new BuildingBlock(this, $editable);
- this.snippets.insertAfter(this.$el);
- animation.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);
- },
- save: function () {
- this.snippets.clean_for_save();
- this._super();
- },
-});
-
-/* ----- SNIPPET SELECTOR ---- */
-
-$.extend($.expr[':'],{
- o_editable: function(node,i,m){
- while (node) {
- if (node.className) {
- if (node.className.indexOf('o_not_editable')!==-1 ) {
- return false;
- }
- if (node.className.indexOf('o_editable')!==-1 ) {
- return true;
- }
- }
- node = node.parentNode;
- }
- return false;
- },
- hasData: function(node,i,m){
- return !!_.toArray(node.dataset).length;
- },
- data: function(node,i,m){
- return $(node).data(m[3]);
- }
-});
-
-
-var BuildingBlock = Widget.extend({
- template: 'website.snippets',
- activeSnippets: [],
- init: function (parent, $editable) {
- this.parent = parent;
- this.$editable = $editable;
-
- this._super.apply(this, arguments);
- if(!$('#oe_manipulators').length){
- $("<div id='oe_manipulators'></div>").appendTo('body');
- }
- this.$active_snipped_id = false;
- this.snippets = [];
- },
- start: function() {
- var self = this;
- this.$snippet = $("#oe_snippets");
-
- this.$el
- .on("mouseenter", function () { self.show(); })
- .on("mouseleave", function (event) { if (event.clientX>0 && event.clientY>0) self.hide(); });
-
- $(window).resize(function () {
- setTimeout('$(document).click()',0);
- });
-
- this.fetch_snippet_templates();
- this.bind_snippet_click_editor();
-
- $(document).on('click', '.dropdown-submenu a[tabindex]', function (e) {
- e.preventDefault();
- });
-
- var _isNotBreakable = $.summernote.core.dom.isNotBreakable;
- $.summernote.core.dom.isNotBreakable = function (node, sc, so, ec, eo) {
- return _isNotBreakable(node, sc, so, ec, eo) || $(node).is('div') || globalSelector.is($(node));
- };
-
- $(window).on('resize', function () {
- 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);
- }
- });
-
- $(document).on('mousemove', function () {
- if (self.$active_snipped_id && self.$active_snipped_id.data("snippet-editor")) {
- self.$active_snipped_id.data("snippet-editor").$overlay.removeClass('o_keypress');
- }
- });
- $(document).on('keydown', function (event) {
- if (self.$active_snipped_id && self.$active_snipped_id.data("snippet-editor")) {
- self.$active_snipped_id.data("snippet-editor").$overlay.addClass('o_keypress');
- }
- if ((event.metaKey || (event.ctrlKey && !event.altKey)) && event.shiftKey && event.keyCode >= 48 && event.keyCode <= 57) {
- self.$snippet.find('.scroll:first > ul li:eq('+(event.keyCode-49)+') a').trigger("click");
- self.show();
- event.preventDefault();
- }
- });
- },
+snippet_editor.Class.include({
_get_snippet_url: function () {
return '/website/snippets';
- },
- _add_check_selector : function (selector, no_check) {
- var self = this;
- selector = selector.split(/\s*,/).join(":not(.o_snippet_not_selectable), ") + ":not(.o_snippet_not_selectable)";
-
- if (no_check) {
- return {
- closest: function ($from, parentNode) {
- return $from.closest(selector, parentNode);
- },
- all: function ($from) {
- return $from ? $from.find(selector) : $(selector);
- },
- is: function ($from) {
- return $from.is(selector);
- }
- };
- } else {
- selector = selector.split(/\s*,/).join(":o_editable, ") + ":o_editable";
- return {
- closest: function ($from, parentNode) {
- var parents = self.$editable.get();
- return $from.closest(selector, parentNode).filter(function () {
- var node = this;
- while (node.parentNode) {
- if (parents.indexOf(node)!==-1) {
- return true;
- }
- node = node.parentNode;
- }
- return false;
- });
- },
- all: function ($from) {
- return $from ? $from.find(selector) : self.$editable.parent().find(selector);
- },
- is: function ($from) {
- return $from.is(selector);
- }
- };
- }
- },
-
- fetch_snippet_templates: function () {
- var self = this;
- var url = this._get_snippet_url();
- if (!url || !url.length) {
- this.$snippet.detach();
- return;
- }
- return ajax.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");
- }
-
- // t-snippet
- $html.find('[data-oe-type="snippet"][data-oe-name]').each(function () {
- $('<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()
- };
- templateOptions.push(option);
- selector.push(option.selector);
- });
- $styles.addClass("hidden");
- _.extend(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
- }
- if (!$(this).data("selector")) {
- $("> *: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 () {
- 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], [data-oe-type]').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
-
- $html.find('.o_not_editable').attr("contentEditable", false);
-
- $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();
- var mt = parseInt($target.css("margin-top") || 0);
- var mb = parseInt($target.css("margin-bottom") || 0);
- var width = $target.outerWidth();
- var bigger = pos.left+width > $("body").outerWidth()-8;
- $el.css({
- 'width': width,
- 'top': pos.top - mt - 5,
- 'left': pos.left-1
- });
- $el.find(".oe_handle.e,.oe_handle.w").css({'height': $target.outerHeight() + mt + mb+1});
- if (bigger) {
- $el.find(".oe_handle.e").css({right: 0, margin: 0})
- .find("div").css({right: 0, left: 'auto'});
- } else {
- $el.find(".oe_handle.e").css({right: "", margin: ""})
- .find("div").css({right: "", left: ""});
- }
- $el.find(".oe_handle.s").css({'top': $target.outerHeight() + mt + mb});
- $el.find(".oe_handle.size").css({'top': $target.outerHeight() + mt});
- $el.find(".oe_handle.s,.oe_handle.n").css({'width': width-2});
- },
-
- show_blocks: function () {
- var cache = {};
- this.$snippet.find(".tab-pane").each(function () {
- var catcheck = false;
- var $category = $(this);
- $category.find(".oe_snippet_body").each(function () {
- var $snippet = $(this);
-
- var check = false;
-
- for (var k in templateOptions) {
- var option = templateOptions[k];
- if ($snippet.is(option.base_selector)) {
-
- cache[k] = cache[k] || {
- 'drop-near': option['drop-near'] ? option['drop-near'].all() : [],
- 'drop-in': option['drop-in'] ? option['drop-in'].all() : []
- };
-
- if (cache[k]['drop-near'].length || cache[k]['drop-in'].length) {
- catcheck = true;
- check = true;
- break;
- }
- }
- }
-
- if (check) {
- $snippet.closest(".oe_snippet").removeClass("disable");
- } else {
- $snippet.closest(".oe_snippet").addClass("disable");
- }
- });
-
- $('#oe_snippets .scroll a[data-toggle="tab"][href="#' + $category.attr("id") + '"]').toggle(catcheck);
- });
- },
- show: function () {
- this.make_active(false);
- this.$el.addClass("o_open");
- this.show_blocks();
- },
- hide: function () {
- this.$el.removeClass("o_open");
- },
- bind_snippet_click_editor: function () {
- var self = this;
- var snipped_event_flag;
- $(document).on('click', '*', function (event) {
- var srcElement = event.srcElement || (event.originalEvent && (event.originalEvent.originalTarget || event.originalEvent.target) || event.target);
- if (self.editor_busy || snipped_event_flag===srcElement || !srcElement) {
- return;
- }
- snipped_event_flag = srcElement;
-
- setTimeout(function () {snipped_event_flag = false;}, 0);
- var $target = $(srcElement);
-
- if ($target.closest(".oe_overlay, .note-popover").length) {
- return;
- }
-
- if (!globalSelector.is($target)) {
- $target = globalSelector.closest($target);
- }
-
- if (self.$active_snipped_id && self.$active_snipped_id.is($target)) {
- return;
- }
- self.make_active($target);
- });
- },
- snippet_blur: function ($snippet) {
- if ($snippet) {
- if ($snippet.data("snippet-editor")) {
- $snippet.data("snippet-editor").on_blur();
- }
- }
- },
- snippet_focus: function ($snippet) {
- if ($snippet) {
- if ($snippet.data("snippet-editor")) {
- $snippet.data("snippet-editor").on_focus();
- }
- }
- },
- clean_for_save: function () {
- var self = this;
- var template = templateOptions;
- 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 () {
- new Option(self, null, $(this), k).clean_for_save();
- });
- }
- }
- this.$editable.find("*[contentEditable], *[attributeEditable]")
- .removeAttr('contentEditable')
- .removeProp('contentEditable')
- .removeAttr('attributeEditable')
- .removeProp('attributeEditable');
- },
- make_active: function ($snippet) {
- if ($snippet && this.$active_snipped_id && this.$active_snipped_id.get(0) === $snippet.get(0)) {
- return;
- }
- if (this.$active_snipped_id) {
- this.snippet_blur(this.$active_snipped_id);
- this.$active_snipped_id = false;
- }
- if ($snippet && $snippet.length) {
- if(_.indexOf(this.snippets, $snippet.get(0)) === -1) {
- this.snippets.push($snippet.get(0));
- }
- this.$active_snipped_id = $snippet;
- this.create_overlay(this.$active_snipped_id);
- this.snippet_focus($snippet);
- }
- this.$snippet.trigger('snippet-activated', $snippet);
- if ($snippet) {
- $snippet.trigger('snippet-activated', $snippet);
- }
- },
- create_overlay: function ($snippet) {
- if (typeof $snippet.data("snippet-editor") === 'undefined') {
- var $targets = this.activate_overlay_zones($snippet);
- if (!$targets.length) return;
- $snippet.data("snippet-editor", new SnippetEditor(this, $snippet));
- }
- this.cover_target($snippet.data('overlay'), $snippet);
- },
-
- // activate drag and drop for the snippets in the snippet toolbar
- make_snippet_draggable: function($snippets){
- var self = this;
- var $tumb = $snippets.find(".oe_snippet_thumbnail_img:first");
- var left = $tumb.outerWidth()/2;
- var top = $tumb.outerHeight()/2;
- var $toInsert, dropped, $snippet;
-
- $snippets.draggable({
- greedy: true,
- helper: 'clone',
- zIndex: '1000',
- appendTo: 'body',
- cursor: "move",
- handle: ".oe_snippet_thumbnail",
- cursorAt: {
- 'left': left,
- 'top': top
- },
- start: function(){
- self.hide();
- dropped = false;
- // snippet_selectors => to get drop-near, drop-in
- $snippet = $(this);
- var $base_body = $snippet.find('.oe_snippet_body');
- var $selector_siblings = $();
- var $selector_children = $();
- var temp = templateOptions;
- for (var k in temp) {
- if ($base_body.is(temp[k].base_selector)) {
- if (temp[k]['drop-near']) {
- if (!$selector_siblings) $selector_siblings = temp[k]['drop-near'].all();
- else $selector_siblings = $selector_siblings.add(temp[k]['drop-near'].all());
- }
- if (temp[k]['drop-in']) {
- if (!$selector_children) $selector_children = temp[k]['drop-in'].all();
- else $selector_children = $selector_children.add(temp[k]['drop-in'].all());
- }
- }
- }
-
- $toInsert = $base_body.clone();
-
- if (!$selector_siblings.length && !$selector_children.length) {
- console.debug($snippet.find(".oe_snippet_thumbnail_title").text() + " have not insert action: data-drop-near or data-drop-in");
- return;
- }
-
- self.activate_insertion_zones($selector_siblings, $selector_children);
-
- $('.oe_drop_zone').droppable({
- over: function(){
- dropped = true;
- $(this).first().after($toInsert);
- },
- out: function(){
- var prev = $toInsert.prev();
- if(this === prev[0]){
- dropped = false;
- $toInsert.detach();
- }
- }
- });
- },
- stop: function(ev, ui){
- $toInsert.removeClass('oe_snippet_body');
-
- if (! dropped && self.$editable.find('.oe_drop_zone') && ui.position.top > 3) {
- var el = self.$editable.find('.oe_drop_zone').nearest({x: ui.position.left, y: ui.position.top}).first();
- if (el.length) {
- el.after($toInsert);
- dropped = true;
- }
- }
-
- self.$editable.find('.oe_drop_zone').droppable('destroy').remove();
-
- if (dropped) {
-
- var prev = $toInsert.first()[0].previousSibling;
- var next = $toInsert.last()[0].nextSibling;
- var rte = self.parent.rte;
-
- if (prev) {
- $toInsert.detach();
- rte.historyRecordUndo($(prev));
- $toInsert.insertAfter(prev);
- } else if (next) {
- $toInsert.detach();
- rte.historyRecordUndo($(next));
- $toInsert.insertBefore(next);
- } else {
- var $parent = $toInsert.parent();
- $toInsert.detach();
- rte.historyRecordUndo($parent);
- $parent.prepend($toInsert);
- }
-
- var $target = false;
- $target = $toInsert;
-
- setTimeout(function () {
- self.$snippet.trigger('snippet-dropped', $target);
-
- animation.start_animation(true, $target);
-
- // drop_and_build_snippet
- self.create_overlay($target);
- if ($target.data("snippet-editor")) {
- $target.data("snippet-editor").drop_and_build_snippet();
- }
- for (var k in templateOptions) {
- templateOptions[k].selector.all($target).each(function () {
- var $snippet = $(this);
- self.create_overlay($snippet);
- if ($snippet.data("snippet-editor")) {
- $snippet.data("snippet-editor").drop_and_build_snippet();
- }
- });
- }
- $target.closest(".o_editable").trigger("content_changed");
- // end
-
- self.make_active($target);
- },0);
- } else {
- $toInsert.remove();
- }
- },
- });
- },
-
- // return the original snippet in the editor bar from a snippet id (string)
- get_snippet_from_id: function(id){
- return $('.oe_snippet').filter(function(){
- return $(this).data('option') === id;
- }).first();
- },
-
- // Create element insertion drop zones. two css selectors can be provided
- // selector.children -> will insert drop zones as direct child of the selected elements
- // in case the selected elements have children themselves, dropzones will be interleaved
- // with them.
- // selector.siblings -> will insert drop zones after and before selected elements
- activate_insertion_zones: function($selector_siblings, $selector_children){
- var self = this;
- var zone_template = $("<div class='oe_drop_zone oe_insert'></div>");
-
- if ($selector_children) {
- $selector_children.each(function (){
- var $zone = $(this);
- var css = window.getComputedStyle(this);
- var float = css.float || css.cssFloat;
- var $drop = zone_template.clone();
-
- $zone.append($drop);
- var node = $drop[0].previousSibling;
- var test = !!(node && ((!node.tagName && node.textContent.match(/\S/)) || node.tagName === "BR"));
- if (test) {
- $drop.addClass("oe_vertical oe_vertical_text").css({
- 'height': parseInt(window.getComputedStyle($zone[0]).lineHeight),
- 'float': 'none',
- 'display': 'inline-block'
- });
- } else if (float === "left" || float === "right") {
- $drop.addClass("oe_vertical").css('height', Math.max(Math.min($zone.outerHeight(), $zone.children().last().outerHeight()), 30));
- }
-
- $drop = $drop.clone();
-
- $zone.prepend($drop);
- node = $drop[0].nextSibling;
- test = !!(node && ((!node.tagName && node.textContent.match(/\S/)) || node.tagName === "BR"));
- if (test) {
- $drop.addClass("oe_vertical oe_vertical_text").css({
- 'height': parseInt(window.getComputedStyle($zone[0]).lineHeight),
- 'float': 'none',
- 'display': 'inline-block'
- });
- } else if (float === "left" || float === "right") {
- $drop.addClass("oe_vertical").css('height', Math.max(Math.min($zone.outerHeight(), $zone.children().first().outerHeight()), 30));
- }
- if (test) {
- $drop.css({'float': 'none', 'display': 'inline-block'});
- }
- });
-
- // add children near drop zone
- $selector_siblings = $(_.uniq(($selector_siblings || $()).add($selector_children.children()).get()));
- }
-
- if ($selector_siblings) {
- $selector_siblings.filter(':not(.oe_drop_zone):not(.oe_drop_clone)').each(function (){
- var $zone = $(this);
- var $drop;
- var css = window.getComputedStyle(this);
- var float = css.float || css.cssFloat;
-
- if($zone.prev('.oe_drop_zone:visible').length === 0){
- $drop = zone_template.clone();
- if (float === "left" || float === "right") {
- $drop.addClass("oe_vertical").css('height', Math.max(Math.min($zone.outerHeight(), $zone.prev().outerHeight() || Infinity), 30));
- }
- $zone.before($drop);
- }
- if($zone.next('.oe_drop_zone:visible').length === 0){
- $drop = zone_template.clone();
- if (float === "left" || float === "right") {
- $drop.addClass("oe_vertical").css('height', Math.max(Math.min($zone.outerHeight(), $zone.next().outerHeight() || Infinity), 30));
- }
- $zone.after($drop);
- }
- });
- }
-
- var count;
- do {
- count = 0;
- $zones = self.$editable.find('.oe_drop_zone > .oe_drop_zone').remove(); // no recursive zones
- count += $zones.length;
- $zones.remove();
- } while (count > 0);
-
- // Cleaning consecutive zone and up zones placed between floating or inline elements. We do not like these kind of zones.
- var $zones = self.$editable.find('.oe_drop_zone:not(.oe_vertical)');
- $zones.each(function (){
- var zone = $(this);
- var prev = zone.prev();
- var next = zone.next();
- // remove consecutive zone
- if (prev.is('.oe_drop_zone') || next.is('.oe_drop_zone')) {
- zone.remove();
- return;
- }
- var float_prev = prev.css('float') || 'none';
- var float_next = next.css('float') || 'none';
- var disp_prev = prev.css('display') || null;
- var disp_next = next.css('display') || null;
- if( (float_prev === 'left' || float_prev === 'right')
- && (float_next === 'left' || float_next === 'right') ){
- zone.remove();
- }else if( !( disp_prev === null
- || disp_next === null
- || disp_prev === 'block'
- || disp_next === 'block' )){
- zone.remove();
- }
- });
- },
-
- // generate drop zones covering the elements selected by the selector
- // we generate overlay drop zones only to get an idea of where the snippet are, the drop
- activate_overlay_zones: function($targets){
- var self = this;
-
- function is_visible($el){
- return $el.css('display') != 'none'
- && $el.css('opacity') != '0'
- && $el.css('visibility') != 'hidden';
- }
-
- // filter out invisible elements
- $targets = $targets.filter(function(){ return is_visible($(this)); });
-
- // filter out elements with invisible parents
- $targets = $targets.filter(function(){
- var parents = $(this).parents().filter(function(){ return !is_visible($(this)); });
- return parents.length === 0;
- });
-
- $targets.each(function () {
- var $target = $(this);
- if (!$target.data('overlay')) {
- var $zone = $(core.qweb.render('website.snippet_overlay'));
-
- // fix for pointer-events: none with ie9
- if (document.body && document.body.addEventListener) {
- $zone.on("click mousedown mousedown", function passThrough(event) {
- event.preventDefault();
- $target.each(function() {
- // check if clicked point (taken from event) is inside element
- event.srcElement = this;
- $(this).trigger(event.type);
- });
- return false;
- });
- }
-
- $zone.appendTo('#oe_manipulators');
- $zone.data('target',$target);
- $target.data('overlay',$zone);
-
- var timer;
- $target.closest('.o_editable').on("content_changed", function () {
- if ($target.data('overlay') && $target.data('overlay').hasClass("oe_active")) {
- clearTimeout(timer);
- timer = setTimeout(function () {
- self.cover_target($target.data('overlay'), $target);
- },50);
- }
- });
-
- var resize = function () {
- if ($zone.parent().length) {
- self.cover_target($zone, $target);
- } else {
- $('body').off("resize", resize);
- }
- };
- $('body').on("resize", resize);
- }
- self.cover_target($target.data('overlay'), $target);
- });
- return $targets;
}
});
-
-var Option = Class.extend({
- // initialisation (don't overwrite)
- init: function (BuildingBlock, editor, $target, option_id) {
- this.BuildingBlock = BuildingBlock;
- this.editor = editor;
- this.$target = $target;
- var option = templateOptions[option_id];
- var styles = this.$target.data("snippet-option-ids") || {};
- styles[option_id] = this;
- this.$target.data("snippet-option-ids", styles);
- this.$overlay = this.$target.data('overlay') || $('<div>');
- this.option= option_id;
- this.$el = option.$el.find(">li").clone();
- this.data = option.$el.data();
- },
-
- // helper for this.$target.find
- $: function (selector) {
- return this.$target(selector);
- },
-
- _bind_li_menu: function () {
- this.$el.filter("li:hasData").find('a:first')
- .off('mouseenter click')
- .on('mouseenter click', _.bind(this._mouse, this));
-
- this.$el
- .off('mouseenter click', "li:hasData a")
- .on('mouseenter click', "li:hasData a", _.bind(this._mouse, this));
-
- this.$el.closest("ul").add(this.$el)
- .off('mouseleave')
- .on('mouseleave', _.bind(this.reset, this));
-
- this.$el
- .off('mouseleave', "ul")
- .on('mouseleave', "ul", _.bind(this.reset, this));
-
- this.reset_methods = [];
- },
-
- /**
- * this method handles mouse:over and mouse:leave on the snippet editor menu
- */
- _time_mouseleave: null,
- _mouse: function (event) {
- var $next = $(event.currentTarget).parent();
-
- // triggers preview or apply methods if a menu item has been clicked
- this.select(event.type === "click" ? "click" : "over", $next);
- if (event.type === 'click') {
- this.set_active();
- this.$target.trigger("snippet-option-change", [this]);
- } else {
- this.$target.trigger("snippet-option-preview", [this]);
- }
- },
- /*
- * select and set item active or not (add highlight item and his parents)
- * called before start
- */
- set_active: function () {
- var classes = _.uniq((this.$target.attr("class") || '').split(/\s+/));
- this.$el.find('[data-toggle_class], [data-select_class]')
- .add(this.$el)
- .filter('[data-toggle_class], [data-select_class]')
- .removeClass("active")
- .filter('[data-toggle_class="' + classes.join('"], [data-toggle_class="') + '"] ,'+
- '[data-select_class="' + classes.join('"], [data-select_class="') + '"]')
- .addClass("active");
- },
-
- start: function () {
- this.set_active();
- this.$target.on('snippet-option-reset', _.bind(this.set_active, this));
- this._bind_li_menu();
- },
-
- on_focus : function () {
- this._bind_li_menu();
- },
-
- on_blur : function () {
- },
-
- on_clone: function () {
- },
-
- on_move: function () {
- },
-
- on_remove: function () {
- },
-
- drop_and_build_snippet: function () {
- },
-
- reset: function () {
- var self = this;
- var lis = self.$el.add(self.$el.find('li')).filter('.active').get();
- lis.reverse();
- _.each(lis, function (li) {
- var $li = $(li);
- for (var k in self.reset_methods) {
- var method = self.reset_methods[k];
- if ($li.is('[data-'+method+']') || $li.closest('[data-'+method+']').size()) {
- delete self.reset_methods[k];
- }
- }
- self.select("reset", $li);
- });
-
- for (var k in self.reset_methods) {
- var method = self.reset_methods[k];
- if (method) {
- self[method]("reset", null);
- }
- }
- self.reset_methods = [];
- self.$target.trigger("snippet-option-reset", [this]);
- },
-
- // call data-method args as method (data-only can be used)
- select: function (type, $li) {
- var self = this;
- var $methods = [];
- var el = $li[0];
-
- if ($li.data('only') && type !== $li.data('only')) {
- return;
- }
-
- if (type==="click") {
- this.reset();
- this.BuildingBlock.parent.rte.historyRecordUndo(this.$target);
- }
-
- function filter (k) { return k !== 'oeId' && k !== 'oeModel' && k !== 'oeField' && k !== 'oeXpath' && k !== 'oeSourceId' && k !== 'only';}
- function hasData(el) {
- for (var k in el.dataset) {
- if (filter (k)) {
- return true;
- }
- }
- return false;
- }
- function method(el) {
- var data = {};
- for (var k in el.dataset) {
- if (filter (k)) {
- data[k] = el.dataset[k];
- }
- }
- return data;
- }
-
- while (el && this.$el.is(el) || _.some(this.$el.map(function () {return $.contains(this, el);}).get()) ) {
- if (hasData(el)) {
- $methods.push(el);
- }
- el = el.parentNode;
- }
-
- $methods.reverse();
-
- _.each($methods, function (el) {
- var $el = $(el);
- var methods = method(el);
-
- for (var k in methods) {
- if (self[k]) {
- if (type !== "reset" && self.reset_methods.indexOf(k) === -1) {
- self.reset_methods.push(k);
- }
- self[k](type, methods[k], $el);
- } else {
- console.error("'"+self.option+"' snippet have not method '"+k+"'");
- }
- }
- });
- },
-
- // default method for snippet
- toggle_class: function (type, value) {
- var $lis = this.$el.find('[data-toggle_class]').add(this.$el).filter('[data-toggle_class]');
-
- function map ($lis) {
- return $lis.map(function () {return $(this).data("toggle_class");}).get().join(" ");
- }
- var classes = map($lis);
- var active_classes = map($lis.filter('.active, :has(.active)'));
-
- this.$target.removeClass(classes);
- this.$target.addClass(active_classes);
-
- if (type !== 'reset') {
- this.$target.toggleClass(value);
- }
- },
- select_class: function (type, value) {
- var $lis = this.$el.find('[data-select_class]').add(this.$el).filter('[data-select_class]');
-
- var classes = $lis.map(function () {return $(this).data('select_class');}).get();
-
- this.$target.removeClass(classes.join(" "));
- if(value) this.$target.addClass(value);
- },
- eval: function (type, value, $li) {
- var fn = new Function("node", "type", "value", "$li", value);
- fn.call(this, this, type, value, $li);
- },
-
- clean_for_save: dummy
-});
-
-
var preventParentEmpty = {
hide_remove_button: function() {
this.$overlay.find('.oe_snippet_remove, .oe_snippet_move').toggleClass("hidden", !this.$target.siblings().length);
@@ -1080,119 +33,7 @@ var preventParentEmpty = {
};
-options.background = Option.extend({
- start: function ($change_target) {
- this.$bg = $change_target || this.$target;
- this._super();
- var src = this.$bg.css("background-image").replace(/url\(['"]*|['"]*\)|^none$/g, "");
- if (this.$bg.hasClass('oe_custom_bg')) {
- this.$el.find('li[data-choose_image]').data("background", src).attr("data-background", src);
- }
- },
- background: function(type, value) {
- if (value && value.length) {
- this.$bg.attr("style", 'background-image: url(' + value + ')' + (this.$bg.attr("style") || '').replace(/background-image:[^;]+/, '') );
- this.$bg.addClass("oe_img_bg");
- } else {
- this.$bg.css("background-image", "");
- this.$bg.removeClass("oe_img_bg").removeClass("oe_custom_bg");
- }
- },
- choose_image: function(type, value, $li) {
- if(type !== "click") return;
-
- var self = this;
- var $image = $('<img class="hidden"/>');
- $image.attr("src", value);
- $image.appendTo(self.$bg);
-
- var _editor = new editor.MediaDialog(null, $image[0]);
- _editor.appendTo(document.body);
- _editor.$('[href="#editor-media-video"], [href="#editor-media-icon"]').addClass('hidden');
-
- _editor.on('saved', self, function () {
- var value = $image.attr("src");
- $image.remove();
- self.$el.find('li[data-choose_image]').data("background", value).attr("data-background", value);
- self.background(type, value,$li);
- self.$bg.addClass('oe_custom_bg');
- self.$bg.trigger("snippet-option-change", [self]);
- self.set_active();
- });
- _editor.on('cancel', self, function () {
- $image.remove();
- });
- },
- set_active: function () {
- var src = this.$bg.css("background-image").replace(/url\(['"]*|['"]*\)|^none$/g, "");
- this._super();
-
- this.$el.find('li[data-background]:not([data-background=""])')
- .removeClass("active")
- .each(function () {
- var background = $(this).data("background") || $(this).attr("data-background");
- if ((src.length && background.length && src.indexOf(background) !== -1) || (!src.length && !background.length)) {
- $(this).addClass("active");
- }
- });
-
- if (!this.$el.find('li[data-background].active').size()) {
- this.$el.find('li[data-background=""]:not([data-choose_image])').addClass("active");
- } else {
- this.$el.find('li[data-background=""]:not([data-choose_image])').removeClass("active");
- }
- }
-});
-
-options.colorpicker = Option.extend({
- start: function () {
- var self = this;
- var res = this._super();
-
- if (!this.$el.find('.colorpicker').length) {
- this.$el.find('li').append( core.qweb.render('website.colorpicker') );
- }
-
- if (this.$el.data('area')) {
- this.$target = this.$target.find(this.$el.data('area'));
- this.$el.removeData('area').removeAttr('area');
- }
-
- var classes = [];
- this.$el.find(".colorpicker button").map(function () {
- var $color = $(this);
- var color = $color.attr("class");
- if (self.$target.hasClass(color)) {
- self.color = color;
- $color.parent().addClass("selected");
- }
- classes.push(color);
- });
- this.classes = classes.join(" ");
-
- this.bind_events();
- return res;
- },
- bind_events: function () {
- var self = this;
- var $td = this.$el.find(".colorpicker td");
- var $colors = this.$el.find(".colorpicker button");
- $colors
- .mouseenter(function () {
- self.$target.removeClass(self.classes).addClass($(this).attr("class"));
- })
- .mouseleave(function () {
- self.$target.removeClass(self.classes)
- .addClass($td.filter(".selected").children().attr("class"));
- })
- .click(function () {
- $td.removeClass("selected");
- $(this).parent().addClass("selected");
- });
- }
-});
-
-options.slider = Option.extend({
+options.registry.slider = options.Class.extend({
drop_and_build_snippet: function() {
this.id = "myCarousel" + new Date().getTime();
this.$target.attr("id", this.id);
@@ -1201,7 +42,7 @@ options.slider = Option.extend({
this.rebind_event();
},
on_clone: function ($clone) {
- this.id = "myCarousel" + new Date().getTime();
+ var id = "myCarousel" + new Date().getTime();
$clone.attr("id", id);
$clone.find("[data-slide]").attr("href", "#" + id);
$clone.find("[data-slide-to]").attr("data-target", "#" + id);
@@ -1220,6 +61,7 @@ options.slider = Option.extend({
.first().addClass("active");
},
start : function () {
+ var self = this;
this._super();
this.$target.carousel({interval: false});
this.id = this.$target.attr("id");
@@ -1228,7 +70,7 @@ options.slider = Option.extend({
this.$target.carousel('pause');
this.rebind_event();
},
- add_slide: function (type) {
+ add_slide: function (type, value) {
if(type !== "click") return;
var self = this;
@@ -1239,7 +81,7 @@ options.slider = Option.extend({
this.$indicators.append('<li data-target="#' + this.id + '" data-slide-to="' + cycle + '"></li>');
// clone the best candidate from template to use new features
- var $snippets = this.BuildingBlock.$snippets.find('.oe_snippet_body.carousel');
+ var $snippets = this.buildingBlock.$snippets.find('.oe_snippet_body.carousel');
var point = 0;
var selection;
var className = _.compact(this.$target.attr("class").split(" "));
@@ -1260,13 +102,14 @@ options.slider = Option.extend({
},0);
return $clone;
},
- remove_slide: function (type) {
+ remove_slide: function (type, value) {
if(type !== "click") return;
if (this.remove_process) {
return;
}
var self = this;
+ var new_index = 0;
var cycle = this.$inner.find('.item').length - 1;
var index = this.$inner.find('.item.active').index();
@@ -1299,7 +142,7 @@ options.slider = Option.extend({
},
});
-options.carousel = options.slider.extend({
+options.registry.carousel = options.registry.slider.extend({
getSize: function () {
this.grid = this._super();
this.grid.size = 8;
@@ -1317,6 +160,11 @@ options.carousel = options.slider.extend({
var self = this;
this._super();
+ // set background and prepare to clean for save
+ var add_class = function (c){
+ if (c) self._class = (self._class || "").replace(new RegExp("[ ]+" + c.replace(" ", "|[ ]+")), '') + ' ' + c;
+ return self._class || "";
+ };
this.$target.on('slid.bs.carousel', function () {
if(self.editor && self.editor.styles.background) {
self.editor.styles.background.$bg = self.$target.find(".item.active");
@@ -1356,7 +204,7 @@ options.carousel = options.slider.extend({
},
});
-options.marginAndResize = Option.extend({
+options.registry.marginAndResize = options.Class.extend({
start: function () {
var self = this;
this._super();
@@ -1419,7 +267,7 @@ options.marginAndResize = Option.extend({
var regClass = new RegExp("\\s*" + resize[0][begin].replace(/[-]*[0-9]+/, '[-]*[0-9]+'), 'g');
}
- self.BuildingBlock.editor_busy = true;
+ self.buildingBlock.editor_busy = true;
var cursor = $handle.css("cursor")+'-important';
var $body = $(document.body);
@@ -1434,7 +282,7 @@ options.marginAndResize = Option.extend({
self.$target.css("height", dy+"px");
self.$target.css("overflow", "hidden");
self.on_resize(compass, null, dy);
- self.BuildingBlock.cover_target(self.$overlay, self.$target);
+ self.buildingBlock.cover_target(self.$overlay, self.$target);
return;
}
var dd = event['page'+XY] - xy + resize[1][begin];
@@ -1457,7 +305,7 @@ options.marginAndResize = Option.extend({
if (change) {
self.on_resize(compass, beginClass, current);
- self.BuildingBlock.cover_target(self.$overlay, self.$target);
+ self.buildingBlock.cover_target(self.$overlay, self.$target);
}
};
@@ -1466,19 +314,19 @@ options.marginAndResize = Option.extend({
$body.unbind('mouseup', body_mouseup);
$body.removeClass(cursor);
setTimeout(function () {
- self.BuildingBlock.editor_busy = false;
+ self.buildingBlock.editor_busy = false;
+ self.$target.closest(".o_editable").trigger("content_changed");
},0);
self.$target.removeClass("resize_editor_busy");
- self.$target.closest(".o_editable").trigger("content_changed");
};
$body.mousemove(body_mousemove);
$body.mouseup(body_mouseup);
});
- this.$overlay.find(".oe_handle.size .auto_size").on('click', function (){
+ this.$overlay.find(".oe_handle.size .auto_size").on('click', function (event){
self.$target.css("height", "");
self.$target.css("overflow", "");
- self.BuildingBlock.cover_target(self.$overlay, self.$target);
- self.$target.closest(".o_editable").trigger("content_changed");
+ self.buildingBlock.cover_target(self.$overlay, self.$target);
+ self.$target.closest(".o_editable").trigger("content_changed");
return false;
});
},
@@ -1518,7 +366,7 @@ options.marginAndResize = Option.extend({
this.$overlay.attr("class", overlay_class);
},
-
+
/* on_resize
* called when the box is resizing and the class change, before the cover_target
* @compass: resize direction : 'n', 's', 'e', 'w'
@@ -1530,7 +378,7 @@ options.marginAndResize = Option.extend({
}
});
-options["margin-y"] = options.marginAndResize.extend({
+options.registry["margin-y"] = options.registry.marginAndResize.extend({
getSize: function () {
this.grid = this._super();
var grid = [0,4,8,16,32,48,64,92,128];
@@ -1545,7 +393,7 @@ options["margin-y"] = options.marginAndResize.extend({
},
});
-options["margin-x"] = options.marginAndResize.extend(preventParentEmpty).extend({
+options.registry["margin-x"] = options.marginAndResize.extend(preventParentEmpty).extend({
getSize: function () {
this.grid = this._super();
var width = this.$target.parents(".row:first").first().outerWidth();
@@ -1553,7 +401,7 @@ options["margin-x"] = options.marginAndResize.extend(preventParentEmpty).extend(
var grid = [1,2,3,4,5,6,7,8,9,10,11,12];
this.grid.e = [_.map(grid, function (v) {return 'col-md-'+v;}), _.map(grid, function (v) {return width/12*v;})];
- grid = [-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11];
+ var grid = [-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10,11];
this.grid.w = [_.map(grid, function (v) {return 'col-md-offset-'+v;}), _.map(grid, function (v) {return width/12*v;}), 12];
return this.grid;
@@ -1616,7 +464,7 @@ options["margin-x"] = options.marginAndResize.extend(preventParentEmpty).extend(
},
});
-options.resize = options.marginAndResize.extend({
+options.registry.resize = options.registry.marginAndResize.extend({
getSize: function () {
this.grid = this._super();
this.grid.size = 8;
@@ -1624,7 +472,7 @@ options.resize = options.marginAndResize.extend({
},
});
-options.parallax = Option.extend({
+options.registry.parallax = options.Class.extend({
getSize: function () {
this.grid = this._super();
this.grid.size = 8;
@@ -1654,6 +502,7 @@ options.parallax = Option.extend({
this.$target.data("snippet-view").set_values();
},
set_active: function () {
+ var value = this.$target.attr('data-scroll-background-ratio') || 0;
this.$el.find('[data-scroll]').removeClass("active")
.filter('[data-scroll="' + (this.$target.attr('data-scroll-background-ratio') || 0) + '"]').addClass("active");
},
@@ -1665,7 +514,7 @@ options.parallax = Option.extend({
}
});
-options.transform = Option.extend({
+options.registry.transform = options.Class.extend({
start: function () {
var self = this;
this._super();
@@ -1703,12 +552,12 @@ options.transform = Option.extend({
}
});
},
- style: function (type) {
+ style: function (type, value) {
if (type !== 'click') return;
var settings = this.$target.data("transfo").settings;
this.$target.transfo({ 'hide': (settings.hide = !settings.hide) });
},
- clear_style: function (type) {
+ clear_style: function (type, value) {
if (type !== 'click') return;
this.$target.removeClass("fa-spin").attr("style", "");
this.resetTransfo();
@@ -1775,42 +624,16 @@ options.transform = Option.extend({
}
});
-options.media = Option.extend({
+options.registry.ul = options.Class.extend({
start: function () {
- this._super();
- animation.start_animation(true, this.$target);
- },
- edition: function (type) {
- if(type !== "click") return;
var self = this;
- var dialog = new editor.MediaDialog(this.$target.closest('.o_editable'), this.$target[0]);
- dialog.appendTo(document.body);
- dialog.on('saved', this, function (item) {
- self.editor.on_blur();
- self.BuildingBlock.make_active(false);
- if (self.$target.parent().data("oe-field") !== "image") {
- setTimeout(function () {
- self.BuildingBlock.make_active($(item));
- },0);
- }
- });
- },
- on_focus : function () {
- var self = this;
- var $parent = this.$target.parent();
-
- if ($parent.data("oe-field") === "image" && $parent.hasClass('o_editable')) {
- this.$overlay.addClass("hidden");
- self.edition('click', null);
- self.BuildingBlock.make_active(false);
- }
- }
-});
-
-options.ul = Option.extend({
- start: function () {
this._super();
this.$target.data("snippet-view", new animation.registry.ul(this.$target, true));
+ this.$target.on('mouseup', '.o_ul_toggle_self, .o_ul_toggle_next', function () {
+ setTimeout(function () {
+ self.buildingBlock.cover_target(self.$overlay, self.$target);
+ },0);
+ });
},
reset_ul: function () {
this.$target.find('.o_ul_toggle_self, .o_ul_toggle_next').remove();
@@ -1851,12 +674,12 @@ options.ul = Option.extend({
});
-options.collapse = Option.extend(preventParentEmpty).extend({
+options.registry.collapse = Option.extend(preventParentEmpty).extend({
start: function () {
var self = this;
this._super();
this.$target.on('shown.bs.collapse hidden.bs.collapse', '[role="tabpanel"]', function () {
- self.BuildingBlock.cover_target(self.$overlay, self.$target);
+ self.buildingBlock.cover_target(self.$overlay, self.$target);
});
},
create_ids: function ($target) {
@@ -1911,403 +734,5 @@ options.collapse = Option.extend(preventParentEmpty).extend({
});
-var SnippetEditor = Class.extend({
- init: function (BuildingBlock, dom) {
- this.BuildingBlock = BuildingBlock;
- this.$target = $(dom);
- this.$overlay = this.$target.data('overlay');
- this.load_style_options();
- this.get_parent_block();
- this.start();
- },
-
- // activate drag and drop for the snippets in the snippet toolbar
- _drag_and_drop: function(){
- var self = this;
- this.dropped = false;
- this.$overlay.draggable({
- greedy: true,
- appendTo: 'body',
- cursor: "move",
- handle: ".oe_snippet_move",
- cursorAt: {
- left: 18,
- top: 14
- },
- helper: function() {
- var $clone = $(this).clone().css({width: "24px", height: "24px", border: 0});
- $clone.find(".oe_overlay_options >:not(:contains(.oe_snippet_move)), .oe_handle").remove();
- $clone.find(":not(.glyphicon)").css({position: 'absolute', top: 0, left: 0});
- $clone.appendTo("body").removeClass("hidden");
- return $clone;
- },
- start: _.bind(self._drag_and_drop_start, self),
- stop: _.bind(self._drag_and_drop_stop, self)
- });
- },
- _drag_and_drop_after_insert_dropzone: function (){},
- _drag_and_drop_active_drop_zone: function ($zones){
- var self = this;
- $zones.droppable({
- over: function(){
- $(".oe_drop_zone.hide").removeClass("hide");
- $(this).addClass("hide").first().after(self.$target);
- self.dropped = true;
- },
- out: function(){
- $(this).removeClass("hide");
- self.$target.detach();
- self.dropped = false;
- },
- });
- },
- _drag_and_drop_start: function (){
- var self = this;
- self.BuildingBlock.hide();
- self.BuildingBlock.editor_busy = true;
- self.size = {
- width: self.$target.width(),
- height: self.$target.height()
- };
- self.$target.after("<div class='oe_drop_clone' style='display: none;'/>");
- self.$target.detach();
- self.$overlay.addClass("hidden");
-
- var $selector_siblings;
- for (var i=0; i<self.selector_siblings.length; i++) {
- if (!$selector_siblings) $selector_siblings = self.selector_siblings[i].all();
- else $selector_siblings = $selector_siblings.add(self.selector_siblings[i].all());
- }
- var $selector_children;
- for (i=0; i<self.selector_children.length; i++) {
- if (!$selector_children) $selector_children = self.selector_children[i].all();
- else $selector_children = $selector_children.add(self.selector_children[i].all());
- }
-
- self.BuildingBlock.activate_insertion_zones($selector_siblings, $selector_children);
-
- $("body").addClass('move-important');
-
- self._drag_and_drop_after_insert_dropzone();
- self._drag_and_drop_active_drop_zone($('.oe_drop_zone'));
- },
- _drag_and_drop_stop: function (){
- var self = this;
- var $dropzone = this.$target.prev();
- var prev = $dropzone.length && $dropzone[0].previousSibling;
- var next = this.$target.last()[0].nextSibling;
- var $parent = this.$target.parent();
-
- $(".oe_drop_clone").after(this.$target);
-
- this.$overlay.removeClass("hidden");
- $("body").removeClass('move-important');
- $('.oe_drop_zone').droppable('destroy').remove();
- $(".oe_drop_clone, .oe_drop_to_remove").remove();
-
- if (this.dropped) {
- this.BuildingBlock.parent.rte.historyRecordUndo(this.$target);
-
- if (prev) {
- this.$target.insertAfter(prev);
- } else if (next) {
- this.$target.insertBefore(next);
- } else {
- $parent.prepend(this.$target);
- }
-
- for (var i in this.styles){
- this.styles[i].on_move();
- }
- }
-
- self.BuildingBlock.editor_busy = false;
-
- self.get_parent_block();
- setTimeout(function () {self.BuildingBlock.create_overlay(self.$target);},0);
- },
-
- load_style_options: function () {
- var self = this;
- var $styles = this.$overlay.find('.oe_options');
- var $ul = $styles.find('ul:first');
- this.styles = {};
- this.selector_siblings = [];
- this.selector_children = [];
- _.each(templateOptions, function (val, option_id) {
- if (!val.selector.is(self.$target)) {
- return;
- }
- if (val['drop-near']) self.selector_siblings.push(val['drop-near']);
- if (val['drop-in']) self.selector_children.push(val['drop-in']);
-
- var option = val.option;
- var Editor = options[option] || Option;
- var editor = self.styles[option] = new Editor(self.BuildingBlock, self, self.$target, option_id);
- $ul.append(editor.$el.addClass("snippet-option-" + option));
- editor.start();
- });
-
- if (!this.selector_siblings.length && !this.selector_children.length) {
- this.$overlay.find(".oe_snippet_move, .oe_snippet_clone, .oe_snippet_remove").addClass('hidden');
- }
-
- if ($ul.find("li").length) {
- $styles.removeClass("hidden");
- }
- this.$overlay.find('[data-toggle="dropdown"]').dropdown();
- },
-
- get_parent_block: function () {
- var self = this;
- var $button = this.$overlay.find('.oe_snippet_parent');
- var $parent = globalSelector.closest(this.$target.parent());
- if ($parent.length) {
- $button.removeClass("hidden");
- $button.off("click").on('click', function (event) {
- event.preventDefault();
- setTimeout(function () {
- self.BuildingBlock.make_active($parent);
- }, 0);
- });
- } else {
- $button.addClass("hidden");
- }
- },
-
- /*
- * start
- * This method is called after init and _readXMLData
- */
- start: function () {
- if (!this.$target.parent().is(':o_editable')) {
- this.$overlay.find('.oe_snippet_move, .oe_snippet_clone, .oe_snippet_remove').remove();
- } else {
- this.$overlay.on('click', '.oe_snippet_clone', _.bind(this.on_clone, this));
- this.$overlay.on('click', '.oe_snippet_remove', _.bind(this.on_remove, this));
- this._drag_and_drop();
- }
- },
-
- on_clone: function (event) {
- event.preventDefault();
- var $clone = this.$target.clone(false);
-
- this.BuildingBlock.parent.rte.historyRecordUndo(this.$target);
-
- this.$target.after($clone);
- for (var i in this.styles){
- this.styles[i].on_clone($clone);
- }
- this.BuildingBlock.create_overlay(this.$target);
- return false;
- },
-
- on_remove: function (event) {
- event.preventDefault();
- this.on_blur();
-
- this.BuildingBlock.parent.rte.historyRecordUndo(this.$target);
-
- var index = _.indexOf(this.BuildingBlock.snippets, this.$target.get(0));
- for (var i in this.styles){
- this.styles[i].on_remove();
- }
- delete this.BuildingBlock.snippets[index];
-
- // remove node and his empty
- var node = this.$target.parent()[0];
-
- this.$target.remove();
- this.$overlay.remove();
-
- if (node && node.firstChild) {
- $.summernote.core.dom.removeSpace(node, node.firstChild, 0, node.lastChild, 1);
- if (!node.firstChild.tagName && node.firstChild.textContent === " ") {
- node.firstChild.parentNode.removeChild(node.firstChild);
- }
- }
-
- // clean editor if they are image or table in deleted content
- $(".note-control-selection").hide();
- $('.o_table_handler').remove();
-
- return false;
- },
-
- /*
- * drop_and_build_snippet
- * This method is called just after that a thumbnail is drag and dropped into a drop zone
- * (after the insertion of this.$body, if this.$body exists)
- */
- drop_and_build_snippet: function () {
- for (var i in this.styles){
- this.styles[i].drop_and_build_snippet();
- }
- },
-
- /* on_focus
- * This method is called when the user click inside the snippet in the dom
- */
- on_focus : function () {
- this.$overlay.addClass('oe_active');
- for (var i in this.styles){
- this.styles[i].on_focus();
- }
- },
-
- /* on_focus
- * This method is called when the user click outside the snippet in the dom, after a focus
- */
- on_blur : function () {
- for (var i in this.styles){
- this.styles[i].on_blur();
- }
- this.$overlay.removeClass('oe_active');
- },
-});
-
-/* t-field options */
-
-options.many2one = Option.extend({
- start: function () {
- var self = this;
-
- this.Model = this.$target.data('oe-many2one-model');
- this.ID = +this.$target.data('oe-many2one-id');
-
- // create search button and bind search bar
- this.$btn = $(core.qweb.render("website.many2one.button"))
- .insertAfter(this.$overlay.find('.oe_options'));
-
- this.$ul = this.$btn.find("ul");
- this.$search = this.$ul.find('li:first');
- this.$search.find('input').on('mousedown click mouseup keyup keydown', function (e) {
- e.stopPropagation();
- });
-
- // move menu item
- setTimeout(function () {
- if (self.$overlay.find('.oe_options').hasClass('hidden')) {
- self.$btn.css('height', '0').find('> a').addClass('hidden');
- self.$ul.show().css({
- 'top': '-24px', 'margin': '0', 'padding': '2px 0', 'position': 'relative'
- });
- } else {
- self.$btn.find('a').on('click', function () {
- self.clear();
- });
- }
- },0);
-
- // bind search input
- this.$search.find('input')
- .focus()
- .on('keyup', function() {
- self.find_existing($(this).val());
- });
-
- // bind result
- this.$ul.on('click', "li:not(:first) a", function () {
- self.select_record(this);
- });
- },
-
- on_focus: function () {
- this.$target.attr('contentEditable', 'false');
- this.clear();
- this._super();
- },
- clear: function () {
- var self = this;
- this.$search.siblings().remove();
- self.$search.find('input').val("");
- setTimeout(function () {
- self.$search.find('input').focus();
- },0);
- },
-
- find_existing: function (name) {
- var self = this;
- var domain = [];
- if (!name || !name.length) {
- self.$search.siblings().remove();
- return;
- }
- if (isNaN(+name)) {
- if (this.Model === "res.partner") {
- domain.push(['name', 'ilike', name]);
- } else {
- domain.push('|', ['name', 'ilike', name], ['email', 'ilike', name]);
- }
- } else {
- domain.push(['id', '=', name]);
- }
-
- ajax.jsonRpc('/web/dataset/call_kw', 'call', {
- model: this.Model,
- method: 'search_read',
- args: [domain, this.Model === "res.partner" ? ['name', 'display_name', 'city', 'country_id'] : ['name', 'display_name']],
- kwargs: {
- order: 'name DESC',
- limit: 5,
- context: website.get_context(),
- }
- }).then(function (result){
- self.$search.siblings().remove();
- self.$search.after(core.qweb.render("website.many2one.search",{contacts:result}));
- });
- },
-
- get_contact_rendering: function (options) {
- return ajax.jsonRpc('/web/dataset/call_kw', 'call', {
- model: 'website.qweb.field.contact',
- method: 'get_record_to_html',
- args: [[this.ID]],
- kwargs: {
- options: options,
- context: website.get_context(),
- }
- });
- },
-
- select_record: function (li) {
- var self = this;
-
- this.BuildingBlock.parent.rte.historyRecordUndo(this.$target);
-
- self.ID = +$(li).data("id");
- self.$target.attr('data-oe-many2one-id', self.ID).data('oe-many2one-id', self.ID);
-
- if (self.$target.data('oe-type') === "contact") {
- $('[data-oe-contact-options]')
- .filter('[data-oe-model="'+self.$target.data('oe-model')+'"]')
- .filter('[data-oe-id="'+self.$target.data('oe-id')+'"]')
- .filter('[data-oe-field="'+self.$target.data('oe-field')+'"]')
- .filter('[data-oe-contact-options!="'+self.$target.data('oe-contact-options')+'"]')
- .add(self.$target)
- .attr('data-oe-many2one-id', self.ID).data('oe-many2one-id', self.ID)
- .each(function () {
- var $node = $(this);
- self.get_contact_rendering($node.data('oe-contact-options'))
- .then(function (html){
- $node.html(html);
- });
- });
- } else {
- self.$target.html($(li).data("name"));
- }
-
- self.clear();
- }
-});
-
-return {
- BuildingBlock: BuildingBlock,
- options: options,
- Option: Option,
- globalSelector: globalSelector,
-};
-
-});
+}); \ No newline at end of file
diff --git a/addons/website/static/src/js/website.theme.js b/addons/website/static/src/js/website.theme.js
index b3dcbc9b0b6..8d5dcc80516 100644
--- a/addons/website/static/src/js/website.theme.js
+++ b/addons/website/static/src/js/website.theme.js
@@ -19,7 +19,7 @@ ajax.jsonRpc('/web/dataset/call', 'call', {
ajax.jsonRpc('/web/dataset/call', 'call', {
'model': 'ir.ui.view',
'method': 'read_template',
- 'args': ['website.colorpicker', website.get_context()]
+ 'args': ['web_editor.colorpicker', website.get_context()]
}).done(function (data) {
QWeb.add_template(data);
});
diff --git a/addons/website/static/src/js/website.tour.rte.js b/addons/website/static/src/js/website.tour.rte.js
deleted file mode 100644
index b068c11f604..00000000000
--- a/addons/website/static/src/js/website.tour.rte.js
+++ /dev/null
@@ -1,340 +0,0 @@
-odoo.define('website.tour.rte', function (require) {
-'use strict';
-
-var core = require('web.core');
-var Tour = require('web.Tour');
-
-var _t = core._t;
-
-var click_event = function(el, type) {
- var evt = document.createEvent("MouseEvents");
- evt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, el);
- el.dispatchEvent(evt);
-};
-
-Tour.register({
- id: 'website_rte',
- name: "Test website RTE",
- path: '/page/homepage',
- mode: 'test',
- steps: [
- {
- element: 'button[data-action=edit]',
- title: "Edit this page",
- wait: 250
- },
- {
- snippet: '#snippet_structure .oe_snippet:has(.s_text_image)',
- title: "Drag & Drop a Text-Image Block",
- },
- {
- element: '.oe_overlay_options:visible .oe_options a:first',
- title: "Customize",
- onload: function () {
- $(".oe_overlay_options:visible .snippet-option-background > ul").show();
- }
- },
- {
- element: '.oe_overlay_options:visible .snippet-option-background > ul li[data-background*="quote"]:first a',
- title: "Chose a background image",
- },
- {
- title: "Change html for this test",
- waitFor: '#wrapwrap > main > div > section:first[style*="background-image"]',
- element: '#wrapwrap > main > div > section .row > div:first',
- onload: function () {
- var $el = $(this.element);
- var html = '<h1 id="text_title_id">Batnae municipium in Anthemusia</h1> '+
- '\n <p>Batnae municipium in Anthemusia conditum Macedonum manu priscorum ab Euphrate flumine brevi spatio disparatur, refertum mercatoribus opulentis, ubi annua sollemnitate prope Septembris initium mensis ad.</p>'+
- '\n <p> Quam <img style="width: 25%" src="/website/static/src/img/text_image.png"/> quidem <span class="fa fa-flag fa-2x"></span> partem accusationis admiratus sum et moleste tuli potissimum esse Atratino datam. Neque enim decebat neque aetas.</p>'+
- '\n <p>Et hanc quidem praeter oppida multa duae civitates exornant Seleucia opus Seleuci regis, et Claudiopolis quam deduxit coloniam Claudius Caesar. Isaura enim antehac nimium potens, olim subversa ut rebellatrix.</p>'+
- '<p>Harum trium sententiarum nulli prorsus assentior.</p>';
- $el.html(html);
- }
- },
- {
- element: '#wrapwrap > main > div > section .row > div:first',
- title: "simulate triple click and change text bg-color",
- onload: function () {
- var $el = $(this.element);
- var $h1 = $('h1', $el);
- $.summernote.core.range.create($h1[0].firstChild, 0, $('p', $el)[0], 0).select();
- click_event($h1[0], 'mouseup');
- }
- },
- {
- waitFor: '#wrapwrap > main > div > section .row > div:first',
- element: '.note-popover button[data-event="color"]:visible',
- title: "change text bg-color after triple click",
- },
- {
- waitFor: '#wrapwrap > main > div > section .row > div:first:not(:has(p font)) h1 font',
- element: '.note-color button.dropdown-toggle:visible',
- title: "change selection to change text color",
- onload: function () {
- var $el = $('#wrapwrap > main > div > section .row > div:first:not(:has(p font)) h1 font');
- $.summernote.core.range.create($el[0].firstChild, 5, $el[0].firstChild, 10).select();
- click_event($el[0], 'mouseup');
- }
- },
- {
- element: 'div[data-target-event="foreColor"]:visible .note-color-row:eq(1) button[data-event="foreColor"]:first',
- title: "change text color",
- },
- {
- waitFor: '#wrapwrap > main > div > section .row > div:first h1 font:eq(2)',
- element: '.note-color button.dropdown-toggle:visible',
- title: "change selection to change text bg-color again",
- onload: function () {
- var $el = $('#wrapwrap > main > div > section .row > div:first h1 font:eq(2)');
- $.summernote.core.range.create($el.prev()[0].firstChild, 3, $el[0].firstChild, 10).select();
- click_event($el.prev()[0], 'mouseup');
- }
- },
- {
- element: 'div[data-target-event="backColor"] .colorpicker button[data-event="backColor"]:first',
- title: "change text backColor again",
- },
- {
- waitFor: '#wrapwrap > main > div > section .row > div:first h1 font:eq(4)',
- element: '.note-color button.dropdown-toggle:visible',
- title: "change selection (h1 and p) to change text color with class",
- onload: function () {
- var $el = $('#wrapwrap > main > div > section .row > div:first h1 font:eq(4)');
- $.summernote.core.range.create($el.prev()[0].firstChild, 3, $el.parent("h1").next("p")[0].firstChild, 30).select();
- click_event($el.prev()[0], 'mouseup');
- }
- },
- {
- element: 'div[data-target-event="foreColor"]:visible button[data-event="foreColor"][data-value^="text-"]:first',
- title: "change text foreColor again",
- },
- {
- waitFor: '#wrapwrap > main > div > section .row > div:first p font',
- element: '.o_editable.note-editable.o_dirty',
- title: "delete selection",
- keydown: 46 // delete
- },
- {
- waitFor: '#wrapwrap > main > div > section .row > div:first:not(:has(p font)) h1',
- element: '.o_editable.note-editable.o_dirty',
- title: "clean and delete (backspace) an other selection",
- onload: function () {
- var $el = $(this.waitFor);
- $.summernote.core.range.createFromNode($el.next("p")[0]).clean();
- $.summernote.core.range.create($el.find('font:containsExact(ici)')[0].firstChild, 1, $el.next().next()[0].firstChild, 5).select();
- click_event($el.find('font:last')[0], 'mouseup');
- },
- keydown: 8 // backspace
- },
- {
- waitFor: '#wrapwrap > main > div > section .row > div:first:has( font:last:containsExact(i) ):has( p:first:containsRegex(/^uam/) ) h1',
- element: '.o_editable.note-editable.o_dirty',
- title: "delete an other selection",
- onload: function () {
- var $el = $(this.waitFor);
- $.summernote.core.range.create($el.find('font:first')[0].firstChild, 3, $el.next("p")[0].childNodes[2], 8).select();
- click_event($el.find('font:first')[0], 'mouseup');
- },
- keydown: 46
- },
- {
- waitFor: '#wrapwrap > main > div > section .row > div:first:has( font:last:containsExact(Bat) )',
- element: '.note-image-popover button[data-event="undo"]',
- title: "undo",
- },
- {
- waitFor: '#wrapwrap > main > div > section .row > div:first:has( font:last:containsExact(i) )',
- element: '.note-air-popover button[data-event="undo"]',
- title: "undo adain",
- },
- {
- waitFor: '#wrapwrap > main > div > section .row > div:first:not(:has(p font)) h1',
- element: '.o_editable.note-editable.o_dirty',
- title: "delete (backspace) after undo",
- keydown: 8 // backspace
- },
- {
- waitFor: '#wrapwrap > main > div > section .row > div:first:has( font:last:containsExact(i) ):has( p:first:containsRegex(/^uam/) )',
- element: '#wrapwrap > main > div > section .row > div:first img[style*="25%"]',
- title: "click on image",
- },
- {
- element: '.note-image-popover:visible button[data-event="resize"][data-value="0.5"]',
- title: "Click on resize half",
- },
- {
- waitFor: '#wrapwrap > main > div > section .row > div:first img[style*="50%"]',
- element: '.note-image-popover:visible button[data-event="showImageDialog"]',
- title: "Click on edit picture",
- },
- {
- waitFor: '.modal #editor-media-image',
- element: '.modal a[data-toggle="tab"]:contains(Pictogram)',
- title: "Click on pictogram tab",
- },
- {
- element: '#editor-media-icon.active span.fa:first',
- title: "select a pictogram",
- },
- {
- waitFor: '#editor-media-icon.active span.font-icons-selected',
- element: '.modal button.save',
- title: "save pictogram",
- },
- {
- element: '.note-image-popover button[data-event="resizefa"][data-value="3"]',
- title: "select a size for the pictogram",
- },
- {
- waitFor: '#wrapwrap span.fa-3x',
- element: '.note-image-popover:visible button[data-event="floatMe"][data-value="right"]',
- title: "click on float right",
- },
- {
- waitFor: '#wrapwrap > main > div > section .row > div:first span.fa.pull-right',
- element: '.note-image-popover:visible button[data-event="showLinkDialog"]',
- title: "click on create link",
- },
- {
- waitFor: '.modal a#link-preview:containsRegex(/^<span [^>]+><\\/span>$/) > span.fa.fa-3x.pull-right',
- element: '.modal .dropdown:has(.link-style) a[data-toggle="dropdown"]',
- title: "click on color style",
- },
- {
- element: '.modal .dropdown ul label.btn-success',
- title: "choose success style",
- },
- {
- waitFor: '.modal a#link-preview.btn:containsRegex(/^<span [^>]+><\\/span>$/)',
- element: '.modal .select2-container.url-source a.select2-choice',
- title: "click to choose an internal page",
- },
- {
- element: '.select2-drop:visible .select2-search input',
- title: "search 'contact'",
- sampleText: "contact",
- },
- {
- element: '.select2-drop:visible .select2-results .select2-result div:contains(/page/)',
- title: "select /page/contactus",
- },
- {
- waitNot: '.select2-drop:visible',
- element: '#link-text',
- title: "change text label",
- sampleText: "ABC[IMG] DEF",
- },
- {
- waitFor: '.modal a#link-preview.btn:containsRegex(/^ABC<span [^>]+><\\/span> DEF$/)',
- element: '.modal button.save',
- title: "save link",
- },
- {
- waitNot: '#link-preview',
- waitFor: 'a.btn[href^="/"]:has(span.fa.fa-3x.pull-right)',
- element: '#wrapwrap > main > div > section .row > div:last img',
- title: "click on other picture",
- },
- {
- waitFor: '#wrapwrap > main > div > section .row > div:first span.fa.pull-right',
- element: '.note-image-popover:visible button[data-event="showLinkDialog"]',
- title: "click on create link again",
- },
- {
- waitFor: '.modal a#link-preview:containsRegex(/^<img [^>]+>$/)',
- element: '.modal .dropdown:has(.link-style) a[data-toggle="dropdown"]',
- title: "click on color style again",
- },
- {
- element: '.modal .dropdown ul label.btn-success',
- title: "choose success style",
- },
- {
- waitFor: '.modal a#link-preview.btn',
- element: '#link-external',
- sampleText: "test@test.test",
- title: "insert an email",
- },
- {
- waitFor: '.modal a#link-preview.btn[href="mailto:test@test.test"]',
- element: '.modal button.save',
- title: "save link",
- },
- {
- waitNot: '#link-preview',
- waitFor: '#wrapwrap > main > div > section .row > div:eq(1) > a > img',
- element: '#wrapwrap > main > div > section .row > div:first p:eq(2)',
- title: "triple enter then double backspace",
- keydown: [66, 13, 66, 13, 13, 8, 8], // B enter B enter enter backspace backspace
- onload: function () {
- var p = $(this.element)[0].firstChild;
- $.summernote.core.range.create(p, p.textContent.length, p, p.textContent.length).select();
- click_event(p, 'mouseup');
- },
- },
- {
- waitNot: '#wrapwrap > main > div > section .row > div:first p:eq(4), #wrapwrap > main > div > section .row > div:eq(3)',
- waitFor: '#wrapwrap > main > div > section .row > div:first p:eq(3)',
- title: "add ul content",
- onload: function () {
- var $el = $('#wrapwrap > main > div > section .row > div:first');
- var html = ' <ul> '+
- '\n <li> <p>Batnae municipium. </p></li>'+
- '\n <li> Seleucia praeter.</li>'+
- '\n <li><p>Et hanc quidem.</p></li>'+
- '\n </ul>';
- $el.append(html);
- var node = $el.find('ul li p:last')[0].firstChild;
- $.summernote.core.range.create(node, 6).select();
- click_event(node, 'mouseup');
- }
- },
- {
- waitFor: '#wrapwrap > main > div > section .row > div:first ul li p:first',
- element: '.note-air-popover .note-style button.dropdown-toggle',
- title: "click on style dropdown",
- },
- {
- element: '.note-air-popover .note-style ul:visible a[data-value="h3"]',
- title: "select h3",
- onload: function () {
- var node = $('#wrapwrap > main > div > section .row > div:first ul li p:last')[0].firstChild;
- $.summernote.core.range.create(node, 0).select();
- click_event(node, 'mouseup');
- }
- },
- {
- element: '#wrapwrap > main > div > section .row > div:first > ul > li > h3',
- title: "double tabulation",
- keydown: [9, 9] // tabulation
- },
- {
- waitFor: '#wrapwrap > main > div > section .row > div:first ul > li > ul > li > ul > li > h3',
- element: '.note-air-popover button[data-event="insertOrderedList"]',
- title: "click on order list",
- },
- {
- waitFor: '#wrapwrap > main > div > section .row > div:first ul > li > ul > li > ol > li > h3',
- element: '#wrapwrap > main > div > section .row > div:first ul li > p:last',
- title: "enter in ul",
- keydown: [66, 13], // enter
- onload: function () {
- $(this.element)[0].firstChild.textContent += "";
- $.summernote.core.range.create($(this.element)[0].firstChild, 7).select();
- click_event($(this.element)[0], 'mouseup');
- }
- },
- {
- element: '#wrapwrap > main > div > section .row > div:first ul li > p:eq(1):containsRegex(/^municipium./)',
- title: "backspace in list",
- keydown: 8
- },
- {
- waitFor: '#wrapwrap > main > div > section .row > div:first ul li p:eq(1)',
- title: "end",
- },
- ]
-});
-
-});
diff --git a/addons/website/static/src/js/website.translator.js b/addons/website/static/src/js/website.translator.js
index 775012e1aa8..cb02f7346e9 100644
--- a/addons/website/static/src/js/website.translator.js
+++ b/addons/website/static/src/js/website.translator.js
@@ -2,229 +2,81 @@ odoo.define('website.translator', function (require) {
'use strict';
var core = require('web.core');
-var editor = require('website.editor');
+var ajax = require('web.ajax');
+var Widget = require('web.Widget');
+var base = require('web_editor.base');
+var translate = require('web_editor.translate');
var website = require('website.website');
-var ajax = require('ajax');
-var QWeb = core.qweb;
+var qweb = core.qweb;
-if (!website.translatable) {
- // Temporary hack until the editor bar is moved to the web client
+if (!translate.translatable) {
return;
}
-website.add_template_file('/website/static/src/xml/website.translator.xml');
-var nodialog = 'website_translator_nodialog';
-
-editor.EditorBar.include({
- do_not_translate : ['-','*','!'],
- start: function () {
- var self = this;
- this.initial_content = {};
- return this._super.apply(this, arguments).then(function () {
- var $edit_button = $("button[data-action=edit]");
- $edit_button.removeClass("hidden");
-
- if(website.no_editor) {
- $edit_button.removeProp('disabled');
- } else {
- $edit_button.parent().after(QWeb.render('website.TranslatorAdditionalButtons'));
- $('a[data-action=edit_master]').on('click', self, function(ev) {
- self.edit_master(ev);
- });
- }
- $('.js_hide_on_translate').hide();
- });
- },
- edit: function () {
- var self = this;
- var mysuper = this._super;
- if (!localStorage[nodialog]) {
- var dialog = new website.TranslatorDialog();
- dialog.appendTo($(document.body));
- dialog.on('activate', this, function () {
- localStorage[nodialog] = dialog.$('input[name=do_not_show]').prop('checked') || '';
- dialog.$el.modal('hide');
- self.translate().then(function () {
- mysuper.call(self, true);
- if(self.gengo_translate){
- self.translation_gengo_display()
- }
- });
- });
+website.TopBar.include({
+ events: _.extend({}, website.TopBar.prototype.events, {
+ 'click [data-action="edit_master"]': 'edit_master',
+ 'click [data-action="translate"]': 'translate',
+ }),
+ translate: function (ev) {
+ ev.preventDefault();
+ if (translate.edit_translations) {
+ translate.instance.edit();
} else {
- this.translate().then(function () {
- mysuper.call(self, true);
- if(self.gengo_translate){
- self.translation_gengo_display()
- }
- });
+ location.search += '&edit_translations';
}
},
edit_master: function (ev) {
ev.preventDefault();
- var link = $('.js_language_selector a[data-default-lang]')[0];
- if (link) {
- link.search += (link.search ? '&' : '?') + 'enable_editor=1';
- var url = link.pathname + link.search + window.location.hash;
- link.pathname = '/website/lang/default';
- link.search = '?' + $.param({r: url});
- window.location = link.href;
- }
+ var $link = $('.js_language_selector a[data-default-lang]');
+ $link[0].search += ($link[0].search ? '&' : '?') + 'enable_editor=1';
+ $link.click();
},
- translate: function () {
- var self = this;
- this.translations = null;
- return ajax.jsonRpc('/website/get_view_translations', 'call', {
- 'xml_id': $(document.documentElement).data('view-xmlid'),
- 'lang': website.get_context().lang,
- }).then(function (translations) {
- self.translations = translations;
- self.processTranslatableNodes();
- // Disable non translatable t-fields
- $('[data-oe-type][data-oe-translate="0"]').removeAttr('data-oe-type');
- });
- },
- processTranslatableNodes: function () {
- var self = this;
- var source_attr = 'data-oe-source-id';
- var $editables = $('[data-oe-model="ir.ui.view"]')
- .not('link, script')
- .not('.oe_snippets,.oe_snippet, .oe_snippet *, .navbar-toggle')
- .not('[data-oe-type]')
- .add($('[data-oe-translate="1"]:not([data-oe-model="ir.ui.view"])').addClass('o_editable'));
+});
- $editables.each(function () {
- var $node = $(this);
- var source_id = $node.parents('[' + source_attr + ']:first').attr(source_attr)|0;
- var view_id = $node.attr('data-oe-source-id') || source_id || $node.attr('data-oe-id');
- self.transNode(this, view_id|0);
- });
- $('.oe_translatable_text').on('paste', function () {
- var node = $(this);
- setTimeout(function () {
- self.sanitizeNode(node);
- }, 0);
- });
- $(document).on('blur keyup paste', '.oe_translatable_text[contenteditable]', function(ev) {
- var $node = $(this);
- setTimeout(function () {
- // Doing stuff next tick because paste and keyup events are
- // fired before the content is changed
- if (ev.type == 'paste') {
- self.sanitizeNode($node[0]);
- }
- if (self.getInitialContent($node[0]) !== $node.text()) {
- $node.addClass('o_dirty').removeClass('oe_translatable_todo oe_translatable_inprogress');
- }
- }, 0);
- });
- },
- getInitialContent: function (node) {
- return this.initial_content[node.attributes['data-oe-nodeid'].value];
- },
- sanitizeNode: function (node) {
- node.text(node.text());
- },
- isTextNode: function (node) {
- return node.nodeType === 3 || node.nodeType === 4;
- },
- isTranslatable: function (text) {
- return text && _.str.trim(text) !== '';
- },
- markTranslatableNode: function (node, view_id) {
- // TODO: link nodes with same content
- node.className += ' oe_translatable_text';
- node.setAttribute('data-oe-translation-view-id', view_id);
- var content = $(node).text().trim();
- var trans = this.translations.filter(function (t) {
- return t.res_id === view_id && t.value.trim() === content;
- });
- if (trans.length) {
- node.setAttribute('data-oe-translation-id', trans[0].id);
- if(trans[0].gengo_translation && (trans[0].state == 'inprogress' || trans[0].state == 'to_translate')){
- node.className += ' oe_translatable_inprogress';
- }
- } else {
- node.className += this.do_not_translate.indexOf(node.textContent.trim()) ? ' oe_translatable_todo' : '';
+
+if (!translate.edit_translations) {
+ return;
+}
+
+ajax.loadXML('/website/static/src/xml/website.translator.xml', qweb);
+
+var nodialog = 'website_translator_nodialog';
+
+var Translate = translate.Class.include({
+ onTranslateReady: function () {
+ if(this.gengo_translate){
+ this.translation_gengo_display();
}
- node.contentEditable = true;
- var nid = _.uniqueId();
- $(node).attr('data-oe-nodeid', nid);
- this.initial_content[nid] = content;
+ this._super();
},
- save: function () {
- var self = this;
- var trans = {};
- // this._super.apply(this, arguments);
- $('.oe_translatable_text.o_dirty').each(function () {
- var $node = $(this);
- var data = $node.data();
- if (!trans[data.oeTranslationViewId]) {
- trans[data.oeTranslationViewId] = [];
+ edit: function () {
+ $("#oe_main_menu_navbar").hide();
+ if (localStorage[nodialog]) {
+ return;
+ }
+ var dialog = new TranslatorDialog();
+ dialog.appendTo($(document.body));
+ dialog.on('activate', this, function () {
+ if (dialog.$('input[name=do_not_show]').prop('checked')) {
+ localStorage.removeItem(nodialog);
+ } else {
+ localStorage.setItem(nodialog, true);
}
- trans[data.oeTranslationViewId].push({
- initial_content: self.getInitialContent(this),
- new_content: $node.text(),
- translation_id: data.oeTranslationId || null
- });
+ dialog.$el.modal('hide');
});
- ajax.jsonRpc('/website/set_translations', 'call', {
- 'data': trans,
- 'lang': website.get_context()['lang'],
- }).then(function () {
- self._save();
- }).fail(function () {
- // TODO: bootstrap alert with error message
- alert("Could not save translation");
- });
- },
- transNode: function (node, view_id) {
- // Mostly handling text and cdata nodes here
- // so avoid jquery usage in this function
- if (node.attributes['data-oe-type']) {
- if (node.attributes['data-oe-translate'].value == '1') {
- node.className += ' oe_translatable_field';
- }
- this.markTranslatableNode(node, view_id);
- } else if (node.childNodes.length === 1
- && this.isTextNode(node.childNodes[0])
- && !node.getAttribute('data-oe-model')) {
- this.markTranslatableNode(node, view_id);
- } else {
- for (var i = 0, l = node.childNodes.length; i < l; i ++) {
- var n = node.childNodes[i];
- if (this.isTextNode(n)) {
- if (this.isTranslatable(n.data)) {
- var container = document.createElement('span');
- node.insertBefore(container, n);
- container.appendChild(n);
- this.markTranslatableNode(container, view_id);
- }
- } else {
- this.transNode(n, view_id);
- }
- }
- }
+ return this._super();
},
-});
-
-website.RTE.include({
- start: function () {
- this._super.apply(this, arguments);
- this.$el.hide();
- },
- fetch_editables: function (root) {
- $(root).click(function (ev) {
- ev.preventDefault();
- });
- return $('[data-oe-translate="1"]');
+ cancel: function () {
+ $("#oe_main_menu_navbar").show();
+ return this._super();
}
});
-website.TranslatorDialog = core.Widget.extend({
- events: _.extend({}, website.EditorBar.prototype.events, {
+var TranslatorDialog = Widget.extend({
+ events: _.extend({}, website.TopBar.prototype.events, {
'hidden.bs.modal': 'destroy',
'click button[data-action=activate]': function (ev) {
this.trigger('activate');
diff --git a/addons/website/static/src/xml/website.backend.xml b/addons/website/static/src/xml/website.backend.xml
index 826e29e261c..5d5f8e4c1ba 100644
--- a/addons/website/static/src/xml/website.backend.xml
+++ b/addons/website/static/src/xml/website.backend.xml
@@ -6,10 +6,4 @@
<span class="o_stat_text oe_publish text-success">Published</span>
</div>
- <t t-name="FieldTextHtmlFrame">
- <div class="oe_form_field oe_form_field_html_frame oe_form_embedded_html" t-att-style="widget.node.attrs.style">
- <iframe/>
- </div>
- </t>
-
</templates>
diff --git a/addons/website/static/src/xml/website.contentMenu.xml b/addons/website/static/src/xml/website.contentMenu.xml
index 2256f4bbf33..d6b1fe40b72 100644
--- a/addons/website/static/src/xml/website.contentMenu.xml
+++ b/addons/website/static/src/xml/website.contentMenu.xml
@@ -23,7 +23,7 @@
</li>
</t>
<t t-name="website.contentMenu.dialog.select">
- <t t-call="website.editor.dialog">
+ <t t-call="web_editor.dialog">
<t t-set="title">Select a Menu</t>
<t t-set="button">Continue</t>
<select class="form-control mb16" t-if="widget.roots">
@@ -34,7 +34,7 @@
</t>
</t>
<t t-name="website.contentMenu.dialog.edit">
- <t t-call="website.editor.dialog">
+ <t t-call="web_editor.dialog">
<t t-set="title">Edit Menu</t>
<select class="form-control mb16" t-if="widget.roots">
<t t-foreach="widget.roots" t-as="root">
@@ -58,7 +58,7 @@
</div>
</t>
</t>
-<t t-name="website.contentMenu.dialog.add" t-extend="website.editor.dialog.link">
+<t t-name="website.contentMenu.dialog.add" t-extend="web_editor.dialog.link">
<t t-jquery="t[t-set='title']" t-operation="inner">
<t t-if="!widget.update_mode">Add Menu Entry</t>
<t t-if="widget.update_mode">Edit Menu Entry</t>
diff --git a/addons/website/static/src/xml/website.editor.xml b/addons/website/static/src/xml/website.editor.xml
index 198336650a4..ce58e3a6c1e 100644
--- a/addons/website/static/src/xml/website.editor.xml
+++ b/addons/website/static/src/xml/website.editor.xml
@@ -1,601 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
- <t t-name="website.editorbar">
- <div id="website-top-navbar" class="navbar navbar-inverse navbar-fixed-top hidden-xs" style="display: none;">
- <div class="navbar-header" id="website-top-edit">
- <ul class="nav navbar-nav js_editor_placeholder" style="position: absolute; left: 180px;">
- </ul>
- <form class="navbar-form text-muted">
- <button type="button" data-action="save"
- class="btn btn-primary btn-xs">Save</button>
- <span>or</span>
- <a href="#" data-action="cancel" class="btn btn-link btn-xs">Discard</a>
- </form>
- </div>
- </div>
- </t>
-
- <t t-name="website.editor.dialog">
- <div class="modal note-link-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"><t t-esc="title"/></h3>
- </div>
- <div class="modal-body"><t t-raw="0"/></div>
- <div class="modal-footer">
- <button type="button" class="btn btn-primary save" t-if="!button">Save</button>
- <button type="button" class="btn btn-primary save" t-if="button"><t t-raw="button"/></button>
- <button type="button" class="btn hidden wait" disabled="disabled"/>
- or
- <a href="#" data-dismiss="modal" aria-hidden="true">Discard</a>
- </div>
- </div>
- </div>
- </div>
- </t>
- <t t-name="website.editor.dialog.link.footer-button">
- <button type="button" class="btn pull-left remove btn-danger">Remove Link</button>
- </t>
- <t t-name="website.editor.dialog.link">
- <t t-call="website.editor.dialog">
- <t t-set="title">Link to</t>
- <form>
- <div class="list-group">
- <div class="form-group list-group-item active">
- <h3 class="list-group-item-heading">
- <label for="link-new" class="control-label">
- Link Label
- </label>
- </h3>
- <input type="text" class="form-control" id="link-text" required="required"/>
- </div>
- </div>
- <ul class="list-group">
- <li class="list-group-item form-group active">
- <h4 class="list-group-item-heading">
- <label for="link-page" class="control-label">
- Page
- </label>
- </h4>
- <input class="page form-control url-source"
- id="link-page" type="hidden"/>
- </li>
- <li class="list-group-item form-group clearfix">
- <div class="pull-right" style="display: none;">
- <label>
- <input type="checkbox" class="window-new"/>
- Open in new window
- </label>
- </div>
- <h4 class="list-group-item-heading">
- <label for="link-external" class="control-label">
- URL or Email Address
- </label>
- </h4>
- <input type="text" class="form-control url email-address url-source"
- id="link-external" placeholder="http://openerp.com"/>
- </li>
- </ul>
- <div class="form-horizontal link-style">
- <div class="form-group">
- <label class="col-sm-2 control-label">
- Style
- </label>
- <div class="col-sm-4">
- <div class="dropdown" style="line-height: 2em;">
- <a data-toggle="dropdown" class="btn btn-default" href="#">Color Style <span class="caret"></span></a>
- <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
- <li>
- <label class="btn btn-link">Link<input value="" class="link-style" type="radio" name="link-style-type" checked="checked"/></label>
- </li>
- <li>
- <label class="btn btn-default">Basic<input value="btn-default" class="link-style" type="radio" name="link-style-type"/></label>
- </li>
- <li>
- <label class="btn btn-success">Success<input value="btn-success" class="link-style" type="radio" name="link-style-type"/></label>
- </li>
- <li>
- <label class="btn btn-primary">Primary<input value="btn-primary" class="link-style" type="radio" name="link-style-type"/></label>
- </li>
- <li>
- <label class="btn btn-info">Info<input value="btn-info" class="link-style" type="radio" name="link-style-type"/></label>
- </li>
- <li>
- <label class="btn btn-warning">Warning<input value="btn-warning" class="link-style" type="radio" name="link-style-type"/></label>
- </li>
- <li>
- <label class="btn btn-danger">Danger<input value="btn-danger" class="link-style" type="radio" name="link-style-type"/></label>
- </li>
- </ul>
- </div>
- </div>
- <div class="col-sm-4">
- <div class="dropdown" style="line-height: 2em;">
- <a data-toggle="dropdown" class="btn btn-default" href="#">Size <span class="caret"></span></a>
- <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
- <li>
- <label class="btn btn-default btn-xs">Extra Small<input value="btn-xs" class="link-style" type="radio" name="link-style-size"/></label>
- </li>
- <li>
- <label class="btn btn-default btn-sm">Small<input value="btn-sm" class="link-style" type="radio" name="link-style-size"/></label>
- </li>
- <li>
- <label class="btn btn-default">Default<input value="" class="link-style" type="radio" name="link-style-size" checked="checked"/></label>
- </li>
- <li>
- <label class="btn btn-default btn-lg">Large<input value="btn-lg" class="link-style" type="radio" name="link-style-size"/></label>
- </li>
- </ul>
- </div>
- </div>
- </div>
- </div>
- <div class="form-horizontal link-style">
- <div class="form-group">
- <label class="col-sm-2 control-label">
- Preview
- </label>
- <div class="col-sm-10" style="line-height: 2em;">
- <div style="overflow: auto; max-width: 100%; max-height: 200px;">
- <a id="link-preview" href="#"></a>
- </div>
- </div>
- </div>
- </div>
- </form>
- </t>
- </t>
- <t t-name="website.editor.dialog.media">
- <div class="modal note-image-dialog" tabindex="-1" role="dialog" aria-hidden="true">
- <div class="modal-dialog select-media">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
- <h3 class="modal-title">Select a Media</h3>
- </div>
- <div class="modal-body">
- <ul class="nav nav-tabs">
- <li class="active"><a href="#editor-media-image" data-toggle="tab">Image</a></li>
- <li><a href="#editor-media-icon" data-toggle="tab">Pictogram</a></li>
- <li><a href="#editor-media-video" data-toggle="tab">Video</a></li>
- <li class="search" style="float: right;">
- <ul class="pager mb0 mt0">
- <li class="previous disabled"><a href="#">← Previous</a></li>
- <li class="next disabled"><a href="#">Next →</a></li>
- </ul>
- </li>
- <li class="search" style="float: right;">
- <form action="#">
- <div class="form-group font-icons fa fa-search mb0">
- <input type="search" class="form-control" id="icon-search"/>
- </div>
- </form>
- </li>
- </ul>
-
- <!-- Tab panes -->
- <div class="tab-content">
- <div class="tab-pane fade in active" id="editor-media-image">
- </div>
- <div class="tab-pane fade" id="editor-media-icon">
- </div>
- <div class="tab-pane fade" id="editor-media-video">
- </div>
- </div>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-primary save">Save</button>
- <button type="button" class="btn hidden wait" disabled="disabled"/>
- or
- <a href="#" data-dismiss="modal" aria-hidden="true">Discard</a>
- </div>
- </div>
- </div>
- </div>
- </t>
- <t t-name="website.editor.dialog.image">
- <div>
- <form method="POST"
- action="/website/attach"
- enctype="multipart/form-data"
- target="fileframe"
- class="form-inline">
- <div class="well">
- <div class="form-group pull-left">
- <input type="file" name="upload" accept="image/*" multiple="multiple" style="position: absolute; opacity: 0; width: 1px; height: 1px;"/>
- <input type="hidden" name="disable_optimization" value=""/>
- <div class="btn-group">
- <button type="button" class="btn btn-primary filepicker">Upload an image from your computer</button>
- <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
- <span class="caret"></span>
- <span class="sr-only">Alternate Upload</span>
- </button>
- <ul class="dropdown-menu" role="menu">
- <li><a href="#" class="js_disable_optimization">Upload image without optimization</a></li>
- </ul>
- </div>
- <button type="button" class="btn hidden wait" disabled="disabled">Uploading...</button>
- </div>
- <div>
- <span class="text-muted"> — or — </span>
- <label for="iamgeurl">Add an image URL</label>
- <div class="form-group btn-group">
- <input type="text" name="url" class="form-control url pull-left" style="width: 320px;" id="iamgeurl" placeholder="http://openerp.com/logo.png"/>
- <button class="btn btn-default" type="submit">Add</button>
- </div>
- </div>
- </div>
- <input type="hidden" name="func"/>
- <div class="help-block"/>
- <div class="existing-attachments">
- <t t-call="website.editor.dialog.image.existing"/>
- </div>
- </form>
- </div>
- <iframe src="about:blank" name="fileframe" class="hidden"/>
- </t>
- <t t-name="website.editor.dialog.image.existing">
- <div class="modal" tabindex="-1" role="dialog" aria-hidden="true">
- <div class="modal-dialog select-image">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
- <h3 class="modal-title">Select a Picture</h3>
- </div>
- <div class="modal-body has-error">
- <div class="existing-attachments"/>
- <div class="help-block"/>
- </div>
- <div class="modal-footer">
- <a href="#" data-dismiss="modal" aria-hidden="true">Discard</a>
- </div>
- </div>
- </div>
- </div>
- </t>
- <t t-name="website.editor.dialog.image.existing.content">
- <div class="existing-attachments">
- <div class="row mt16" t-foreach="rows" t-as="row">
- <div class="col-sm-2 existing-attachment-cell"
- t-foreach="row" t-as="attachment">
- <i class="fa fa-times existing-attachment-remove" t-att-data-id="attachment.id"/>
- <img t-att-src="attachment.website_url" t-att-alt="attachment.name" t-att-title="attachment.name" t-att-data-id="attachment.id" class="img img-responsive"/>
- </div>
- </div>
- </div>
- </t>
- <t t-name="website.editor.dialog.image.existing.error">
- <div class="help-block">
- <p>The image could not be deleted because it is used in the
- following pages or views:</p>
- <ul t-foreach="views" t-as="view">
- <li>
- <a t-attf-href="/web#model=ir.ui.view&amp;id=#{view.id}">
- <t t-esc="view.name"/>
- </a>
- </li>
- </ul>
- </div>
- </t>
- <t t-name="website.editor.table.panel">
- <table class="editorbar-panel">
- <tr t-foreach="rows"><td t-foreach="cols">&#8203;</td></tr>
- </table>
- </t>
- <t t-name="website.editor.table">
- <table class="table table-bordered table-responsive">
- <tbody>
- <tr t-foreach="rows"><td t-foreach="cols">&#8203;</td></tr>
- </tbody>
- </table>
- </t>
-
- <t t-name="website.editor.discard">
- <div class="modal" 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">Discard edition</h3>
- </div>
- <div class="modal-body">
- <p>
- If you discard the current edition, <em>all</em>
- unsaved changes will be lost.
- </p>
- <p>You can cancel to return to the edition mode.</p>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-danger">Discard</button>
- or
- <a href="#" data-dismiss="modal" aria-hidden="true">Cancel</a>
- </div>
- </div>
- </div>
- </div>
- </t>
-
- <t t-name="website.editor.hoverbutton.link">
- <button contentEditable="false" type="button" data-event="showLinkDialog" tabindex="-1" class="btn btn-primary hover-edition-button btn-xs">Change</button>
- </t>
-
- <t t-name="website.editor.hoverbutton.media">
- <div contentEditable="false" class="hover-edition dropdown">
- <a class="btn btn-primary btn-sm" data-toggle="dropdown" href="#">Customize</a>
- <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
- <li><a href="#" class="hover-edition-button">Change Media</a></li>
- <li><a href="#" class="hover-style-button">Style</a></li>
- <li class="dropdown-submenu">
- <a href="#" tabindex="-1">Rotation</a>
- <ul class="dropdown-menu">
- <li data-value="fa-spin"><a>Spin</a></li>
- <li data-value="fa-flip-horizontal"><a>Horizontal flip</a></li>
- <li data-value="fa-flip-vertical"><a>Vertical flip</a></li>
- </ul>
- </li>
- <li><a href="#" data-value="fa-border">border</a></li>
- </ul>
- </div>
- </t>
- <t t-name="website.editor.dialog.alt">
- <t t-call="website.editor.dialog">
- <t t-set="title">Change media Alt and Title</t>
- <form action="#" class="form-horizontal">
- <div class="form-group">
- <label for="alt" class="col-sm-2 control-label">Alt:</label>
- <div class="col-sm-9"><input id="alt" type="text" class="form-control" required="required" t-att-value="widget.alt"/></div>
- </div>
- <div class="form-group">
- <label for="title" class="col-sm-2 control-label">Title:</label>
- <div class="col-sm-9"><input id="title" type="text" class="form-control" required="required" t-att-value="widget.title"/></div>
- </div>
- </form>
+ <t t-extend="web_editor.dialog.link">
+ <t t-jquery=".list-group-item.form-group">
+ this.removeClass('active');
</t>
- </t>
-
- <t t-name="website.editor.dialog.font-icons">
- <form action="#">
- <input type="hidden" id="fa-icon"/>
- <input type="hidden" id="fa-size" value="fa-1x"/>
- <div class="font-icons-icons">
- <t t-call="website.editor.dialog.font-icons.icons">
- <t t-set="iconsParser" t-value="widget.iconsParser"/>
- </t>
- </div>
- </form>
- </t>
- <t t-name="website.editor.dialog.font-icons.icons">
- <t t-foreach="iconsParser" t-as="data">
- <span t-foreach="data.icons" t-as="icon"
- t-attf-class="#{data.base} font-icons-icon #{icon}"
- t-att-data-id="icon"/>
+ <t t-jquery=".list-group-item.form-group:has(#link-external)" t-operation="before">
+ <li class="list-group-item form-group">
+ <h4 class="list-group-item-heading">
+ <label for="link-page" class="control-label">
+ Page
+ </label>
+ </h4>
+ <input class="page form-control url-source" id="link-page" type="hidden"/>
+ </li>
</t>
</t>
- <t t-name="website.editor.dialog.video">
- <form action="#" class="form-inline">
- <div class="well">
- <div class="form-group btn-group">
- <span class="text-muted pull-right" style="margin-left:10px; line-height: 2em;">(Youtube, Vimeo, Dailymotion)</span>
- <label for="urlvideo" style="width: 220px; line-height: 2em;" class="pull-left">Set a video URL</label>
- <input type="text"
- name="url"
- class="form-control url pull-left"
- style="width: 400px;"
- id="urlvideo"
- placeholder="//www.youtube.com/embed/yws1tbgNV7k"
- t-translation="off"/>
- <button class="btn btn-default">Preview</button>
- </div>
- <div class="form-group btn-group">
- <label for="urlvideo" style="width: 220px; line-height: 2em;" class="pull-left"><span class="text-muted">— or —</span> Embed Video (HTML)</label>
- <input type="text"
- name="embed"
- class="form-control url pull-left"
- style="width: 400px;"
- id="embedvideo"
- placeholder='&lt;iframe src="//www.youtube.com/embed/yws1tbgNV7k"&gt;&lt;/iframe&gt;'
- t-translation="off"/>
- <button class="btn btn-default">Preview</button>
- </div>
- </div>
-
- <div id="video-preview" style="width: 450px; margin: 0 auto;">
- <div class="media_iframe_video">
- <div class="media_iframe_video_size"></div>
- <iframe
- src=""
- frameborder="0"
- allowfullscreen="allowfullscreen"></iframe>
- </div>
- </div>
-
- <div class="text-center mt32">
- <div class="checkbox">
- <label><input type="checkbox" id="autoplay"/> Autoplay</label>
- </div>
- </div>
- </form>
- </t>
- <t t-name="website.editor.insert.inline.media">
- <p class="inline-media-link" contenteditable="false">
- <a class="editor-insert-media fa fa-plus-circle"></a>
- </p>
- </t>
- <t t-name="website.editor.tplButton">
- <button type="button" t-att-class="'btn btn-default btn-sm btn-small ' +
- (options.className ? options.className : '') +
- (options.dropdown ? 'dropdown-toggle' : '') "
- t-att-data-toggle= "options.dropdown ? 'dropdown' : ''"
- t-att-title="options.title ? options.title : ''"
- t-att-data-event="options.event ? options.event : ''"
- t-att-data-value="options.value ? options.value : ''"
- t-att-tabindex="-1"><t t-raw="options.sLabel"/>
- <t t-if="options.dropdown">
- <span class="caret"></span>
- </t>
- </button>
- <t t-raw="options.dropdown or ''"/>
- </t>
- <t t-name="website.editor.tplAirPopover">
- <div class="popover bottom in note-air-popover" style="display: none;">
- <div class="arrow"></div>
- <div class="popover-content">
- <t t-foreach="options.airPopover" t-as="group">
- <div t-attf-class="note-#{group[0]} btn-group">
- <t t-foreach="group[1]" t-as="g">
- <t t-call="website.editor.tplButton">
- <t t-set="options" t-value="buttonInfo[g](lang ,options)"/>
- </t>
- </t>
- </div>
- </t>
- </div>
- </div>
- </t>
- <t t-name="website.editor.tplLinkPopover">
- <div class="note-link-popover popover bottom in'" style="display: none;">
- <div class="arrow"></div>
- <div class="popover-content">
- <a href="http://www.google.com" target="_blank">www.google.com</a>
- <div class="note-insert btn-group">
- <button type="button" class="btn btn-default btn-sm btn-small" t-attf-title="#{lang.link.edit}" data-event="showLinkDialog" tabindex="-1">
- <i class="fa fa-pencil-square-o"></i>
- </button>
- <button type="button" class="btn btn-default btn-sm btn-small" t-attf-title="#{lang.link.unlink}" data-event="unlink" tabindex="-1">
- <i class="fa fa-chain-broken"></i>
- </button>
- </div>
- </div>
- </div>
- </t>
- <t t-name="website.editor.tplLinkImagePopover">
- <div class="note-link-image-popover popover bottom in'" style="display: none;">
- <div class="arrow"></div>
- <div class="popover-content">
- <a href="http://www.google.com" target="_blank">www.google.com</a>
- <div class="note-insert btn-group">
- <button type="button" class="btn btn-default btn-sm btn-small" t-attf-title="#{lang.image.image}" data-event="showImageDialog" tabindex="-1">
- <i class="fa fa-picture-o"></i>
- </button>
- </div>
- </div>
- </div>
- </t>
- <t t-name="website.editor.tplImagePopover">
- <div class="note-image-popover popover bottom in'" style="display: none;">
- <div class="arrow"></div>
- <div class="popover-content">
- <a href="http://www.google.com" target="_blank">www.google.com</a>
- <div class="note-insert btn-group">
- <button type="button" class="btn btn-default btn-sm btn-small" t-attf-title="#{lang.image.resizeFull}" data-event="resize" data-value="1" tabindex="-1">
- <span class="note-fontsize-10">100%</span>
- </button>
- <button type="button" class="btn btn-default btn-sm btn-small" t-attf-title="#{lang.image.resizeHalf}" data-event="resize" data-value="0.5" tabindex="-1">
- <span class="note-fontsize-10">50%</span>
- </button>
- <button type="button" class="btn btn-default btn-sm btn-small" t-attf-title="#{lang.image.resizeQuarter}" data-event="resize" data-value="0.25" tabindex="-1">
- <span class="note-fontsize-10">25%</span>
- </button>
- </div>
- <div class="note-insert btn-group">
- <button type="button" class="btn btn-default btn-sm btn-small" t-attf-title="#{lang.image.floatLeft}" data-event="floatMe" data-value="left" tabindex="-1">
- <i class="fa fa-align-left"></i>
- </button>
- <button type="button" class="btn btn-default btn-sm btn-small" t-attf-title="#{lang.image.floatRight}" data-event="floatMe" data-value="right" tabindex="-1">
- <i class="fa fa-align-right"></i>
- </button>
- <button type="button" class="btn btn-default btn-sm btn-small" t-attf-title="#{lang.image.floatNone}" data-event="floatMe" data-value="none" tabindex="-1">
- <i class="fa fa-align-justify"></i>
- </button>
- </div>
- <div class="note-insert btn-group">
- <button type="button" class="btn btn-default btn-sm btn-small" t-attf-title="#{lang.image.remove}" data-event="removeMedia" data-value="none" tabindex="-1">
- <i class="fa fa-trash-o "></i>
- </button>
- </div>
- </div>
- </div>
- </t>
- <t t-name="website.editor.tplPopovers">
- <div class="note-popover">
- <t t-call="website.editor.tplLinkPopover"/>
- <t t-call="website.editor.tplLinkImagePopover"/>
- <t t-call="website.editor.tplImagePopover"/>
- <t t-if="options.airMode">
- <t t-call="website.editor.tplAirPopover"/>
- </t>
- </div>
- </t>
-
- <t t-name="website.editor.tplHandles">
- <div class="note-handle">
- <div class="note-control-selection">
- <div class="note-control-selection-bg"></div>
- <div class="note-control-holder note-control-nw"></div>
- <div class="note-control-holder note-control-ne"></div>
- <div class="note-control-holder note-control-sw"></div>
- <div class="note-control-sizing note-control-se"></div>
- <div class="note-control-selection-info"></div>
- </div>
- </div>
- </t>
- <t t-name="website.editor.table">
- <ul class="dropdown-menu">
- <div class="note-dimension-picker">
- <div class="note-dimension-picker-mousecatcher" data-event="insertTable" data-value="1x1"></div>
- <div class="note-dimension-picker-highlighted"></div>
- <div class="note-dimension-picker-unhighlighted"></div>
- </div>
- <div class="note-dimension-display"> 1 x 1 </div>
- </ul>
- </t>
- <t t-name="website.editor.color">
- <ul class="dropdown-menu">
- <li>
- <div class="btn-group">
- <div class="note-palette-title"><t t-raw="lang.color.background"/></div>
- <div class="note-color-reset" data-event="backColor" data-value="inherit" t-att-title="lang.color.transparent">
- <t t-raw="lang.color.setTransparent"/>
- </div>
- <div class="note-color-palette" data-target-event="backColor"></div>
- </div>
- <div class="btn-group">
- <div class="note-palette-title"><t t-raw="lang.color.foreground"/></div>
- <div class="note-color-reset" data-event="foreColor" data-value="inherit" t-att-title="lang.color.reset">
- <t t-raw="lang.color.resetToDefault"/>
- </div>
- <div class="note-color-palette" data-target-event="foreColor"></div>
- </div>
- </li>
- </ul>
- </t>
- <t t-name="website.editor.paragraph">
- <div class="dropdown-menu">
- <div class="note-align btn-group">
- <t t-call="website.editor.tplButton">
- <t t-set="options" t-value="leftButton"/>
- </t>
- <t t-call="website.editor.tplButton">
- <t t-set="options" t-value="centerButton"/>
- </t>
- <t t-call="website.editor.tplButton">
- <t t-set="options" t-value="rightButton"/>
- </t>
- <t t-call="website.editor.tplButton">
- <t t-set="options" t-value="justifyButton"/>
- </t>
- </div>
- <div class="note-list btn-group">
- <t t-call="website.editor.tplButton">
- <t t-set="options" t-value="indentButton"/>
- </t>
- <t t-call="website.editor.tplButton">
- <t t-set="options" t-value="outdentButton"/>
- </t>
- </div>
- </div>
- </t>
</templates>
diff --git a/addons/website/static/src/xml/website.gallery.xml b/addons/website/static/src/xml/website.gallery.xml
index bf25990a713..21fe07dca4a 100644
--- a/addons/website/static/src/xml/website.gallery.xml
+++ b/addons/website/static/src/xml/website.gallery.xml
@@ -18,7 +18,7 @@
<h4 class="modal-title">Add images</h4>
</div>
<div class="modal-body">
- <form action="/website/attach" method="post" enctype="multipart/form-data" >
+ <form action="/web_editor/attachment/add" method="post" enctype="multipart/form-data" >
<div class="form-group">
<input name="upload" type="file" value="Choose images" multiple="multiple" accept="image/*"/>
</div>
diff --git a/addons/website/static/src/xml/website.snippets.xml b/addons/website/static/src/xml/website.snippets.xml
deleted file mode 100644
index 42a925184fa..00000000000
--- a/addons/website/static/src/xml/website.snippets.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<templates id="template" xml:space="preserve">
-
- <!-- Snippet loader -->
- <t t-name="website.snippets_style">
- <li class="navbar-form">
- <div class="btn-group">
- <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
- Block style <span class="caret"></span>
- </button>
- <ul class="dropdown-menu" id="oe_snippets_style" role="menu"></ul>
- </div>
- </li>
- </t>
-
- <t t-name="website.snippets">
- <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>
-
- <t t-name="website.snippet_overlay">
- <div class="oe_overlay">
- <div class="oe_overlay_options" contentEditable="false">
- <div class="btn-group">
- <a href="#" class="btn btn-default btn-sm oe_snippet_parent" title="Select Container Block"><i class="fa fa-upload"></i></a>
- <div class="dropdown oe_options hidden btn-group">
- <a href="#" data-toggle="dropdown" class="btn btn-primary btn-sm" title="Customize">Customize <span class="caret"/></a>
- <ul class="dropdown-menu" role="menu"></ul>
- </div>
- <a href="#" class="btn btn-default btn-sm oe_snippet_move" title="Drag to Move">&amp;nbsp;<i class="fa fa-arrows"></i>&amp;nbsp;</a>
- <a href="#" class="btn btn-default btn-sm oe_snippet_clone" title="Duplicate Container">&amp;nbsp;<i class="fa fa-files-o"></i>&amp;nbsp; </a>
- <a href="#" class="btn btn-default btn-sm oe_snippet_remove" title="Remove Block">&amp;nbsp;<i class="fa fa-trash-o"></i>&amp;nbsp; </a>
- </div>
- </div>
- <div class='oe_handles'>
- <div class='oe_handle n readonly'><div></div></div>
- <div class='oe_handle e readonly'><div></div></div>
- <div class='oe_handle w readonly'><div></div></div>
- <div class='oe_handle size readonly'>
- <div class="oe_handle_button auto_size">Auto Resize</div>
- <div class="oe_handle_button size">Resize</div>
- </div>
- <div class='oe_handle s readonly'><div></div></div>
- </div>
- </div>
- </t>
-
- <t t-name="website.snippet_manipulator">
- <div class='oe_snippet_manipulator'></div>
- </t>
-
- <!-- t-field options -->
-
- <t t-name="website.many2one.button">
- <div class="dropdown">
- <a href="#" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown" data-hover="dropdown" title="Search Contact"><i class="fa fa-search"></i></a>
- <ul class="dropdown-menu contact_menu" role="menu">
- <li><a><input href="#" type="email" placeholder="Search"/></a></li>
- </ul>
- </div>
- </t>
-
- <t t-name="website.many2one.search">
- <t t-foreach="contacts" t-as="item">
- <li><a href="#" t-att-data-id="item.id" t-att-data-name="item.display_name"><t t-esc="item.display_name"/> <t t-if="item.city or item.country_id"><small class="text-muted">(<t t-esc="item.city"/> <t t-esc="item.country_id and item.country_id[1]"/>)</small></t></a></li>
- </t>
- </t>
-</templates>
diff --git a/addons/website/static/src/xml/website.translator.xml b/addons/website/static/src/xml/website.translator.xml
index 0019f8d9d3a..8e9c9564f08 100644
--- a/addons/website/static/src/xml/website.translator.xml
+++ b/addons/website/static/src/xml/website.translator.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<templates id="template" xml:space="preserve">
+
<t t-name="website.TranslatorAdditionalButtons">
<li><a class="btn btn-link" data-action="edit_master" href="#"> or Edit Master</a></li>
</t>
+
<t t-name="website.TranslatorDialog">
<div class="modal fade oe_website_translator" tabindex="-1" role="dialog">
<div class="modal-dialog">
@@ -19,10 +21,10 @@
<p>
Here are the visuals used to help you translate efficiently:
<ul class="oe_translate_examples">
- <li class="oe_translatable_todo">
+ <li data-oe-translation-state="to_translate">
Content to translate
</li>
- <li class="oe_translatable_text">
+ <li data-oe-translation-state="translated">
Translated content
</li>
</ul>
@@ -37,7 +39,7 @@
</section>
</div>
<div class="modal-footer">
- <div class="pull-right">
+ <div class="pull-left">
<input type="checkbox" name="do_not_show"/>
Do not show this dialog later.
</div>