[MERGE] from trunk
bzr revid: xmo@openerp.com-20130913125230-38lb4jv8ypt6y9dh
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
ace.define("ace/theme/monokai",["require","exports","module","ace/lib/dom"],function(e,t,n){t.isDark=!0,t.cssClass="ace-monokai",t.cssText=".ace-monokai .ace_gutter {background: #2F3129;color: #8F908A}.ace-monokai .ace_print-margin {width: 1px;background: #555651}.ace-monokai {background-color: #272822;color: #F8F8F2}.ace-monokai .ace_cursor {border-left: 2px solid #F8F8F0}.ace-monokai .ace_overwrite-cursors .ace_cursor {border-left: 0px;border-bottom: 1px solid #F8F8F0}.ace-monokai .ace_marker-layer .ace_selection {background: #49483E}.ace-monokai.ace_multiselect .ace_selection.ace_start {box-shadow: 0 0 3px 0px #272822;border-radius: 2px}.ace-monokai .ace_marker-layer .ace_step {background: rgb(102, 82, 0)}.ace-monokai .ace_marker-layer .ace_bracket {margin: -1px 0 0 -1px;border: 1px solid #49483E}.ace-monokai .ace_marker-layer .ace_active-line {background: #202020}.ace-monokai .ace_gutter-active-line {background-color: #272727}.ace-monokai .ace_marker-layer .ace_selected-word {border: 1px solid #49483E}.ace-monokai .ace_invisible {color: #52524d}.ace-monokai .ace_entity.ace_name.ace_tag,.ace-monokai .ace_keyword,.ace-monokai .ace_meta.ace_tag,.ace-monokai .ace_storage {color: #F92672}.ace-monokai .ace_constant.ace_character,.ace-monokai .ace_constant.ace_language,.ace-monokai .ace_constant.ace_numeric,.ace-monokai .ace_constant.ace_other {color: #AE81FF}.ace-monokai .ace_invalid {color: #F8F8F0;background-color: #F92672}.ace-monokai .ace_invalid.ace_deprecated {color: #F8F8F0;background-color: #AE81FF}.ace-monokai .ace_support.ace_constant,.ace-monokai .ace_support.ace_function {color: #66D9EF}.ace-monokai .ace_fold {background-color: #A6E22E;border-color: #F8F8F2}.ace-monokai .ace_storage.ace_type,.ace-monokai .ace_support.ace_class,.ace-monokai .ace_support.ace_type {font-style: italic;color: #66D9EF}.ace-monokai .ace_entity.ace_name.ace_function,.ace-monokai .ace_entity.ace_other,.ace-monokai .ace_entity.ace_other.ace_attribute-name,.ace-monokai .ace_variable {color: #A6E22E}.ace-monokai .ace_variable.ace_parameter {font-style: italic;color: #FD971F}.ace-monokai .ace_string {color: #E6DB74}.ace-monokai .ace_comment {color: #75715E}.ace-monokai .ace_markup.ace_underline {text-decoration: underline}.ace-monokai .ace_indent-guide {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0FD0ZXBzd/wPAAjVAoxeSgNeAAAAAElFTkSuQmCC) right repeat-y;}";var r=e("../lib/dom");r.importCssString(t.cssText,t.cssClass)})
|
||||
@@ -0,0 +1,358 @@
|
||||
/**
|
||||
* vkBeautify - javascript plugin to pretty-print or minify text in XML, JSON, CSS and SQL formats.
|
||||
*
|
||||
* Version - 0.99.00.beta
|
||||
* Copyright (c) 2012 Vadim Kiryukhin
|
||||
* vkiryukhin @ gmail.com
|
||||
* http://www.eslinstructor.net/vkbeautify/
|
||||
*
|
||||
* Dual licensed under the MIT and GPL licenses:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* Pretty print
|
||||
*
|
||||
* vkbeautify.xml(text [,indent_pattern]);
|
||||
* vkbeautify.json(text [,indent_pattern]);
|
||||
* vkbeautify.css(text [,indent_pattern]);
|
||||
* vkbeautify.sql(text [,indent_pattern]);
|
||||
*
|
||||
* @text - String; text to beatufy;
|
||||
* @indent_pattern - Integer | String;
|
||||
* Integer: number of white spaces;
|
||||
* String: character string to visualize indentation ( can also be a set of white spaces )
|
||||
* Minify
|
||||
*
|
||||
* vkbeautify.xmlmin(text [,preserve_comments]);
|
||||
* vkbeautify.jsonmin(text);
|
||||
* vkbeautify.cssmin(text [,preserve_comments]);
|
||||
* vkbeautify.sqlmin(text);
|
||||
*
|
||||
* @text - String; text to minify;
|
||||
* @preserve_comments - Bool; [optional];
|
||||
* Set this flag to true to prevent removing comments from @text ( minxml and mincss functions only. )
|
||||
*
|
||||
* Examples:
|
||||
* vkbeautify.xml(text); // pretty print XML
|
||||
* vkbeautify.json(text, 4 ); // pretty print JSON
|
||||
* vkbeautify.css(text, '. . . .'); // pretty print CSS
|
||||
* vkbeautify.sql(text, '----'); // pretty print SQL
|
||||
*
|
||||
* vkbeautify.xmlmin(text, true);// minify XML, preserve comments
|
||||
* vkbeautify.jsonmin(text);// minify JSON
|
||||
* vkbeautify.cssmin(text);// minify CSS, remove comments ( default )
|
||||
* vkbeautify.sqlmin(text);// minify SQL
|
||||
*
|
||||
*/
|
||||
|
||||
(function() {
|
||||
|
||||
function createShiftArr(step) {
|
||||
|
||||
var space = ' ';
|
||||
|
||||
if ( isNaN(parseInt(step)) ) { // argument is string
|
||||
space = step;
|
||||
} else { // argument is integer
|
||||
switch(step) {
|
||||
case 1: space = ' '; break;
|
||||
case 2: space = ' '; break;
|
||||
case 3: space = ' '; break;
|
||||
case 4: space = ' '; break;
|
||||
case 5: space = ' '; break;
|
||||
case 6: space = ' '; break;
|
||||
case 7: space = ' '; break;
|
||||
case 8: space = ' '; break;
|
||||
case 9: space = ' '; break;
|
||||
case 10: space = ' '; break;
|
||||
case 11: space = ' '; break;
|
||||
case 12: space = ' '; break;
|
||||
}
|
||||
}
|
||||
|
||||
var shift = ['\n']; // array of shifts
|
||||
for(ix=0;ix<100;ix++){
|
||||
shift.push(shift[ix]+space);
|
||||
}
|
||||
return shift;
|
||||
}
|
||||
|
||||
function vkbeautify(){
|
||||
this.step = ' '; // 4 spaces
|
||||
this.shift = createShiftArr(this.step);
|
||||
};
|
||||
|
||||
vkbeautify.prototype.xml = function(text,step) {
|
||||
|
||||
var ar = text.replace(/>\s{0,}</g,"><")
|
||||
.replace(/</g,"~::~<")
|
||||
.replace(/\s*xmlns\:/g,"~::~xmlns:")
|
||||
.replace(/\s*xmlns\=/g,"~::~xmlns=")
|
||||
.split('~::~'),
|
||||
len = ar.length,
|
||||
inComment = false,
|
||||
deep = 0,
|
||||
str = '',
|
||||
ix = 0,
|
||||
shift = step ? createShiftArr(step) : this.shift;
|
||||
|
||||
for(ix=0;ix<len;ix++) {
|
||||
// start comment or <![CDATA[...]]> or <!DOCTYPE //
|
||||
if(ar[ix].search(/<!/) > -1) {
|
||||
str += shift[deep]+ar[ix];
|
||||
inComment = true;
|
||||
// end comment or <![CDATA[...]]> //
|
||||
if(ar[ix].search(/-->/) > -1 || ar[ix].search(/\]>/) > -1 || ar[ix].search(/!DOCTYPE/) > -1 ) {
|
||||
inComment = false;
|
||||
}
|
||||
} else
|
||||
// end comment or <![CDATA[...]]> //
|
||||
if(ar[ix].search(/-->/) > -1 || ar[ix].search(/\]>/) > -1) {
|
||||
str += ar[ix];
|
||||
inComment = false;
|
||||
} else
|
||||
// <elm></elm> //
|
||||
if( /^<\w/.exec(ar[ix-1]) && /^<\/\w/.exec(ar[ix]) &&
|
||||
/^<[\w:\-\.\,]+/.exec(ar[ix-1]) == /^<\/[\w:\-\.\,]+/.exec(ar[ix])[0].replace('/','')) {
|
||||
str += ar[ix];
|
||||
if(!inComment) deep--;
|
||||
} else
|
||||
// <elm> //
|
||||
if(ar[ix].search(/<\w/) > -1 && ar[ix].search(/<\//) == -1 && ar[ix].search(/\/>/) == -1 ) {
|
||||
str = !inComment ? str += shift[deep++]+ar[ix] : str += ar[ix];
|
||||
} else
|
||||
// <elm>...</elm> //
|
||||
if(ar[ix].search(/<\w/) > -1 && ar[ix].search(/<\//) > -1) {
|
||||
str = !inComment ? str += shift[deep]+ar[ix] : str += ar[ix];
|
||||
} else
|
||||
// </elm> //
|
||||
if(ar[ix].search(/<\//) > -1) {
|
||||
str = !inComment ? str += shift[--deep]+ar[ix] : str += ar[ix];
|
||||
} else
|
||||
// <elm/> //
|
||||
if(ar[ix].search(/\/>/) > -1 ) {
|
||||
str = !inComment ? str += shift[deep]+ar[ix] : str += ar[ix];
|
||||
} else
|
||||
// <? xml ... ?> //
|
||||
if(ar[ix].search(/<\?/) > -1) {
|
||||
str += shift[deep]+ar[ix];
|
||||
} else
|
||||
// xmlns //
|
||||
if( ar[ix].search(/xmlns\:/) > -1 || ar[ix].search(/xmlns\=/) > -1) {
|
||||
str += shift[deep]+ar[ix];
|
||||
}
|
||||
|
||||
else {
|
||||
str += ar[ix];
|
||||
}
|
||||
}
|
||||
|
||||
return (str[0] == '\n') ? str.slice(1) : str;
|
||||
}
|
||||
|
||||
vkbeautify.prototype.json = function(text,step) {
|
||||
|
||||
var step = step ? step : this.step;
|
||||
|
||||
if (typeof JSON === 'undefined' ) return text;
|
||||
|
||||
if ( typeof text === "string" ) return JSON.stringify(JSON.parse(text), null, step);
|
||||
if ( typeof text === "object" ) return JSON.stringify(text, null, step);
|
||||
|
||||
return text; // text is not string nor object
|
||||
}
|
||||
|
||||
vkbeautify.prototype.css = function(text, step) {
|
||||
|
||||
var ar = text.replace(/\s{1,}/g,' ')
|
||||
.replace(/\{/g,"{~::~")
|
||||
.replace(/\}/g,"~::~}~::~")
|
||||
.replace(/\;/g,";~::~")
|
||||
.replace(/\/\*/g,"~::~/*")
|
||||
.replace(/\*\//g,"*/~::~")
|
||||
.replace(/~::~\s{0,}~::~/g,"~::~")
|
||||
.split('~::~'),
|
||||
len = ar.length,
|
||||
deep = 0,
|
||||
str = '',
|
||||
ix = 0,
|
||||
shift = step ? createShiftArr(step) : this.shift;
|
||||
|
||||
for(ix=0;ix<len;ix++) {
|
||||
|
||||
if( /\{/.exec(ar[ix])) {
|
||||
str += shift[deep++]+ar[ix];
|
||||
} else
|
||||
if( /\}/.exec(ar[ix])) {
|
||||
str += shift[--deep]+ar[ix];
|
||||
} else
|
||||
if( /\*\\/.exec(ar[ix])) {
|
||||
str += shift[deep]+ar[ix];
|
||||
}
|
||||
else {
|
||||
str += shift[deep]+ar[ix];
|
||||
}
|
||||
}
|
||||
return str.replace(/^\n{1,}/,'');
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
function isSubquery(str, parenthesisLevel) {
|
||||
return parenthesisLevel - (str.replace(/\(/g,'').length - str.replace(/\)/g,'').length )
|
||||
}
|
||||
|
||||
function split_sql(str, tab) {
|
||||
|
||||
return str.replace(/\s{1,}/g," ")
|
||||
|
||||
.replace(/ AND /ig,"~::~"+tab+tab+"AND ")
|
||||
.replace(/ BETWEEN /ig,"~::~"+tab+"BETWEEN ")
|
||||
.replace(/ CASE /ig,"~::~"+tab+"CASE ")
|
||||
.replace(/ ELSE /ig,"~::~"+tab+"ELSE ")
|
||||
.replace(/ END /ig,"~::~"+tab+"END ")
|
||||
.replace(/ FROM /ig,"~::~FROM ")
|
||||
.replace(/ GROUP\s{1,}BY/ig,"~::~GROUP BY ")
|
||||
.replace(/ HAVING /ig,"~::~HAVING ")
|
||||
//.replace(/ SET /ig," SET~::~")
|
||||
.replace(/ IN /ig," IN ")
|
||||
|
||||
.replace(/ JOIN /ig,"~::~JOIN ")
|
||||
.replace(/ CROSS~::~{1,}JOIN /ig,"~::~CROSS JOIN ")
|
||||
.replace(/ INNER~::~{1,}JOIN /ig,"~::~INNER JOIN ")
|
||||
.replace(/ LEFT~::~{1,}JOIN /ig,"~::~LEFT JOIN ")
|
||||
.replace(/ RIGHT~::~{1,}JOIN /ig,"~::~RIGHT JOIN ")
|
||||
|
||||
.replace(/ ON /ig,"~::~"+tab+"ON ")
|
||||
.replace(/ OR /ig,"~::~"+tab+tab+"OR ")
|
||||
.replace(/ ORDER\s{1,}BY/ig,"~::~ORDER BY ")
|
||||
.replace(/ OVER /ig,"~::~"+tab+"OVER ")
|
||||
|
||||
.replace(/\(\s{0,}SELECT /ig,"~::~(SELECT ")
|
||||
.replace(/\)\s{0,}SELECT /ig,")~::~SELECT ")
|
||||
|
||||
.replace(/ THEN /ig," THEN~::~"+tab+"")
|
||||
.replace(/ UNION /ig,"~::~UNION~::~")
|
||||
.replace(/ USING /ig,"~::~USING ")
|
||||
.replace(/ WHEN /ig,"~::~"+tab+"WHEN ")
|
||||
.replace(/ WHERE /ig,"~::~WHERE ")
|
||||
.replace(/ WITH /ig,"~::~WITH ")
|
||||
|
||||
//.replace(/\,\s{0,}\(/ig,",~::~( ")
|
||||
//.replace(/\,/ig,",~::~"+tab+tab+"")
|
||||
|
||||
.replace(/ ALL /ig," ALL ")
|
||||
.replace(/ AS /ig," AS ")
|
||||
.replace(/ ASC /ig," ASC ")
|
||||
.replace(/ DESC /ig," DESC ")
|
||||
.replace(/ DISTINCT /ig," DISTINCT ")
|
||||
.replace(/ EXISTS /ig," EXISTS ")
|
||||
.replace(/ NOT /ig," NOT ")
|
||||
.replace(/ NULL /ig," NULL ")
|
||||
.replace(/ LIKE /ig," LIKE ")
|
||||
.replace(/\s{0,}SELECT /ig,"SELECT ")
|
||||
.replace(/\s{0,}UPDATE /ig,"UPDATE ")
|
||||
.replace(/ SET /ig," SET ")
|
||||
|
||||
.replace(/~::~{1,}/g,"~::~")
|
||||
.split('~::~');
|
||||
}
|
||||
|
||||
vkbeautify.prototype.sql = function(text,step) {
|
||||
|
||||
var ar_by_quote = text.replace(/\s{1,}/g," ")
|
||||
.replace(/\'/ig,"~::~\'")
|
||||
.split('~::~'),
|
||||
len = ar_by_quote.length,
|
||||
ar = [],
|
||||
deep = 0,
|
||||
tab = this.step,//+this.step,
|
||||
inComment = true,
|
||||
inQuote = false,
|
||||
parenthesisLevel = 0,
|
||||
str = '',
|
||||
ix = 0,
|
||||
shift = step ? createShiftArr(step) : this.shift;;
|
||||
|
||||
for(ix=0;ix<len;ix++) {
|
||||
if(ix%2) {
|
||||
ar = ar.concat(ar_by_quote[ix]);
|
||||
} else {
|
||||
ar = ar.concat(split_sql(ar_by_quote[ix], tab) );
|
||||
}
|
||||
}
|
||||
|
||||
len = ar.length;
|
||||
for(ix=0;ix<len;ix++) {
|
||||
|
||||
parenthesisLevel = isSubquery(ar[ix], parenthesisLevel);
|
||||
|
||||
if( /\s{0,}\s{0,}SELECT\s{0,}/.exec(ar[ix])) {
|
||||
ar[ix] = ar[ix].replace(/\,/g,",\n"+tab+tab+"")
|
||||
}
|
||||
|
||||
if( /\s{0,}\s{0,}SET\s{0,}/.exec(ar[ix])) {
|
||||
ar[ix] = ar[ix].replace(/\,/g,",\n"+tab+tab+"")
|
||||
}
|
||||
|
||||
if( /\s{0,}\(\s{0,}SELECT\s{0,}/.exec(ar[ix])) {
|
||||
deep++;
|
||||
str += shift[deep]+ar[ix];
|
||||
} else
|
||||
if( /\'/.exec(ar[ix]) ) {
|
||||
if(parenthesisLevel<1 && deep) {
|
||||
deep--;
|
||||
}
|
||||
str += ar[ix];
|
||||
}
|
||||
else {
|
||||
str += shift[deep]+ar[ix];
|
||||
if(parenthesisLevel<1 && deep) {
|
||||
deep--;
|
||||
}
|
||||
}
|
||||
var junk = 0;
|
||||
}
|
||||
|
||||
str = str.replace(/^\n{1,}/,'').replace(/\n{1,}/g,"\n");
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
vkbeautify.prototype.xmlmin = function(text, preserveComments) {
|
||||
|
||||
var str = preserveComments ? text
|
||||
: text.replace(/\<![ \r\n\t]*(--([^\-]|[\r\n]|-[^\-])*--[ \r\n\t]*)\>/g,"")
|
||||
.replace(/[ \r\n\t]{1,}xmlns/g, ' xmlns');
|
||||
return str.replace(/>\s{0,}</g,"><");
|
||||
}
|
||||
|
||||
vkbeautify.prototype.jsonmin = function(text) {
|
||||
|
||||
if (typeof JSON === 'undefined' ) return text;
|
||||
|
||||
return JSON.stringify(JSON.parse(text), null, 0);
|
||||
|
||||
}
|
||||
|
||||
vkbeautify.prototype.cssmin = function(text, preserveComments) {
|
||||
|
||||
var str = preserveComments ? text
|
||||
: text.replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\//g,"") ;
|
||||
|
||||
return str.replace(/\s{1,}/g,' ')
|
||||
.replace(/\{\s{1,}/g,"{")
|
||||
.replace(/\}\s{1,}/g,"}")
|
||||
.replace(/\;\s{1,}/g,";")
|
||||
.replace(/\/\*\s{1,}/g,"/*")
|
||||
.replace(/\*\/\s{1,}/g,"*/");
|
||||
}
|
||||
|
||||
vkbeautify.prototype.sqlmin = function(text) {
|
||||
return text.replace(/\s{1,}/g," ").replace(/\s{1,}\(/,"(").replace(/\s{1,}\)/,")");
|
||||
}
|
||||
|
||||
window.vkbeautify = new vkbeautify();
|
||||
|
||||
})();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
@charset "utf-8";
|
||||
/* ---- CKEditor Minimal Reset ---- */
|
||||
.navbar.navbar-inverse .cke_chrome {
|
||||
border: none;
|
||||
@@ -24,7 +25,7 @@
|
||||
width: 100%;
|
||||
padding: 2px;
|
||||
margin: 0;
|
||||
z-index: 10000;
|
||||
z-index: 20000;
|
||||
background-color: #414141;
|
||||
background: -webkit-linear-gradient(#646060, #262626);
|
||||
box-sizing: border-box;
|
||||
@@ -82,10 +83,6 @@
|
||||
}
|
||||
|
||||
/* ---- EDITOR BAR ---- */
|
||||
.modal .tab-content {
|
||||
padding-top: 5px;
|
||||
}
|
||||
|
||||
table.editorbar-panel {
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
@@ -94,10 +91,6 @@ table.editorbar-panel td.selected {
|
||||
background-color: #b1c9d9;
|
||||
}
|
||||
|
||||
.modal .image-preview-container, .modal .image-preview {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
/* ---- RTE ---- */
|
||||
.oe_editable .btn {
|
||||
-webkit-user-select: auto;
|
||||
@@ -118,7 +111,7 @@ table.editorbar-panel td.selected {
|
||||
background: #282828;
|
||||
box-shadow: 0px 10px 10px -10px black inset;
|
||||
overflow-y: auto;
|
||||
z-index: 100;
|
||||
z-index: 20000;
|
||||
}
|
||||
#oe_snippets .nav-pills {
|
||||
padding: 3px 8px;
|
||||
@@ -179,6 +172,11 @@ table.editorbar-panel td.selected {
|
||||
height: 32px;
|
||||
margin: -16px 0px;
|
||||
-webkit-transition: margin 250ms linear;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
position: absolute;
|
||||
background: rgba(153, 0, 255, 0.17);
|
||||
border-radius: 3px;
|
||||
}
|
||||
.oe_drop_zone.oe_insert:first-child:not(:last-child) {
|
||||
margin-top: -8px;
|
||||
@@ -204,11 +202,11 @@ table.editorbar-panel td.selected {
|
||||
.oe_drop_zone.oe_insert.oe_hover:before {
|
||||
border-top: dashed 2px rgba(116, 255, 161, 0.72);
|
||||
}
|
||||
|
||||
.oe_drop_zone.oe_overlay {
|
||||
.oe_drop_zone.oe_insert.oe_vertical {
|
||||
width: 16px;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
background: rgba(153, 0, 255, 0.17);
|
||||
border-radius: 3px;
|
||||
margin: 0px !important;
|
||||
}
|
||||
|
||||
.oe_drop_zone {
|
||||
@@ -217,7 +215,7 @@ table.editorbar-panel td.selected {
|
||||
}
|
||||
.oe_drop_zone.oe_hover {
|
||||
background: rgba(0, 255, 133, 0.22);
|
||||
z-index: 97;
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
/* ---- SNIPPET MANIPULATOR ---- */
|
||||
@@ -231,9 +229,6 @@ table.editorbar-panel td.selected {
|
||||
box-sizing: border-box;
|
||||
pointer-events: none;
|
||||
}
|
||||
.oe_overlay .oe_handle {
|
||||
display: none !important;
|
||||
}
|
||||
.oe_overlay.oe_hover {
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
@@ -248,6 +243,9 @@ table.editorbar-panel td.selected {
|
||||
.oe_overlay.oe_selected {
|
||||
border-color: rgba(0, 153, 255, 0.5);
|
||||
}
|
||||
.oe_overlay .oe_handle {
|
||||
display: none !important;
|
||||
}
|
||||
.oe_overlay.oe_active {
|
||||
border-color: rgba(153, 0, 255, 0.5);
|
||||
}
|
||||
@@ -255,25 +253,40 @@ table.editorbar-panel td.selected {
|
||||
display: block !important;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.oe_overlay .icon.btn {
|
||||
display: inline-block;
|
||||
}
|
||||
.oe_overlay .oe_overlay_options {
|
||||
display: none;
|
||||
z-index: 99;
|
||||
z-index: 1002;
|
||||
}
|
||||
.oe_overlay .oe_overlay_options .oe_option {
|
||||
pointer-events: auto;
|
||||
.oe_overlay .oe_overlay_options .oe_options, .oe_overlay .oe_overlay_options .oe_label, .oe_overlay .oe_overlay_options .oe_move {
|
||||
position: absolute;
|
||||
display: block;
|
||||
z-index: 1002;
|
||||
top: -11px;
|
||||
}
|
||||
.oe_overlay .oe_overlay_options .oe_option.n {
|
||||
top: 0px;
|
||||
.oe_overlay .oe_overlay_options .oe_options {
|
||||
pointer-events: auto;
|
||||
left: -14px;
|
||||
}
|
||||
.oe_overlay .oe_overlay_options .oe_option.e {
|
||||
right: 0px;
|
||||
.oe_overlay .oe_overlay_options .oe_label {
|
||||
top: -8px;
|
||||
right: 6px;
|
||||
background: white;
|
||||
font-size: 75%;
|
||||
color: rgba(153, 0, 255, 0.5);
|
||||
padding: 0 5px;
|
||||
}
|
||||
.oe_overlay .oe_overlay_options .oe_option.s {
|
||||
bottom: 0px;
|
||||
.oe_overlay .oe_overlay_options .oe_move {
|
||||
pointer-events: auto;
|
||||
left: 50%;
|
||||
}
|
||||
.oe_overlay .oe_overlay_options .oe_option.w {
|
||||
left: 0px;
|
||||
.oe_overlay .oe_overlay_options .oe_move .js_box_move {
|
||||
margin-left: -50%;
|
||||
}
|
||||
.oe_overlay .oe_overlay_options .dropdown-menu select, .oe_overlay .oe_overlay_options .dropdown-menu input {
|
||||
display: block;
|
||||
}
|
||||
.oe_overlay.oe_active .oe_overlay_options {
|
||||
display: block;
|
||||
@@ -337,6 +350,10 @@ table.editorbar-panel td.selected {
|
||||
cursor: w-resize !important;
|
||||
}
|
||||
|
||||
.move-important, .move-important * {
|
||||
cursor: move !important;
|
||||
}
|
||||
|
||||
/* ---- MOBILE PREVIEW ---- */
|
||||
.oe_mobile_preview.modal .modal-content {
|
||||
height: 660px;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
width: 100%
|
||||
padding: 2px
|
||||
margin: 0
|
||||
z-index: 10000
|
||||
z-index: 20000
|
||||
background-color: #414141
|
||||
background: -webkit-linear-gradient(#646060, #262626)
|
||||
box-sizing: border-box
|
||||
@@ -74,18 +74,12 @@
|
||||
|
||||
/* ---- EDITOR BAR ---- */
|
||||
|
||||
.modal .tab-content
|
||||
padding-top: 5px
|
||||
|
||||
table.editorbar-panel
|
||||
cursor: pointer
|
||||
width: 100%
|
||||
td.selected
|
||||
background-color: #b1c9d9
|
||||
|
||||
.modal .image-preview-container, .modal .image-preview
|
||||
margin-bottom: 0.5em
|
||||
|
||||
/* ---- RTE ---- */
|
||||
|
||||
// bootstrap makes .btn elements unselectable -> RTE double-click can't know
|
||||
@@ -109,7 +103,7 @@ table.editorbar-panel
|
||||
background: rgb(40,40,40)
|
||||
box-shadow: 0px 10px 10px -10px black inset
|
||||
overflow-y: auto
|
||||
z-index: 100
|
||||
z-index: 20000
|
||||
.nav-pills
|
||||
padding: 3px 8px
|
||||
background: #444444
|
||||
@@ -166,6 +160,8 @@ table.editorbar-panel
|
||||
height: 32px
|
||||
margin: -16px 0px
|
||||
-webkit-transition: margin 250ms linear
|
||||
width: 100%
|
||||
z-index: 1000
|
||||
&:first-child:not(:last-child)
|
||||
margin-top: -8px
|
||||
margin-bottom: -24px
|
||||
@@ -184,8 +180,12 @@ table.editorbar-panel
|
||||
top: 24px
|
||||
&.oe_hover:before
|
||||
border-top: dashed 2px rgba(116, 255, 161, 0.72)
|
||||
|
||||
.oe_drop_zone.oe_overlay
|
||||
&.oe_vertical
|
||||
width: 16px
|
||||
display: inline-block
|
||||
position: absolute
|
||||
margin: 0px !important
|
||||
&.oe_overlay
|
||||
position: absolute
|
||||
background: rgba(153, 0, 255, 0.17)
|
||||
border-radius: 3px
|
||||
@@ -195,7 +195,7 @@ table.editorbar-panel
|
||||
border-radius: 3px
|
||||
&.oe_hover
|
||||
background: rgba(0, 255, 133, 0.22)
|
||||
z-index: 97
|
||||
z-index: 1001
|
||||
|
||||
/* ---- SNIPPET MANIPULATOR ---- */
|
||||
|
||||
@@ -208,8 +208,6 @@ table.editorbar-panel
|
||||
transition: opacity 100ms linear
|
||||
box-sizing: border-box
|
||||
pointer-events: none
|
||||
.oe_handle
|
||||
display: none !important
|
||||
&.oe_hover
|
||||
opacity: 1
|
||||
cursor: pointer
|
||||
@@ -221,26 +219,41 @@ table.editorbar-panel
|
||||
box-shadow: 0px 0px 0px 1px rgba(255,255,255,0.3), 0px 0px 0px 1px rgba(255,255,255,0.3) inset
|
||||
&.oe_selected
|
||||
border-color: rgba(0, 153, 255, 0.5)
|
||||
.oe_handle
|
||||
display: none !important
|
||||
&.oe_active
|
||||
border-color: rgba(153, 0, 255, 0.5)
|
||||
.oe_handle
|
||||
display: block !important
|
||||
pointer-events: auto
|
||||
.icon.btn
|
||||
display: inline-block
|
||||
|
||||
.oe_overlay_options
|
||||
display: none
|
||||
z-index: 99
|
||||
.oe_option
|
||||
pointer-events: auto
|
||||
z-index: 1002
|
||||
.oe_options,.oe_label,.oe_move
|
||||
position: absolute
|
||||
&.n
|
||||
top: 0px
|
||||
&.e
|
||||
right: 0px
|
||||
&.s
|
||||
bottom: 0px
|
||||
&.w
|
||||
left: 0px
|
||||
display: block
|
||||
z-index: 1002
|
||||
top: -11px
|
||||
.oe_options
|
||||
pointer-events: auto
|
||||
left: -14px
|
||||
.oe_label
|
||||
top: -8px
|
||||
right: 6px
|
||||
background: #fff
|
||||
font-size: 75%
|
||||
color: rgba(153, 0, 255, 0.5)
|
||||
padding: 0 5px
|
||||
.oe_move
|
||||
pointer-events: auto
|
||||
left: 50%
|
||||
.js_box_move
|
||||
margin-left: -50%
|
||||
.dropdown-menu select,.dropdown-menu input
|
||||
display: block
|
||||
&.oe_active .oe_overlay_options
|
||||
display: block
|
||||
|
||||
@@ -286,6 +299,8 @@ table.editorbar-panel
|
||||
cursor: e-resize !important
|
||||
.w-resize-important, .w-resize-important *
|
||||
cursor: w-resize !important
|
||||
.move-important, .move-important *
|
||||
cursor: move !important
|
||||
|
||||
|
||||
/* ---- MOBILE PREVIEW ---- */
|
||||
|
||||
@@ -27,21 +27,16 @@
|
||||
this.xml = text;
|
||||
},
|
||||
isWellFormed: function () {
|
||||
try {
|
||||
if (document.implementation.createDocument) {
|
||||
var dom = new DOMParser().parseFromString(this.xml, "text/xml");
|
||||
return dom.getElementsByTagName("parsererror").length === 0;
|
||||
} else if (window.ActiveXObject) {
|
||||
// TODO test in IE
|
||||
var msDom = new ActiveXObject("Microsoft.XMLDOM");
|
||||
msDom.async = false;
|
||||
return !msDom.loadXML(this.xml);
|
||||
} else {
|
||||
throw Error("Not implemented");
|
||||
}
|
||||
} catch(exception) {
|
||||
console.log(exception);
|
||||
if (document.implementation.createDocument) {
|
||||
var dom = new DOMParser().parseFromString(this.xml, "text/xml");
|
||||
return dom.getElementsByTagName("parsererror").length === 0;
|
||||
} else if (window.ActiveXObject) {
|
||||
// TODO test in IE
|
||||
var msDom = new ActiveXObject("Microsoft.XMLDOM");
|
||||
msDom.async = false;
|
||||
return !msDom.loadXML(this.xml);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
format: function () {
|
||||
return vkbeautify.xml(this.xml, 4);
|
||||
@@ -101,15 +96,11 @@
|
||||
method: 'read',
|
||||
args: [[this.selectedViewId()], ['arch'], website.get_context()],
|
||||
}).then(function(result) {
|
||||
if (result && result.length > 0) {
|
||||
var xml = new website.ace.XmlDocument(result[0].arch)
|
||||
var editingSession = new ace.EditSession(xml.xml);
|
||||
editingSession.setMode("ace/mode/xml");
|
||||
editingSession.setUndoManager(new ace.UndoManager());
|
||||
editor.setSession(editingSession);
|
||||
} else {
|
||||
throw Error("Could not load view XML");
|
||||
}
|
||||
var xml = new website.ace.XmlDocument(result[0].arch);
|
||||
var editingSession = new ace.EditSession(xml.xml);
|
||||
editingSession.setMode("ace/mode/xml");
|
||||
editingSession.setUndoManager(new ace.UndoManager());
|
||||
editor.setSession(editingSession);
|
||||
});
|
||||
},
|
||||
formatXml: function () {
|
||||
|
||||
@@ -359,7 +359,7 @@
|
||||
"Superscript", "TextColor", "BGColor", "RemoveFormat"
|
||||
]},{
|
||||
name: 'span', items: [
|
||||
"Link", "Unlink", "Blockquote", "BulletedList",
|
||||
"Link", "Blockquote", "BulletedList",
|
||||
"NumberedList", "Indent", "Outdent"
|
||||
]},{
|
||||
name: 'justify', items: [
|
||||
@@ -411,6 +411,9 @@
|
||||
return sup;
|
||||
},
|
||||
save: function () {
|
||||
this.close();
|
||||
},
|
||||
close: function () {
|
||||
this.$el.modal('hide');
|
||||
},
|
||||
});
|
||||
@@ -418,6 +421,20 @@
|
||||
website.editor.LinkDialog = website.editor.Dialog.extend({
|
||||
template: 'website.editor.dialog.link',
|
||||
events: _.extend({}, website.editor.Dialog.prototype.events, {
|
||||
'change .url-source': function (e) { this.changed($(e.target)); },
|
||||
'mousedown': function (e) {
|
||||
var $target = $(e.target).closest('.list-group-item');
|
||||
if (!$target.length || $target.hasClass('active')) {
|
||||
// clicked outside groups, or clicked in active groups
|
||||
return;
|
||||
}
|
||||
|
||||
$target
|
||||
.addClass('active')
|
||||
.siblings().removeClass('active')
|
||||
.addBack().removeClass('has-error');
|
||||
},
|
||||
'click button.remove': 'remove_link',
|
||||
}),
|
||||
init: function (editor) {
|
||||
this._super(editor);
|
||||
@@ -430,12 +447,28 @@
|
||||
this.editor.getSelection().selectElement(element);
|
||||
}
|
||||
this.element = element;
|
||||
if (element) {
|
||||
this.add_removal_button();
|
||||
}
|
||||
|
||||
return $.when(
|
||||
this.fetch_pages().done(this.proxy('fill_pages')),
|
||||
this._super()
|
||||
).done(this.proxy('bind_data'));
|
||||
},
|
||||
add_removal_button: function () {
|
||||
this.$('.modal-footer').prepend(
|
||||
openerp.qweb.render(
|
||||
'website.editor.dialog.link.footer-button'));
|
||||
},
|
||||
remove_link: function () {
|
||||
var editor = this.editor;
|
||||
// same issue as in make_link
|
||||
setTimeout(function () {
|
||||
editor.execCommand('unlink');
|
||||
}, 0);
|
||||
this.close();
|
||||
},
|
||||
/**
|
||||
* Greatly simplified version of CKEDITOR's
|
||||
* plugins.link.dialogs.link.onOk.
|
||||
@@ -483,25 +516,25 @@
|
||||
},
|
||||
save: function () {
|
||||
var self = this, _super = this._super.bind(this);
|
||||
var $active_tab = this.$('.tab-pane.active');
|
||||
var $e = this.$('.list-group-item.active .url-source');
|
||||
var val = $e.val();
|
||||
if (!val) {
|
||||
$e.closest('.form-group').addClass('has-error');
|
||||
return;
|
||||
}
|
||||
|
||||
var $e = $active_tab.find('.url-source');
|
||||
|
||||
var val = $e.val(), done = $.when();
|
||||
if ($active_tab.is('#link-email')) {
|
||||
var done = $.when();
|
||||
if ($e.hasClass('email-address')) {
|
||||
this.make_link('mailto:' + val, false, val);
|
||||
} else if ($active_tab.is('#link-existing')) {
|
||||
} else if ($e.hasClass('existing')) {
|
||||
self.make_link(val, false, this.pages[val]);
|
||||
} else if ($active_tab.is('#link-new')) {
|
||||
} else if ($e.hasClass('pages')) {
|
||||
// Create the page, get the URL back
|
||||
done = $.get(_.str.sprintf(
|
||||
'/pagenew/%s?noredirect', encodeURIComponent(val)))
|
||||
'/pagenew/%s?noredirect', encodeURIComponent(val)))
|
||||
.then(function (response) {
|
||||
val = response;
|
||||
self.make_link(response, false, val);
|
||||
});
|
||||
done.then(function () {
|
||||
self.make_link(val, false);
|
||||
});
|
||||
} else {
|
||||
this.make_link(val, this.$('input.window-new').prop('checked'));
|
||||
}
|
||||
@@ -514,19 +547,22 @@
|
||||
|
||||
var match, $control;
|
||||
if (match = /(mailto):(.+)/.exec(href)) {
|
||||
$control = this.$('#link-email input').val(match[2]);
|
||||
$control = this.$('input.email-address').val(match[2]);
|
||||
} else if(href in this.pages) {
|
||||
$control = this.$('#link-existing select').val(href);
|
||||
} else {
|
||||
$control = this.$('#link-external input:first').val(href);
|
||||
$control = this.$('select.existing').val(href);
|
||||
}
|
||||
if (!$control) {
|
||||
$control = this.$('input.url').val(href);
|
||||
}
|
||||
|
||||
var tab_name = $control.closest('.tab-pane').attr('id');
|
||||
this.$('.nav a[href="#' + tab_name + '"]').tab('show');
|
||||
this.changed($control);
|
||||
|
||||
this.$('input.window-new').prop(
|
||||
'checked', this.element.getAttribute('target') === '_blank');
|
||||
},
|
||||
changed: function ($e) {
|
||||
this.$('.url-source').not($e).val('');
|
||||
},
|
||||
/**
|
||||
* CKEDITOR.plugins.link.getSelectedLink ignores the editor's root,
|
||||
* if the editor is set directly on a link it will thus not work.
|
||||
@@ -556,43 +592,32 @@
|
||||
},
|
||||
fill_pages: function (results) {
|
||||
var self = this;
|
||||
var pages = this.$('#link-existing-select')[0];
|
||||
var pages = this.$('select.existing')[0];
|
||||
_(results).each(function (result) {
|
||||
self.pages[result.url] = result.name;
|
||||
|
||||
pages.options[pages.options.length] =
|
||||
new Option(result.name, result.url);
|
||||
new Option(result.name, result.url);
|
||||
});
|
||||
},
|
||||
});
|
||||
website.editor.ImageDialog = website.editor.Dialog.extend({
|
||||
template: 'website.editor.dialog.image',
|
||||
events: _.extend({}, website.editor.Dialog.prototype.events, {
|
||||
'change .url-source': function (e) { this.changed($(e.target)); },
|
||||
'click button.filepicker': function () {
|
||||
this.$('input[type=file]').click();
|
||||
},
|
||||
'change input[type=file]': 'file_selection',
|
||||
'change input.url': 'preview_image',
|
||||
'change select.image-style': 'preview_image',
|
||||
'click .existing-attachments a': 'select_existing',
|
||||
}),
|
||||
start: function () {
|
||||
var selection = this.editor.getSelection();
|
||||
var el = selection && selection.getSelectedElement();
|
||||
this.element = null;
|
||||
|
||||
var $select = this.$('.image-style');
|
||||
var $options = $select.children();
|
||||
this.image_styles = $options.map(function () { return this.value; }).get();
|
||||
|
||||
if (el && el.is('img')) {
|
||||
this.element = el;
|
||||
_(this.image_styles).each(function (style) {
|
||||
if (el.hasClass(style)) {
|
||||
$select.val(style);
|
||||
}
|
||||
});
|
||||
// set_image should follow setup of image style
|
||||
this.set_image(el.getAttribute('src'));
|
||||
}
|
||||
|
||||
@@ -602,7 +627,6 @@
|
||||
},
|
||||
save: function () {
|
||||
var url = this.$('input.url').val();
|
||||
var style = this.$('.image-style').val();
|
||||
var element, editor = this.editor;
|
||||
if (!(element = this.element)) {
|
||||
element = editor.document.createElement('img');
|
||||
@@ -616,10 +640,7 @@
|
||||
}, 0);
|
||||
}
|
||||
element.setAttribute('src', url);
|
||||
$(element.$).removeClass(this.image_styles.join(' '));
|
||||
if (style) { element.addClass(style); }
|
||||
|
||||
return this._super();
|
||||
this._super();
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -657,10 +678,7 @@
|
||||
var image = this.$('input.url').val();
|
||||
if (!image) { return; }
|
||||
|
||||
this.$('img.image-preview')
|
||||
.attr('src', image)
|
||||
.removeClass(this.image_styles.join(' '))
|
||||
.addClass(this.$('select.image-style').val());
|
||||
this.$('img.image-preview').attr('src', image);
|
||||
},
|
||||
|
||||
fetch_existing: function () {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
// TODO l10n ?
|
||||
|
||||
var website = openerp.website;
|
||||
website.templates.push('/website/static/src/xml/website.seo.xml');
|
||||
@@ -16,14 +15,183 @@
|
||||
|
||||
website.seo = {};
|
||||
|
||||
website.seo.PageParser = openerp.Class.extend({
|
||||
website.seo.Suggestion = openerp.Widget.extend({
|
||||
template: 'website.seo_suggestion',
|
||||
events: {
|
||||
'click .js_seo_suggestion': 'select',
|
||||
},
|
||||
init: function (parent, keyword) {
|
||||
this.keyword = keyword;
|
||||
var keywordRegex = new RegExp(this.keyword, "gi");
|
||||
var pageText = $('body').children().not('.js_seo_configuration').text();
|
||||
var isKeywordInBody = keywordRegex.test(pageText);
|
||||
// cf. http://getbootstrap.com/components/#labels
|
||||
// default, primary, success, info, warning, danger
|
||||
this.type = isKeywordInBody ? 'info' : 'default';
|
||||
this._super(parent);
|
||||
},
|
||||
select: function () {
|
||||
this.trigger('selected', this.keyword);
|
||||
},
|
||||
});
|
||||
|
||||
website.seo.SuggestionList = openerp.Widget.extend({
|
||||
template: 'website.seo_list',
|
||||
init: function (parent, word) {
|
||||
this.word = word;
|
||||
this._super(parent);
|
||||
},
|
||||
start: function () {
|
||||
this.refresh();
|
||||
},
|
||||
refresh: function () {
|
||||
var self = this;
|
||||
self.$el.append("Loading...");
|
||||
function addSuggestions (list) {
|
||||
self.$el.empty();
|
||||
// TODO Improve algorithm + Ajust based on custom user keywords
|
||||
var nameRegex = new RegExp(self.companyName, "gi");
|
||||
var cleanList = _.map(list, function removeCompanyName (word) {
|
||||
return word.replace(nameRegex, "").trim();
|
||||
});
|
||||
// TODO Order properly ?
|
||||
_.each(_.uniq(cleanList), function (keyword) {
|
||||
if (keyword) {
|
||||
var suggestion = new website.seo.Suggestion(self, keyword);
|
||||
suggestion.on('selected', self, function (word) {
|
||||
self.trigger('selected', word);
|
||||
});
|
||||
suggestion.appendTo(self.$el);
|
||||
}
|
||||
});
|
||||
}
|
||||
$.getJSON("http://seo.eu01.aws.af.cm/suggest/"+encodeURIComponent(this.word + " "), addSuggestions);
|
||||
},
|
||||
});
|
||||
|
||||
website.seo.Keyword = openerp.Widget.extend({
|
||||
template: 'website.seo_keyword',
|
||||
events: {
|
||||
'click a[data-action=remove-keyword]': 'destroy',
|
||||
},
|
||||
maxWordsPerKeyword: 4, // TODO Check
|
||||
init: function (parent, keyword) {
|
||||
this.keyword = keyword;
|
||||
// cf. http://getbootstrap.com/components/#labels
|
||||
// default, primary, success, info, warning, danger
|
||||
this.type = 'warning';
|
||||
this._super(parent);
|
||||
},
|
||||
start: function () {
|
||||
var self = this;
|
||||
self.suggestionList = new website.seo.SuggestionList(self, this.keyword);
|
||||
self.suggestionList.on('selected', self, function (word) {
|
||||
self.trigger('selected', word);
|
||||
});
|
||||
this.suggestionList.appendTo(this.$('.js_seo_keyword_suggestion'));
|
||||
},
|
||||
destroy: function () {
|
||||
this.trigger('removed');
|
||||
this._super();
|
||||
},
|
||||
});
|
||||
|
||||
website.seo.KeywordList = openerp.Widget.extend({
|
||||
template: 'website.seo_list',
|
||||
maxKeywords: 10,
|
||||
init: function (parent) {
|
||||
this._super(parent);
|
||||
},
|
||||
keywords: function () {
|
||||
var result = [];
|
||||
this.$('span.js_seo_keyword').each(function () {
|
||||
result.push($(this).data('keyword'));
|
||||
});
|
||||
return result;
|
||||
},
|
||||
isKeywordListFull: function () {
|
||||
return this.keywords().length >= this.maxKeywords;
|
||||
},
|
||||
isExistingKeyword: function (word) {
|
||||
return _.contains(this.keywords(), word);
|
||||
},
|
||||
add: function (candidate) {
|
||||
var self = this;
|
||||
// TODO Refine
|
||||
var word = candidate ? candidate.replace(/[,;.:<>]+/g, " ").replace(/ +/g, " ").trim() : "";
|
||||
if (word && !self.isKeywordListFull() && !self.isExistingKeyword(word)) {
|
||||
var keyword = new website.seo.Keyword(self, word);
|
||||
keyword.on('removed', self, function () {
|
||||
self.trigger('list-not-full');
|
||||
self.trigger('removed', word);
|
||||
});
|
||||
keyword.on('selected', self, function (word) {
|
||||
self.trigger('selected', word);
|
||||
});
|
||||
keyword.appendTo(self.$el);
|
||||
}
|
||||
if (self.isKeywordListFull()) {
|
||||
self.trigger('list-full');
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
website.seo.Image = openerp.Widget.extend({
|
||||
template: 'website.seo_image',
|
||||
init: function (parent, options) {
|
||||
this.src = options.src;
|
||||
this.alt = options.alt;
|
||||
this._super(parent);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
website.seo.ImageList = openerp.Widget.extend({
|
||||
start: function () {
|
||||
var self = this;
|
||||
new website.seo.HtmlPage().images().each(function (index, image) {
|
||||
new website.seo.Image(self, image).appendTo(self.$el);
|
||||
});
|
||||
},
|
||||
images: function () {
|
||||
var result = [];
|
||||
this.$('input').each(function () {
|
||||
var $input = $(this);
|
||||
result.push({
|
||||
src: $input.attr('src'),
|
||||
alt: $input.val(),
|
||||
});
|
||||
});
|
||||
return result;
|
||||
},
|
||||
add: function (image) {
|
||||
new website.seo.Image(this, image).appendTo(this.$el);
|
||||
},
|
||||
});
|
||||
|
||||
website.seo.HtmlPage = openerp.Class.extend({
|
||||
url: function () {
|
||||
var url = window.location.href;
|
||||
var hashIndex = url.indexOf('#');
|
||||
return hashIndex >= 0 ? url.substring(0, hashIndex) : url;
|
||||
},
|
||||
title: function () {
|
||||
return $(document.title).text();
|
||||
return $('title').text();
|
||||
},
|
||||
changeTitle: function (title) {
|
||||
$('title').text(title);
|
||||
},
|
||||
description: function () {
|
||||
return $('meta[name=description]').attr('value');
|
||||
},
|
||||
changeDescription: function (description) {
|
||||
return $('meta[name=description]').attr('value', description);
|
||||
},
|
||||
keywords: function () {
|
||||
return $('meta[name=keywords]').attr('value').split(",");
|
||||
},
|
||||
changeKeywords: function (keywords) {
|
||||
return $('meta[name=keywords]').attr('value', keyword.join(","));
|
||||
},
|
||||
headers: function (tag) {
|
||||
return $('#wrap '+tag).map(function () {
|
||||
@@ -58,222 +226,67 @@
|
||||
},
|
||||
});
|
||||
|
||||
website.seo.Keyword = openerp.Widget.extend({
|
||||
template: 'website.seo_keyword',
|
||||
events: {
|
||||
'click a[data-action=remove-keyword]': 'destroy',
|
||||
},
|
||||
maxWordsPerKeyword: 4, // TODO Check
|
||||
types: {
|
||||
// cf. http://getbootstrap.com/components/#labels
|
||||
// default, primary, success, info, warning, danger
|
||||
perfect: 'success',
|
||||
advised: 'primary',
|
||||
used: 'warning',
|
||||
custom: 'default',
|
||||
},
|
||||
init: function (parent, options) {
|
||||
this.keyword = options.keyword;
|
||||
this.type = this.types[options.type] || 'default';
|
||||
this._super(parent);
|
||||
},
|
||||
destroy: function () {
|
||||
this.trigger('removed');
|
||||
this._super();
|
||||
},
|
||||
});
|
||||
|
||||
website.seo.KeywordList = openerp.Widget.extend({
|
||||
template: 'website.seo_list',
|
||||
maxKeywords: 10,
|
||||
keywords: function () {
|
||||
var result = [];
|
||||
this.$('.js_seo_keyword').each(function () {
|
||||
result.push($(this).data('keyword'));
|
||||
});
|
||||
return result;
|
||||
},
|
||||
isKeywordListFull: function () {
|
||||
return this.keywords().length >= this.maxKeywords;
|
||||
},
|
||||
isExistingKeyword: function (word) {
|
||||
return _.contains(this.keywords(), word);
|
||||
},
|
||||
add: function (candidate, suggested) {
|
||||
var self = this;
|
||||
// TODO Refine
|
||||
var word = candidate ? candidate.replace(/[,;.:<>]+/g, " ").replace(/ +/g, " ").trim() : "";
|
||||
if (word && !self.isKeywordListFull() && !self.isExistingKeyword(word)) {
|
||||
var type = suggested ? 'advised' : 'custom';
|
||||
var keyword = new website.seo.Keyword(self, {
|
||||
keyword: word,
|
||||
type: type,
|
||||
});
|
||||
keyword.on('removed', null, function () {
|
||||
self.trigger('list-not-full');
|
||||
});
|
||||
keyword.appendTo(self.$el);
|
||||
}
|
||||
if (self.isKeywordListFull()) {
|
||||
self.trigger('list-full');
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
website.seo.Suggestion = openerp.Widget.extend({
|
||||
template: 'website.seo_suggestion',
|
||||
events: {
|
||||
'click .js_seo_suggestion': 'select'
|
||||
},
|
||||
types: {
|
||||
// cf. http://getbootstrap.com/components/#labels
|
||||
// default, primary, success, info, warning, danger
|
||||
primary: 'primary',
|
||||
secondary: 'info',
|
||||
|
||||
},
|
||||
init: function (parent, options) {
|
||||
this.keyword = options.keyword;
|
||||
this.type = this.types[options.type || 'primary'];
|
||||
this._super(parent);
|
||||
},
|
||||
select: function () {
|
||||
this.trigger('selected');
|
||||
},
|
||||
});
|
||||
|
||||
website.seo.SuggestionList = openerp.Widget.extend({
|
||||
template: 'website.seo_list',
|
||||
init: function (parent, companyName) {
|
||||
this.companyName = companyName;
|
||||
this._super(parent);
|
||||
},
|
||||
start: function () {
|
||||
var self = this;
|
||||
self.$el.append("Loading...");
|
||||
// cf. https://github.com/ddm/seo
|
||||
// TODO Try with /recommend/
|
||||
$.getJSON("http://seo.eu01.aws.af.cm/suggest/"+encodeURIComponent(self.companyName), function (list) {
|
||||
self.$el.empty();
|
||||
// TODO Improve algorithm + Ajust based on custom user keywords
|
||||
var nameRegex = new RegExp(self.companyName, "gi");
|
||||
var cleanList = _.map(list, function removeCompanyName (word) {
|
||||
return word.replace(nameRegex, "").trim();
|
||||
});
|
||||
// TODO Order properly ?
|
||||
cleanList.push(self.companyName);
|
||||
_.each(_.uniq(cleanList), function (keyword) {
|
||||
if (keyword) {
|
||||
var suggestion = new website.seo.Suggestion(self, {
|
||||
keyword: keyword
|
||||
});
|
||||
suggestion.on('selected', self, function () {
|
||||
self.trigger('selected', keyword);
|
||||
});
|
||||
suggestion.appendTo(self.$el);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
suggestions: function () {
|
||||
return this.$('.js_seo_suggestion').map(function () {
|
||||
return $(this).data('keyword');
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
website.seo.Image = openerp.Widget.extend({
|
||||
template: 'website.seo_image',
|
||||
init: function (parent, options) {
|
||||
this.src = options.src;
|
||||
this.alt = options.alt;
|
||||
this._super(parent);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
website.seo.ImageList = openerp.Widget.extend({
|
||||
start: function () {
|
||||
var self = this;
|
||||
new website.seo.PageParser().images().each(function (index, image) {
|
||||
new website.seo.Image(self, image).appendTo(self.$el);
|
||||
});
|
||||
},
|
||||
images: function () {
|
||||
var result = [];
|
||||
this.$('input').each(function () {
|
||||
var $input = $(this);
|
||||
result.push({
|
||||
src: $input.attr('src'),
|
||||
alt: $input.val(),
|
||||
});
|
||||
});
|
||||
return result;
|
||||
},
|
||||
add: function (image) {
|
||||
new website.seo.Image(this, image).appendTo(this.$el);
|
||||
},
|
||||
});
|
||||
|
||||
website.seo.Configurator = openerp.Widget.extend({
|
||||
template: 'website.seo_configuration',
|
||||
events: {
|
||||
'keypress input[name=seo_page_keywords]': 'confirmKeyword',
|
||||
'keyup input[name=seo_page_keywords]': 'confirmKeyword',
|
||||
'keyup input[name=seo_page_title]': 'titleChanged',
|
||||
'keyup textarea[name=seo_page_description]': 'descriptionChanged',
|
||||
'click button[data-action=add]': 'addKeyword',
|
||||
'click button[data-action=update]': 'update',
|
||||
'hidden.bs.modal': 'destroy'
|
||||
'hidden.bs.modal': 'destroy',
|
||||
},
|
||||
maxTitleSize: 65,
|
||||
maxDescriptionSize: 155,
|
||||
start: function () {
|
||||
var self = this;
|
||||
var $modal = this.$el;
|
||||
var pageParser = new website.seo.PageParser();
|
||||
$modal.find('.js_seo_page_url').text(pageParser.url());
|
||||
$modal.find('input[name=seo_page_title]').val(pageParser.title());
|
||||
this.suggestImprovements(pageParser);
|
||||
this.imageList = new website.seo.ImageList(this);
|
||||
this.imageList.appendTo($modal.find('.js_seo_image_list'));
|
||||
this.keywordList = new website.seo.KeywordList(this);
|
||||
this.keywordList.on('list-full', null, function () {
|
||||
var $modal = self.$el;
|
||||
var htmlPage = this.htmlPage = new website.seo.HtmlPage();
|
||||
$modal.find('.js_seo_page_url').text(htmlPage.url());
|
||||
$modal.find('input[name=seo_page_title]').val(htmlPage.title());
|
||||
$modal.find('textarea[name=seo_page_description]').val(htmlPage.description());
|
||||
self.suggestImprovements(htmlPage);
|
||||
self.imageList = new website.seo.ImageList(self);
|
||||
self.imageList.appendTo($modal.find('.js_seo_image_list'));
|
||||
self.keywordList = new website.seo.KeywordList(self);
|
||||
self.keywordList.on('list-full', self, function () {
|
||||
$modal.find('input[name=seo_page_keywords]')
|
||||
.attr('readonly', "readonly")
|
||||
.attr('placeholder', "Remove a keyword first");
|
||||
$modal.find('button[data-action=add]')
|
||||
.prop('disabled', true).addClass('disabled');
|
||||
});
|
||||
this.keywordList.on('list-not-full', null, function () {
|
||||
self.keywordList.on('list-not-full', self, function () {
|
||||
$modal.find('input[name=seo_page_keywords]')
|
||||
.removeAttr('readonly').attr('placeholder', "");
|
||||
$modal.find('button[data-action=add]')
|
||||
.prop('disabled', false).removeClass('disabled');
|
||||
});
|
||||
this.keywordList.appendTo($modal.find('.js_seo_keywords_list'));
|
||||
var companyName = pageParser.company().toLowerCase();
|
||||
this.suggestionList = new website.seo.SuggestionList(this, companyName);
|
||||
this.suggestionList.on('selected', self, function (word) {
|
||||
self.acceptSuggestion(word);
|
||||
self.keywordList.on('selected', self, function (word) {
|
||||
self.keywordList.add(word);
|
||||
});
|
||||
this.suggestionList.appendTo($modal.find('.js_seo_suggestions_list'));
|
||||
self.keywordList.appendTo($modal.find('.js_seo_keywords_list'));
|
||||
var companyName = htmlPage.company().toLowerCase();
|
||||
self.addKeyword(companyName);
|
||||
$modal.modal();
|
||||
},
|
||||
suggestImprovements: function (parser) {
|
||||
var tips = [];
|
||||
var self = this;
|
||||
function displayTip(message, type) {
|
||||
new website.seo.Tip(this, {
|
||||
new website.seo.Tip(self, {
|
||||
message: message,
|
||||
type: type
|
||||
type: type,
|
||||
}).appendTo(self.$('.js_seo_tips'));
|
||||
}
|
||||
var pageParser = parser || new website.seo.PageParser();
|
||||
if (!pageParser.headers('h1').length === 0) {
|
||||
var htmlPage = parser || new website.seo.HtmlPage();
|
||||
if (htmlPage.headers('h1').length === 0) {
|
||||
tips.push({
|
||||
type: 'warning',
|
||||
message: "You don't have an <h1> tag on your page.",
|
||||
});
|
||||
}
|
||||
if (pageParser.headers('h1').length > 1) {
|
||||
if (htmlPage.headers('h1').length > 1) {
|
||||
tips.push({
|
||||
type: 'warning',
|
||||
message: "You have more than one <h1> tag on your page.",
|
||||
@@ -295,21 +308,33 @@
|
||||
addKeyword: function (word) {
|
||||
var $input = this.$('input[name=seo_page_keywords]');
|
||||
var keyword = _.isString(word) ? word : $input.val();
|
||||
this.keywordList.add(keyword, false);
|
||||
this.keywordList.add(keyword);
|
||||
$input.val("");
|
||||
},
|
||||
acceptSuggestion: function (suggestion) {
|
||||
this.keywordList.add(suggestion, true);
|
||||
},
|
||||
update: function () {
|
||||
var data = {
|
||||
title: this.$('input[name=seo_page_title]').val(),
|
||||
description: this.$('input[name=seo_page_title]').val(),
|
||||
title: this.htmlPage.title(),
|
||||
description: this.htmlPage.description(),
|
||||
keywords: this.keywordList.keywords(),
|
||||
images: this.imageList.images(),
|
||||
};
|
||||
console.log(data);
|
||||
// TODO Persist changes
|
||||
this.$el.modal('hide');
|
||||
},
|
||||
titleChanged: function () {
|
||||
var self = this;
|
||||
setTimeout(function () {
|
||||
var title = self.$('input[name=seo_page_title]').val();
|
||||
self.htmlPage.changeTitle(title);
|
||||
}, 1);
|
||||
},
|
||||
descriptionChanged: function () {
|
||||
var self = this;
|
||||
setTimeout(function () {
|
||||
var description = self.$('textarea[name=seo_page_description]').attr('value');
|
||||
self.htmlPage.changeDescription(description);
|
||||
}, 1);
|
||||
},
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -42,12 +42,19 @@
|
||||
});
|
||||
$el.css($target.offset());
|
||||
};
|
||||
website.snippet.is_empty_dom = function ($dom) {
|
||||
if ($.trim($dom.text()) !== '') return false;
|
||||
if ($dom.find('area, base, command, embed, hr, img, input, keygen').length) return false;
|
||||
return true;
|
||||
};
|
||||
function hack_to_add_snippet_id () {
|
||||
_.each(website.snippet.selector, function (val) {
|
||||
$(val[0]).each(function() {
|
||||
if ($(this).is("[data-snippet-id='"+ val[1]+"']"))
|
||||
$(this).removeAttr("data-snippet-id");
|
||||
if (!$(this).is("[data-snippet-id]") && $(this).parents("[data-oe-model]").length)
|
||||
$(this).attr("data-snippet-id", val[1]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
website.snippet.selector = [];
|
||||
website.snippet.BuildingBlock = openerp.Widget.extend({
|
||||
template: 'website.snippets',
|
||||
activeSnippets: [],
|
||||
@@ -60,6 +67,7 @@
|
||||
this.$active_snipped_id = false;
|
||||
this.active = false;
|
||||
this.parent_of_editable_box = "body > :not(:has(#website-top-view)):not(#oe_manipulators):not(#oe_snippets) ";
|
||||
hack_to_add_snippet_id();
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
@@ -165,19 +173,18 @@
|
||||
if (!self.active) {
|
||||
return;
|
||||
}
|
||||
if (self.editor_busy) {
|
||||
if($selected_target){
|
||||
$selected_target.data('overlay').removeClass('oe_selected');
|
||||
}
|
||||
}
|
||||
var $target = $(event.srcElement).parents("[data-snippet-id]:first");
|
||||
if($target.length && $selected_target != $target){
|
||||
if($selected_target){
|
||||
$selected_target.data('overlay').removeClass('oe_selected');
|
||||
if($target.length && !self.editor_busy) {
|
||||
if($selected_target != $target){
|
||||
if($selected_target){
|
||||
$selected_target.data('overlay').removeClass('oe_selected');
|
||||
}
|
||||
$selected_target = $target;
|
||||
self.create_overlay($target);
|
||||
$target.data('overlay').addClass('oe_selected');
|
||||
}
|
||||
$selected_target = $target;
|
||||
self.create_overlay($target);
|
||||
$target.data('overlay').addClass('oe_selected');
|
||||
} else if($selected_target) {
|
||||
$selected_target.data('overlay').removeClass('oe_selected');
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -190,12 +197,14 @@
|
||||
helper: 'clone',
|
||||
zIndex: '1000',
|
||||
appendTo: 'body',
|
||||
cursor: "move",
|
||||
start: function(){
|
||||
var action = $snippet.data('action');
|
||||
if( action === 'insert'){
|
||||
self.activate_insertion_zones({
|
||||
siblings: $snippet.data('selector-siblings'),
|
||||
childs: $snippet.data('selector-childs')
|
||||
childs: $snippet.data('selector-childs'),
|
||||
vertical_childs: $snippet.data('selector-vertical-childs')
|
||||
});
|
||||
} else if( action === 'mutate' ){
|
||||
|
||||
@@ -230,17 +239,24 @@
|
||||
var $toInsert = $snippet.find('.oe_snippet_body').clone();
|
||||
$toInsert.removeClass('oe_snippet_body');
|
||||
$toInsert.attr('data-snippet-id', snipped_id);
|
||||
$(".oe_drop_zone.oe_hover").after($toInsert);
|
||||
$(".oe_drop_zone.oe_hover").first().after($toInsert);
|
||||
$target = $toInsert;
|
||||
hack_to_add_snippet_id();
|
||||
} else {
|
||||
$target = $(".oe_drop_zone.oe_hover").data('target');
|
||||
$target = $(".oe_drop_zone.oe_hover").first().data('target');
|
||||
}
|
||||
|
||||
$('.oe_drop_zone').droppable('destroy').remove();
|
||||
|
||||
if (website.snippet.animationRegistry[snipped_id]) {
|
||||
new website.snippet.animationRegistry[snipped_id]($target);
|
||||
}
|
||||
if (website.snippet.editorRegistry[snipped_id]) {
|
||||
self.create_overlay($target);
|
||||
var snippet = new website.snippet.editorRegistry[snipped_id](self, $target);
|
||||
snippet.build_snippet($target);
|
||||
$target.data("snippet-editor").build_snippet($target);
|
||||
setTimeout(function () {self.make_active($target);},0);
|
||||
}
|
||||
|
||||
},
|
||||
});
|
||||
},
|
||||
@@ -262,6 +278,7 @@
|
||||
var $snippet = get_snippet_from_id($instance.data('snippet-id'));
|
||||
|
||||
$instance.draggable({
|
||||
greedy: true,
|
||||
helper: 'clone',
|
||||
zIndex: '1000',
|
||||
appendTo: 'body',
|
||||
@@ -271,7 +288,8 @@
|
||||
|
||||
self.activate_insertion_zones({
|
||||
siblings: $snippet.data('selector-siblings'),
|
||||
child: $snippet.data('selector-childs')
|
||||
child: $snippet.data('selector-childs'),
|
||||
vertical_childs: $snippet.data('selector-vertical-childs')
|
||||
});
|
||||
|
||||
}
|
||||
@@ -286,28 +304,39 @@
|
||||
// selector.siblings -> will insert drop zones after and before selected elements
|
||||
activate_insertion_zones: function(selector){
|
||||
var self = this;
|
||||
var child_selector = selector.childs ? this.parent_of_editable_box + (selector.childs).split(",").join(this.parent_of_editable_box) : false;
|
||||
var sibling_selector = selector.siblings ? this.parent_of_editable_box + (selector.siblings).split(",").join(this.parent_of_editable_box) : false;
|
||||
var child_selector = selector.childs ? this.parent_of_editable_box + (selector.childs).split(",").join(this.parent_of_editable_box) : false;
|
||||
var sibling_selector = selector.siblings ? this.parent_of_editable_box + (selector.siblings).split(",").join(this.parent_of_editable_box) : false;
|
||||
var vertical_child_selector = selector.vertical_childs ? this.parent_of_editable_box + (selector.vertical_childs).split(",").join(this.parent_of_editable_box) : false;
|
||||
|
||||
var zone_template = "<div class='oe_drop_zone oe_insert'></div>";
|
||||
|
||||
if(child_selector){
|
||||
var $zones = $(child_selector);
|
||||
for( var i = 0, len = $zones.length; i < len; i++ ){
|
||||
$zones.eq(i).find('> *:not(.oe_drop_zone)').after(zone_template);
|
||||
$zones.eq(i).prepend(zone_template);
|
||||
}
|
||||
$(child_selector).each(function (){
|
||||
var $zone = $(this);
|
||||
$zone.find('> *:not(.oe_drop_zone):visible').after(zone_template);
|
||||
$zone.prepend(zone_template);
|
||||
});
|
||||
}
|
||||
|
||||
if(vertical_child_selector){
|
||||
$(vertical_child_selector).each(function (){
|
||||
var $zone = $(this);
|
||||
var $template = $(zone_template).addClass("oe_vertical").css('height', $zone.outerHeight()+'px');
|
||||
$zone.find('> *:not(.oe_drop_zone):visible').after($template);
|
||||
$zone.prepend($template.clone());
|
||||
});
|
||||
}
|
||||
|
||||
if(sibling_selector){
|
||||
var $zones = $(sibling_selector);
|
||||
for( var i = 0, len = $zones.length; i < len; i++ ){
|
||||
if($zones.eq(i).prev('.oe_drop_zone').length === 0){
|
||||
$zones.eq(i).before(zone_template);
|
||||
$(sibling_selector).each(function (){
|
||||
var $zone = $(this);
|
||||
if($zone.prev('.oe_drop_zone:visible').length === 0){
|
||||
$zone.before(zone_template);
|
||||
}
|
||||
if($zones.eq(i).next('.oe_drop_zone').length === 0){
|
||||
$zones.eq(i).after(zone_template);
|
||||
if($zone.next('.oe_drop_zone:visible').length === 0){
|
||||
$zone.after(zone_template);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var count;
|
||||
@@ -320,12 +349,12 @@
|
||||
$zones = $('.oe_drop_zone > .oe_drop_zone').remove(); // no recusrive zones
|
||||
count += $zones.length;
|
||||
$zones.remove();
|
||||
}while(count > 0);
|
||||
} while (count > 0);
|
||||
|
||||
// Cleaning up zones placed between floating or inline elements. We do not like these kind of zones.
|
||||
var $zones = $('.oe_drop_zone');
|
||||
for( var i = 0, len = $zones.length; i < len; i++ ){
|
||||
var zone = $zones.eq(i);
|
||||
var $zones = $('.oe_drop_zone:not(.oe_vertical)');
|
||||
$zones.each(function (){
|
||||
var zone = $(this);
|
||||
var prev = zone.prev();
|
||||
var next = zone.next();
|
||||
var float_prev = zone.prev().css('float') || 'none';
|
||||
@@ -335,15 +364,14 @@
|
||||
if( (float_prev === 'left' || float_prev === 'right')
|
||||
&& (float_next === 'left' || float_next === 'right') ){
|
||||
zone.remove();
|
||||
continue;
|
||||
return;
|
||||
}else if( !( disp_prev === null
|
||||
|| disp_next === null
|
||||
|| disp_prev === 'block'
|
||||
|| disp_next === 'block' )){
|
||||
zone.remove();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// generate drop zones covering the elements selected by the selector
|
||||
@@ -373,14 +401,7 @@
|
||||
$targets.each(function () {
|
||||
var $target = $(this);
|
||||
if (!$target.data('overlay')) {
|
||||
var $zone = $(
|
||||
'<div class="oe_overlay">'+
|
||||
' <div class="oe_overlay_options">'+
|
||||
' <ul class="oe_option n w"></ul>'+
|
||||
' <ul class="oe_option n"></ul>'+
|
||||
' <ul class="oe_option n e"></ul>'+
|
||||
' </div>'+
|
||||
'</div>');
|
||||
var $zone = $(openerp.qweb.render('website.snippet_overlay'));
|
||||
$zone.appendTo('#oe_manipulators');
|
||||
$zone.data('target',$target);
|
||||
$target.data('overlay',$zone);
|
||||
@@ -412,8 +433,7 @@
|
||||
return this.$el.find.apply(this.$el, arguments);
|
||||
},
|
||||
init: function (dom) {
|
||||
this.$el = $(dom);
|
||||
this._super.apply(this, arguments);
|
||||
this.$el = this.$target = $(dom);
|
||||
},
|
||||
/* onFocusEdit
|
||||
* if they are an editor for this snippet-id
|
||||
@@ -436,8 +456,8 @@
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
$(document).ready(function () {
|
||||
hack_to_add_snippet_id();
|
||||
$("[data-snippet-id]").each(function() {
|
||||
var $snipped_id = $(this);
|
||||
if (typeof $snipped_id.data("snippet-view") === 'undefined' &&
|
||||
@@ -481,15 +501,66 @@
|
||||
this.$editor = this.$el.find(".oe_snippet_options");
|
||||
this.$thumbnail = this.$el.find(".oe_snippet_thumbnail");
|
||||
this.$body = this.$el.find(".oe_snippet_body");
|
||||
|
||||
var $options = this.$overlay.find(".oe_overlay_options");
|
||||
this.$editor.prependTo($options.find(".oe_options ul"));
|
||||
$options.find(".oe_label").text(this.$el.find('.oe_snippet_thumbnail.oe_label, .oe_snippet_thumbnail .oe_label').text());
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// activate drag and drop for the snippets in the snippet toolbar
|
||||
_drag_and_drop: function(){
|
||||
var self = this;
|
||||
this.$overlay.draggable({
|
||||
greedy: true,
|
||||
appendTo: 'body',
|
||||
cursor: "move",
|
||||
cursorAt: {
|
||||
top: self.$target.outerHeight()/2,
|
||||
left: self.$target.outerWidth()/2 },
|
||||
distance: 20,
|
||||
handle: ".js_box_move",
|
||||
start: function(){
|
||||
self.parent.editor_busy = true;
|
||||
self.$target.css("display", "none");
|
||||
self.parent.activate_insertion_zones({
|
||||
siblings: self.$el ? self.$el.data('selector-siblings') : false,
|
||||
childs: self.$el ? self.$el.data('selector-childs') : false,
|
||||
vertical_childs: self.$el ? self.$el.data('selector-vertical-childs') : false,
|
||||
});
|
||||
$("body").addClass('move-important');
|
||||
$('.oe_drop_zone').droppable({
|
||||
hoverClass: "oe_hover",
|
||||
drop: function(){
|
||||
$(this).after(self.$target);
|
||||
},
|
||||
});
|
||||
},
|
||||
stop: function(){
|
||||
$("body").removeClass('move-important');
|
||||
$('.oe_drop_zone').droppable('destroy').remove();
|
||||
self.$target.css("display", "");
|
||||
self.parent.editor_busy = false;
|
||||
setTimeout(function () {self.parent.create_overlay(self.$target);},0);
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
* start
|
||||
* This method is called after init and _readXMLData
|
||||
*/
|
||||
start: function () {
|
||||
if(this.$editor) this.$editor.prependTo(this.$overlay.find(".oe_overlay_options .oe_option.n.w"));
|
||||
var self = this;
|
||||
this.$overlay.on('click', '.js_box_remove', function () {
|
||||
self.$target.detach();
|
||||
self.onBlur();
|
||||
self.$target.remove();
|
||||
return false;
|
||||
});
|
||||
this._drag_and_drop();
|
||||
},
|
||||
|
||||
/*
|
||||
@@ -498,8 +569,6 @@
|
||||
* (after the insertion of this.$body, if this.$body exists)
|
||||
*/
|
||||
build_snippet: function ($target) {
|
||||
var self = this;
|
||||
setTimeout(function () {self.parent.make_active(self.$target);},0);
|
||||
},
|
||||
|
||||
/* onFocus
|
||||
@@ -534,6 +603,7 @@
|
||||
|
||||
|
||||
website.snippet.editorRegistry.resize = website.snippet.Editor.extend({
|
||||
template : "website.snippets.resize",
|
||||
start: function () {
|
||||
var self = this;
|
||||
this._super();
|
||||
@@ -547,16 +617,6 @@
|
||||
|
||||
this.$overlay.append($box.find(".oe_handles").html());
|
||||
|
||||
var $editor = $box.find(".oe_snippet_options");
|
||||
$editor.prependTo(this.$overlay.find(".oe_overlay_options .oe_option.n.w"));
|
||||
|
||||
$editor.on('click', '.js_box_remove', function () {
|
||||
self.$target.detach();
|
||||
self.onBlur();
|
||||
self.$target.remove();
|
||||
});
|
||||
|
||||
|
||||
this.$overlay.find(".oe_handle").on('mousedown', function (event){
|
||||
event.preventDefault();
|
||||
|
||||
@@ -588,10 +648,7 @@
|
||||
var current = resize[2] || 0;
|
||||
_.each(resize[0], function (val, key) {
|
||||
if (self.$target.hasClass(val)) {
|
||||
if (current)
|
||||
self.$target.removeClass(val);
|
||||
else
|
||||
current = key;
|
||||
current = key;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -663,11 +720,12 @@
|
||||
});
|
||||
|
||||
website.snippet.editorRegistry.colmd = website.snippet.editorRegistry.resize.extend({
|
||||
template : "website.snippets.colmd",
|
||||
getSize: function () {
|
||||
this.grid = this._super();
|
||||
var width = this.$target.parents(".row:first").first().outerWidth();
|
||||
|
||||
var grid = [0,1,2,3,4,5,6,7,8,9,10,11,12];
|
||||
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;})];
|
||||
|
||||
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];
|
||||
@@ -675,127 +733,26 @@
|
||||
|
||||
return this.grid;
|
||||
},
|
||||
resizeHeight: function () {
|
||||
var height = 0;
|
||||
var $parent = this.$target.parent();
|
||||
var $cols = $parent.find('>');
|
||||
$cols.css('height', '');
|
||||
if ($cols.length <= 1) {
|
||||
$parent.css('height', '');
|
||||
return;
|
||||
}
|
||||
var both = '<div class="oe_remove_me" style="overflow: hidden; height: 0;">.</div>';
|
||||
$parent.append(both).prepend(both);
|
||||
$cols.each(function () {
|
||||
if (height < $(this).outerHeight()) {
|
||||
height = $(this).outerHeight();
|
||||
}
|
||||
});
|
||||
$parent.css('height', height + 'px');
|
||||
$parent.find('.oe_remove_me').remove();
|
||||
$cols.css('height', '99%');
|
||||
},
|
||||
on_resize: function (compass, beginClass, current) {
|
||||
if (compass !== 'e' && compass !== 'w' )
|
||||
if (compass !== 'w')
|
||||
return;
|
||||
|
||||
var self = this;
|
||||
var currentClass = this.grid[compass][0][current];
|
||||
var beginSize = Number(beginClass.match(/col-md-([0-9]+)|$/)[1] || 0) + Number(beginClass.match(/col-lg-offset-([0-9-]+)|$/)[1] || 0);
|
||||
|
||||
// don't change the rigth border position when we change the offset (replace col size)
|
||||
var colsize = compass === 'w' ?
|
||||
beginSize - Number(currentClass.match(/col-lg-offset-([0-9-]+)|$/)[1] || 0) :
|
||||
Number(currentClass.match(/col-md-([0-9-]+)|$/)[1] || 0);
|
||||
if (colsize > 12) colsize = 12;
|
||||
if (colsize < 1) {
|
||||
colsize = website.snippet.is_empty_dom(self.$target) ? 0 : 1;
|
||||
}
|
||||
this.$target.attr("class",
|
||||
this.$target.attr("class").replace(/\s*(col-lg-offset-|col-md-)([0-9-]+)/g, '') + ' col-md-' + colsize
|
||||
);
|
||||
var beginCol = Number(beginClass.match(/col-md-([0-9]+)|$/)[1] || 0);
|
||||
var beginOffset = Number(beginClass.match(/col-lg-offset-([0-9-]+)|$/)[1] || 0);
|
||||
var offset = Number(this.grid.w[0][current].match(/col-lg-offset-([0-9-]+)|$/)[1] || 0);
|
||||
|
||||
// calculate col size (0 < size <= 12)
|
||||
var size = 0;
|
||||
var $parent = this.$target.parent();
|
||||
_.each(this.grid.e[0], function (val) {
|
||||
size += $parent.find('.' + val).length * Number(val.replace(/[^0-9]+/, ''));
|
||||
});
|
||||
_.each(this.grid.w[0], function (val) {
|
||||
size += $parent.find('.' + val).length * Number(val.replace(/[^0-9]+/, ''));
|
||||
});
|
||||
this.$target.attr("class",this.$target.attr("class").replace(/\s*(col-lg-offset-|col-md-)([0-9-]+)/g, ''));
|
||||
|
||||
function change_empty_col ($col) {
|
||||
var _size = Number($col.attr("class").match(/col-md-([0-9-]+)|$/)[1] || 0);
|
||||
if (12 - (size - _size) > 0) {
|
||||
size -= _size;
|
||||
$col.attr("class", $col.attr("class").replace(/\s*col-md-([0-9-]+)/g, '') + ' col-md-' + (12 - size));
|
||||
size = 12;
|
||||
} else if(website.snippet.is_empty_dom($col)) {
|
||||
size -= _size;
|
||||
$col.remove();
|
||||
}
|
||||
var colSize = beginCol - (offset - beginOffset);
|
||||
this.$target.addClass('col-md-' + (colSize > 12 ? 12 : colSize));
|
||||
if (offset > 0) {
|
||||
this.$target.addClass('col-lg-offset-' + offset);
|
||||
}
|
||||
|
||||
function insert_empty_col () {
|
||||
var cleanClass = beginClass.replace(/\s*(col-lg-offset-|col-md-)([0-9-]+)/g, '');
|
||||
var $insert = $('<div class="' + cleanClass + '" data-snippet-id="colmd"><p><br/></p></div>');
|
||||
$insert.addClass('col-md-'+(12-size));
|
||||
size = 12;
|
||||
return $insert;
|
||||
}
|
||||
|
||||
// change previous or next col if empty
|
||||
if (compass === 'w') {
|
||||
var $prev = this.$target.prev();
|
||||
if ($prev.length) {
|
||||
change_empty_col($prev);
|
||||
}
|
||||
if(size < 12 && size > 0) {
|
||||
this.$target.before(insert_empty_col());
|
||||
}
|
||||
} else {
|
||||
var $next = this.$target.next();
|
||||
if ($next.length) {
|
||||
change_empty_col($next);
|
||||
}
|
||||
if(size < 12 && size > 0) {
|
||||
this.$target.after(insert_empty_col());
|
||||
}
|
||||
}
|
||||
if(size > 12 || size <= 0) {
|
||||
this.$target.attr("class",
|
||||
this.$target.attr("class").replace(/\s*col-md-([0-9-]+)/g, '') + ' col-md-' + (size-12)
|
||||
);
|
||||
}
|
||||
|
||||
// remove empty col
|
||||
if (this.$target.hasClass("col-md-0")) {
|
||||
$('body').mouseup();
|
||||
setTimeout(function () {
|
||||
self.$overlay.remove();
|
||||
var $div = self.$target.prev();
|
||||
if (!$div.length) {
|
||||
$div = self.$target.next();
|
||||
}
|
||||
self.$target.remove();
|
||||
self.parent.make_active($div);
|
||||
},0);
|
||||
}
|
||||
|
||||
setTimeout(function () {
|
||||
self.resizeHeight();
|
||||
},0);
|
||||
},
|
||||
start: function () {
|
||||
var self = this;
|
||||
this._super();
|
||||
this.resizeHeight();
|
||||
$("body").on("save", function () {
|
||||
self.$target.parent().css('height', '').find('>').css('height', '');
|
||||
});
|
||||
},
|
||||
});
|
||||
website.snippet.selector.push([ _.map([1,2,3,4,5,6,7,8,9,10,11,12], function (v) {return '.row > .col-md-'+v;}).join(","), 'colmd']);
|
||||
|
||||
|
||||
website.snippet.editorRegistry.carousel = website.snippet.editorRegistry.resize.extend({
|
||||
template : "website.snippets.carousel",
|
||||
@@ -811,14 +768,24 @@
|
||||
this.$editor.find(".js_add").on('click', this.on_add);
|
||||
this.$editor.find(".js_remove").on('click', this.on_remove);
|
||||
|
||||
|
||||
//background
|
||||
var bg = this.$target.find('.carousel-inner .item.active').css('background-image').replace(/url\((.*)\)/g, '\$1');
|
||||
this.$editor.find('select[name="carousel-background"] option[value="'+bg+'"], select[name="carousel-background"] option[value="'+bg.replace(window.location.protocol+'//'+window.location.host, '')+'"]')
|
||||
.prop('selected', true);
|
||||
var selected = this.$editor.find('select[name="carousel-background"] option[value="'+bg+'"], select[name="carousel-background"] option[value="'+bg.replace(window.location.protocol+'//'+window.location.host, '')+'"]')
|
||||
.prop('selected', true).length;
|
||||
if (!selected) {
|
||||
this.$editor.find('.carousel-background input').val(bg);
|
||||
}
|
||||
|
||||
this.$editor.find('select[name="carousel-background"]').on('change', function () {
|
||||
self.$target.find('.carousel-inner .item.active').css('background-image', 'url(' + $(this).val() + ')');
|
||||
});
|
||||
this.$editor.find('select[name="carousel-background"], input')
|
||||
.on('click', function (event) {event.preventDefault(); return false;})
|
||||
.on('change', function () {
|
||||
self.$target.find('.carousel-inner .item.active').css('background-image', 'url(' + $(this).val() + ')');
|
||||
$(this).next().val("");
|
||||
});
|
||||
|
||||
|
||||
//style
|
||||
var style = false;
|
||||
if (this.$target.find('.carousel-inner .item.active .container .content_image.col-lg-offset-1'))
|
||||
style = 'image_right';
|
||||
@@ -887,11 +854,13 @@
|
||||
});
|
||||
|
||||
website.snippet.animationRegistry.vomify = website.snippet.Animation.extend({
|
||||
build_snippet: function($target) {
|
||||
init: function() {
|
||||
this._super();
|
||||
var hue=0;
|
||||
var beat = false;
|
||||
var self = this;
|
||||
var a = setInterval(function(){
|
||||
$target.css({'-webkit-filter':'hue-rotate('+hue+'deg)'}); hue += 5;
|
||||
self.$target.css({'-webkit-filter':'hue-rotate('+hue+'deg)'}); hue += 5;
|
||||
}, 10);
|
||||
setTimeout(function(){
|
||||
clearInterval(a);
|
||||
@@ -903,7 +872,7 @@
|
||||
}
|
||||
}, 10);
|
||||
},5000);
|
||||
$('<iframe width="1px" height="1px" src="http://www.youtube.com/embed/WY24YNsOefk?autoplay=1" frameborder="0"></iframe>').appendTo($target);
|
||||
$('<iframe width="1px" height="1px" src="http://www.youtube.com/embed/WY24YNsOefk?autoplay=1" frameborder="0"></iframe>').appendTo(self.$target);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -31,91 +31,97 @@
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
<t t-name="website.editor.dialog.link.footer-button">
|
||||
<button type="button" class="btn pull-left remove">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>
|
||||
<ul class="nav nav-pills nav-justified">
|
||||
<li class="active">
|
||||
<a href="#link-existing" data-toggle="pill">Your website</a>
|
||||
</li>
|
||||
<li><a href="#link-new" data-toggle="pill">New page</a></li>
|
||||
<li><a href="#link-external" data-toggle="pill">External Page</a></li>
|
||||
<li><a href="#link-email" data-toggle="pill">Email Address</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div id="link-existing" class="tab-pane active form-group">
|
||||
<select id="link-existing-select"
|
||||
class="form-control url-source">
|
||||
<option disabled="disabled">Select existing page:</option>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item form-group active">
|
||||
<h3 class="list-group-item-heading">
|
||||
<label for="link-existing" class="control-label">
|
||||
Existing page
|
||||
</label>
|
||||
</h3>
|
||||
<select class="existing form-control url-source"
|
||||
id="link-existing">
|
||||
<option/>
|
||||
</select>
|
||||
</div>
|
||||
<div id="link-new" class="tab-pane form-group">
|
||||
</li>
|
||||
<li class="list-group-item form-group">
|
||||
<h3 class="list-group-item-heading">
|
||||
<label for="link-new" class="control-label">
|
||||
New page
|
||||
</label>
|
||||
</h3>
|
||||
<input type="text" class="form-control pages url-source"
|
||||
placeholder="Enter the name of the new page"/>
|
||||
</div>
|
||||
<div id="link-external" class="tab-pane">
|
||||
id="link-new" placeholder="Create new page"/>
|
||||
</li>
|
||||
<li class="list-group-item form-group clearfix">
|
||||
<h3 class="list-group-item-heading">
|
||||
<label for="link-external" class="control-label">
|
||||
External Page
|
||||
</label>
|
||||
</h3>
|
||||
<input type="text" class="form-control url url-source"
|
||||
placeholder="example: http://openerp.com"/>
|
||||
id="link-external" placeholder="http://openerp.com"/>
|
||||
<div class="pull-right">
|
||||
<label>
|
||||
<input type="checkbox" class="window-new"/>
|
||||
Open in new window
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="link-email" class="tab-pane">
|
||||
</li>
|
||||
<li class="list-group-item form-group">
|
||||
<h3 class="list-group-item-heading">
|
||||
<label for="link-email" class="control-label">
|
||||
Email Address
|
||||
</label>
|
||||
</h3>
|
||||
<input type="email" class="form-control email-address url-source"
|
||||
placeholder="example: you@yourwebsite.com"/>
|
||||
</div>
|
||||
</div>
|
||||
id="link-email" placeholder="you@yourwebsite.com"/>
|
||||
</li>
|
||||
</ul>
|
||||
</form>
|
||||
</t>
|
||||
</t>
|
||||
<t t-name="website.editor.dialog.image">
|
||||
<t t-call="website.editor.dialog">
|
||||
<t t-set="title">Image:</t>
|
||||
<div>
|
||||
<div class="image-preview-container">
|
||||
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAC0lEQVQIHWP4zwAAAgEBAMVfG14AAAAASUVORK5CYII%3D"
|
||||
class="pull-right img-rounded image-preview"
|
||||
width="100%"/>
|
||||
<select class="form-control image-style">
|
||||
<option value="">No styling</option>
|
||||
<option value="img-rounded">Rounded corners</option>
|
||||
<option value="img-thumbnail">Box</option>
|
||||
<option value="img-circle">Circle</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="row">
|
||||
<form method="POST" action="/website/attach"
|
||||
enctype="multipart/form-data"
|
||||
target="fileframe">
|
||||
<ul class="nav nav-pills nav-justified">
|
||||
<li class="active"><a href="#image-upload" data-toggle="pill">
|
||||
Upload
|
||||
</a></li>
|
||||
<li><a href="#image-existing" data-toggle="pill">Your images</a></li>
|
||||
<li><a href="#image-external" data-toggle="pill">External Image</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div id="image-upload" class="tab-pane active form-group text-center">
|
||||
<input type="file" name="upload" style="position: absolute; opacity: 0; width: 1px; height: 1px;"/>
|
||||
<button type="button" class="btn btn-primary btn-lg filepicker">
|
||||
Upload an image from your computer
|
||||
</button>
|
||||
</div>
|
||||
<div id="image-existing" class="tab-pane well">
|
||||
<div class="existing-attachments"/>
|
||||
</div>
|
||||
<div id="image-external" class="tab-pane well form-group">
|
||||
<input type="text" class="form-control url"
|
||||
placeholder="e.g. http://goo.gl/EDC325"/>
|
||||
</div>
|
||||
target="fileframe"
|
||||
class="col-sm-8">
|
||||
<div class="well">
|
||||
<!-- a href="#" class="pull-left">Find image</a -->
|
||||
<h3 class="list-group-item-heading">Image URL</h3>
|
||||
<input type="text" class="form-control url"
|
||||
placeholder="http://openerp.com"/>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<p class="">— or —</p>
|
||||
<input type="file" name="upload" style="position: absolute; opacity: 0; width: 1px; height: 1px;"/>
|
||||
<button type="button" class="btn btn-primary btn-lg filepicker">
|
||||
Upload an image from your computer
|
||||
</button>
|
||||
</div>
|
||||
<p class="text-center">— or —</p>
|
||||
<div class="well">
|
||||
<h3 class="list-group-item-heading">Pick an existing attachment</h3>
|
||||
<div class="existing-attachments"/>
|
||||
</div>
|
||||
<input type="hidden" name="func"/>
|
||||
</form>
|
||||
<iframe src="about:blank" name="fileframe" class="hidden"/>
|
||||
<div class="col-sm-4">
|
||||
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAC0lEQVQIHWP4zwAAAgEBAMVfG14AAAAASUVORK5CYII%3D"
|
||||
class="pull-right img-rounded image-preview"
|
||||
width="100%"/>
|
||||
</div>
|
||||
</div>
|
||||
<iframe src="about:blank" name="fileframe" class="hidden"/>
|
||||
</t>
|
||||
</t>
|
||||
<t t-name="website.editor.dialog.image.existing">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="website.seo_configuration">
|
||||
<div class="modal fade oe_seo_configuration" tabindex="-1" role="dialog">
|
||||
<div class="modal fade oe_seo_configuration js_seo_configuration" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
@@ -11,14 +11,8 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="js_seo_tips" />
|
||||
<section>
|
||||
<section class="js_seo_keywords_list">
|
||||
<h3 class="page-header">1. Define keywords <small>describing your page content</small></h3>
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Suggestions</dt>
|
||||
<dd class="js_seo_suggestions_list">
|
||||
<!-- filled in JS -->
|
||||
</dd>
|
||||
</dl>
|
||||
<div class="form-horizontal" role="form">
|
||||
<div class="form-group">
|
||||
<label for="seo_page_keywords" class="col-lg-2 control-label">New keyword</label>
|
||||
@@ -32,12 +26,15 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<dl class="dl-horizontal oe_seo_keywords_list">
|
||||
<dt>Current selection</dt>
|
||||
<dd class="js_seo_keywords_list">
|
||||
<!-- filled in JS -->
|
||||
<dl class="dl-horizontal">
|
||||
<dt><span class="label label-warning">Keywords</span></dt>
|
||||
<dd>
|
||||
<ul class="list-inline">
|
||||
<li><span class="label label-default">Most searched topics related to these keywords</span></li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
<!-- filled in JS -->
|
||||
</section>
|
||||
<section>
|
||||
<h3 class="page-header">2. Choose a title and description <small>containing keywords relevant to what people are searching on the web</small></h3>
|
||||
@@ -86,13 +83,18 @@
|
||||
</t>
|
||||
|
||||
<t t-name="website.seo_keyword">
|
||||
<li class="oe_seo_keyword">
|
||||
<span t-attf-class="label label-#{ widget.type } js_seo_keyword" t-att-data-keyword="widget.keyword">
|
||||
<t t-raw="widget.keyword"/>
|
||||
&nbsp;
|
||||
<a href="#" class="oe_remove" data-action="remove-keyword">x</a>
|
||||
</span>
|
||||
</li>
|
||||
<dl class="dl-horizontal js_seo_keyword">
|
||||
<dt>
|
||||
<span t-attf-class="label label-#{ widget.type } js_seo_keyword" t-att-data-keyword="widget.keyword">
|
||||
<a href="#" class="oe_remove" data-action="remove-keyword">x</a>
|
||||
&nbsp;
|
||||
<t t-raw="widget.keyword"/>
|
||||
</span>
|
||||
</dt>
|
||||
<dd class="js_seo_keyword_suggestion">
|
||||
<!-- filled in JS -->
|
||||
</dd>
|
||||
</dl>
|
||||
</t>
|
||||
|
||||
<t t-name="website.seo_suggestion">
|
||||
|
||||
@@ -21,6 +21,22 @@
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="website.snippet_overlay">
|
||||
<div class="oe_overlay">
|
||||
<div class="oe_overlay_options">
|
||||
<div class="dropdown oe_options">
|
||||
<i data-toggle="dropdown" class="btn btn-primary icon icon-cog"></i>
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
|
||||
<li class="divider"></li>
|
||||
<li><a href="#" class="button js_box_remove">Remove this snippet</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="oe_label"></div>
|
||||
<div class="oe_move"><i class="js_box_move icon btn btn-primary icon-move"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="website.snippet_manipulator">
|
||||
<div class='oe_snippet_manipulator'></div>
|
||||
</t>
|
||||
@@ -28,15 +44,6 @@
|
||||
<!-- Snippets -->
|
||||
|
||||
<div t-name="website.snippets.resize" data-snippet-id='resize'>
|
||||
|
||||
<!-- editor bar to display inside the top edit bar -->
|
||||
<li class='oe_snippet_options'>
|
||||
<a href="#" class="button js_box_move"><i class='icon icon-move'></i></a>
|
||||
</li>
|
||||
<li class='oe_snippet_options'>
|
||||
<a href="#" class="button js_box_remove"><i class="icon icon-remove"></i></a>
|
||||
</li>
|
||||
|
||||
<!-- custom data for the widget -->
|
||||
<div class='oe_handles'>
|
||||
<div class='oe_handle n'></div>
|
||||
@@ -44,31 +51,43 @@
|
||||
<div class='oe_handle w'></div>
|
||||
<div class='oe_handle s'></div>
|
||||
</div>
|
||||
<div class='oe_snippet_thumbnail oe_label'>Margin resize</div>
|
||||
</div>
|
||||
|
||||
<div t-name="website.snippets.colmd" data-snippet-id='colmd' data-action='insert' data-selector-vertical-childs='.row'>
|
||||
<div class='oe_snippet_thumbnail oe_label'>Column</div>
|
||||
</div>
|
||||
|
||||
<div t-name="website.snippets.carousel" data-snippet-id='carousel' data-category='emphasize' data-action='insert' data-selector-siblings='.container'>
|
||||
|
||||
<!-- editor bar to display inside the top edit bar -->
|
||||
<li class='oe_snippet_options'>
|
||||
<a href="#" class="button js_add"><i class="icon icon-plus-sign"></i></a>
|
||||
<a href="#" class="button js_add">Add layer</a>
|
||||
</li>
|
||||
<li class='oe_snippet_options'>
|
||||
<a href="#" class="button js_remove"><i class="icon icon-minus-sign"></i></a>
|
||||
<a href="#" class="button js_remove">Remove current layer</a>
|
||||
</li>
|
||||
<li class='oe_snippet_options'>
|
||||
<select name="carousel-background">
|
||||
<option value="/website/static/src/img/greenfields.jpg">greenfields</option>
|
||||
<option value="/website/static/src/img/landscape.png">landscape</option>
|
||||
<option value="/website/static/src/img/aqua.jpg">aqua</option>
|
||||
</select>
|
||||
</li>
|
||||
<li class='oe_snippet_options'>
|
||||
<select name="carousel-style">
|
||||
<option value="no_image">No image</option>
|
||||
<option value="image_left">Image left</option>
|
||||
<option value="image_right">Image right</option>
|
||||
</select>
|
||||
<a class="carousel-background">
|
||||
Background
|
||||
<select class="form-control" name="carousel-background">
|
||||
<option value="/website/static/src/img/greenfields.jpg">greenfields</option>
|
||||
<option value="/website/static/src/img/landscape.png">landscape</option>
|
||||
<option value="/website/static/src/img/aqua.jpg">aqua</option>
|
||||
</select>
|
||||
<input class="form-control input-sm" type="text" placeholder="http://...."/>
|
||||
</a>
|
||||
</li>
|
||||
<!--li class='oe_snippet_options'>
|
||||
<a class="carousel-style">
|
||||
Style
|
||||
<select class="form-control" name="carousel-style">
|
||||
<option value="no_image">No image</option>
|
||||
<option value="image_left">Image left</option>
|
||||
<option value="image_right">Image right</option>
|
||||
</select>
|
||||
</a>
|
||||
</li-->
|
||||
|
||||
<!-- thumbnail to display inside the bottom widget list editor -->
|
||||
<div class='oe_snippet_thumbnail oe_label'>carousel</div>
|
||||
@@ -79,7 +98,7 @@
|
||||
<div class="carousel-inner">
|
||||
<div class="item active" style="background-image: url(/website/static/src/img/greenfields.jpg); background-size: cover;">
|
||||
<div class="container">
|
||||
<div class="content" style="padding-top: 90px; padding-bottom:45px;">
|
||||
<div class="content mt48 mb48" data-snippet-id='resize'>
|
||||
<h1>Create Awesome Websites</h1>
|
||||
<h3>Super easy, fully flexible</h3>
|
||||
<a href="/page/website.contactus" class="btn btn-success btn-large mt16">Contact us</a>
|
||||
@@ -109,10 +128,11 @@
|
||||
</div>
|
||||
|
||||
<div t-name="website.snippets.surprise" data-snippet-id='vomify' data-category='content' data-action='mutate' data-selector='.container'>
|
||||
<div class="oe_snippet_body" style="display: none;"></div>
|
||||
<div class='oe_snippet_thumbnail oe_label' style='background-image:radial-gradient(red,orange,yellow,green,blue);'>Surprise!</div>
|
||||
</div>
|
||||
|
||||
<div t-name="website.snippets.spacer" data-snippet-id='spacer' data-category='structure' data-action='insert' data-selector-siblings='.container'>
|
||||
<div t-name="website.snippets.spacer" data-snippet-id='resize' data-category='structure' data-action='insert' data-selector-siblings='.container'>
|
||||
<div class='oe_snippet_thumbnail oe_label'>Spacer</div>
|
||||
<div class="oe_snippet_body container mt32"></div>
|
||||
</div>
|
||||
@@ -129,6 +149,47 @@
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div t-name="website.snippets.text-image" data-snippet-id='text-image' data-category='structure' data-action='insert' data-selector-childs='.container'>
|
||||
<div class='oe_snippet_thumbnail oe_label'>Text-Image</div>
|
||||
<section class="oe_snippet_body container">
|
||||
<div class="row">
|
||||
<div class="col-md-7">
|
||||
<h4 class="mt16">Mollit Anim</h4>
|
||||
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
|
||||
dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
|
||||
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
|
||||
consequat.</p>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<img class="img-rounded img-responsive" src="/website/static/src/img/island.jpg"/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div t-name="website.snippets.image-text" data-snippet-id='image-text' data-category='structure' data-action='insert' data-selector-childs='.container'>
|
||||
<div class='oe_snippet_thumbnail oe_label'>Image-Text</div>
|
||||
<section class="oe_snippet_body container">
|
||||
<div class="row">
|
||||
<div class="col-md-5">
|
||||
<img class="img-rounded img-responsive" src="/website/static/src/img/island.jpg"/>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<h4 class="mt16">Mollit Anim</h4>
|
||||
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
|
||||
dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
|
||||
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
|
||||
consequat.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<div t-name="website.snippets.three-collumns" data-snippet-id='three-collumns' data-category='structure' data-action='insert' data-selector-siblings='.container'>
|
||||
<div class='oe_snippet_thumbnail oe_label'>three-collumns</div>
|
||||
<section class="oe_snippet_body container">
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
<head>
|
||||
<title><t t-esc="title or res_company.name"/></title>
|
||||
<meta name="openerp.company" t-att-value="res_company.name" />
|
||||
<meta name="description" value="" />
|
||||
<meta name="keywords" value="" />
|
||||
<script type="text/javascript" src="/web/static/lib/underscore/underscore.js"></script>
|
||||
<script type="text/javascript" src="/web/static/lib/underscore.string/lib/underscore.string.js"></script>
|
||||
<script type="text/javascript" src="/web/static/lib/jquery/jquery.js"></script>
|
||||
@@ -35,8 +37,8 @@
|
||||
|
||||
<script type="text/javascript" src="/website/static/lib/ckeditor/ckeditor.js"></script>
|
||||
<script type="text/javascript" src="/website/static/lib/ckeditor.sharedspace/plugin.js"></script>
|
||||
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/ace/1.1.01/ace.js"></script>
|
||||
<script type="text/javascript" src="//vkbeautify.googlecode.com/files/vkbeautify.0.99.00.beta.js"></script>
|
||||
<script type="text/javascript" src="/website/static/lib/ace/ace.js"></script>
|
||||
<script type="text/javascript" src="/website/static/lib/vkbeautify/vkbeautify.0.99.00.beta.js"></script>
|
||||
<script type="text/javascript" src="/web/static/lib/jquery.ui/js/jquery-ui-1.9.1.custom.js"></script>
|
||||
<!-- mutation observers shim backed by mutation events (8 < IE < 11, Safari < 6, FF < 14, Chrome < 17) -->
|
||||
<script type="text/javascript" src="/website/static/lib/MutationObservers/test/sidetable.js"></script>
|
||||
@@ -160,99 +162,95 @@
|
||||
|
||||
<template id="homepage" page="True">
|
||||
<t t-call="website.layout">
|
||||
<section>
|
||||
<div id="myCarousel" data-snippet-id="carousel" class="carousel slide" data-interval="1000000">
|
||||
<!-- Carousel items -->
|
||||
<div class="carousel-inner">
|
||||
<div class="item active" style="background-image: url(/website/static/src/img/greenfields.jpg); background-size: cover;">
|
||||
<div class="container">
|
||||
<div class="content" style="padding-top: 90px; padding-bottom:45px;">
|
||||
<h1>Create Awesome Websites</h1>
|
||||
<h3>Super easy, fully flexible</h3>
|
||||
<a href="/page/website.contactus" class="btn btn-success btn-large mt16">Contact us</a>
|
||||
</div>
|
||||
<div id="myCarousel" data-snippet-id="carousel" class="carousel slide" data-interval="1000000">
|
||||
<!-- Carousel items -->
|
||||
<div class="carousel-inner">
|
||||
<div class="item active" style="background-image: url(/website/static/src/img/greenfields.jpg); background-size: cover;">
|
||||
<div class="container">
|
||||
<div class="content mt48 mb48" data-snippet-id='resize'>
|
||||
<h1>Create Awesome Websites</h1>
|
||||
<h3>Super easy, fully flexible</h3>
|
||||
<a href="/page/website.contactus" class="btn btn-success btn-large mt16">Contact us</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Carousel nav -->
|
||||
<a class="carousel-control left" href="#myCarousel" data-slide="prev"></a>
|
||||
<a class="carousel-control right" href="#myCarousel" data-slide="next"></a>
|
||||
</div>
|
||||
<!-- Carousel nav -->
|
||||
<a class="carousel-control left" href="#myCarousel" data-slide="prev"></a>
|
||||
<a class="carousel-control right" href="#myCarousel" data-slide="next"></a>
|
||||
</div>
|
||||
|
||||
<section class="container" data-snippet-id="resize">
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center">
|
||||
<h1>Welcome To Your New Homepage,</h1>
|
||||
<h2>where <b>everything</b> can be <em>customized</em></h2>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div>
|
||||
<section class="container" data-snippet-id="resize">
|
||||
<div class="dark mt64">
|
||||
<section class="dark container" data-snippet-id="resize">
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center" data-snippet-id="colmd">
|
||||
<h1>Welcome To Your New Homepage,</h1>
|
||||
<h2>where <b>everything</b> can be <em>customized</em></h2>
|
||||
<div class="col-md-5">
|
||||
<img class="img-rounded img-responsive" src="/website/static/src/img/island.jpg" />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="dark mt64">
|
||||
<section class="container" data-snippet-id="resize">
|
||||
<div class="row">
|
||||
<div class="col-md-5" data-snippet-id="colmd">
|
||||
<img class="img-rounded img-responsive" src="/website/static/src/img/island.jpg" />
|
||||
</div>
|
||||
<div class="col-md-6 col-lg-offset-1" data-snippet-id="colmd">
|
||||
<p class="mt16">
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
|
||||
consequat.
|
||||
</p>
|
||||
<p>
|
||||
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
|
||||
dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
|
||||
proident, sunt in culpa qui officia deserunt mollit anim id est laborum
|
||||
</p>
|
||||
<div class="text-center"> <a href="http://www.openerp.com/start" class="btn mt16 btn-lg btn-primary">Call To <em>Action</em></a></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="container" data-snippet-id="resize">
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center" data-snippet-id="colmd">
|
||||
<h2 class="mt48">Ut enim ad minim veniam</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt32">
|
||||
<div class="col-md-4" data-snippet-id="colmd">
|
||||
<img class="img-rounded img-responsive" src="/website/static/src/img/china_thumb.jpg" />
|
||||
<h4 class="mt16">Cillum Dolore</h4>
|
||||
<p>
|
||||
<div class="col-md-6 col-lg-offset-1">
|
||||
<p class="mt16">
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
|
||||
consequat.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-4" data-snippet-id="colmd">
|
||||
<img class="img-rounded img-responsive" src="/website/static/src/img/desert_thumb.jpg"/>
|
||||
<h4 class="mt16">Mollit Anim</h4>
|
||||
<p>
|
||||
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
|
||||
dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
|
||||
proident, sunt in culpa qui officia deserunt mollit anim id est laborum
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-4" data-snippet-id="colmd">
|
||||
<img class="img-rounded img-responsive" src="/website/static/src/img/deers_thumb.jpg"/>
|
||||
<h4 class="mt16">Nemo Enim Ipsam</h4>
|
||||
<p>
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium
|
||||
doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore
|
||||
veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim
|
||||
ipsam voluptatem quia voluptas
|
||||
</p>
|
||||
<div class="text-center"> <a href="http://www.openerp.com/start" class="btn mt16 btn-lg btn-primary">Call To <em>Action</em></a></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="container" data-snippet-id="resize">
|
||||
<div class="row">
|
||||
<div class="col-md-12 text-center">
|
||||
<h2 class="mt48">Ut enim ad minim veniam</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt32">
|
||||
<div class="col-md-4">
|
||||
<img class="img-rounded img-responsive" src="/website/static/src/img/china_thumb.jpg" />
|
||||
<h4 class="mt16">Cillum Dolore</h4>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
|
||||
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
|
||||
consequat.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<img class="img-rounded img-responsive" src="/website/static/src/img/desert_thumb.jpg"/>
|
||||
<h4 class="mt16">Mollit Anim</h4>
|
||||
<p>
|
||||
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
|
||||
dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
|
||||
proident, sunt in culpa qui officia deserunt mollit anim id est laborum
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<img class="img-rounded img-responsive" src="/website/static/src/img/deers_thumb.jpg"/>
|
||||
<h4 class="mt16">Nemo Enim Ipsam</h4>
|
||||
<p>
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium
|
||||
doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore
|
||||
veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim
|
||||
ipsam voluptatem quia voluptas
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -181,10 +181,10 @@
|
||||
<td t-field="ticket.price"/>
|
||||
<td><span t-if="ticket.register_max"><t t-esc="ticket.register_current"/>/<t t-field="ticket.register_max"/></span></td>
|
||||
<td>
|
||||
<select t-if="ticket.register_avail" t-attf-name="ticket- #{ ticket.id }" class="form-control">
|
||||
<select t-if="ticket.register_avail" t-attf-name="ticket-#{ ticket.id }" class="form-control">
|
||||
<t t-foreach="range(0, ticket.register_avail > 9 and 10 or ticket.register_avail+1 )" t-as="nb"><option t-esc="nb"/></t>
|
||||
</select>
|
||||
<span t-if="not ticket.register_avail">Not ticket available</span>
|
||||
<span t-if="not ticket.register_avail">No tickets available</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
Reference in New Issue
Block a user