merge trunk

bzr revid: nicolas.vanhoren@openerp.com-20120524115141-d8tgll1dl7fsbz0o
This commit is contained in:
niv-openerp 2012-05-24 13:51:41 +02:00
commit c6b01a2c03
34 changed files with 4094 additions and 5281 deletions

View File

@ -36,19 +36,6 @@
"static/lib/underscore/underscore.string.js", "static/lib/underscore/underscore.string.js",
"static/lib/backbone/backbone.js", "static/lib/backbone/backbone.js",
"static/lib/visualsearch/lib/js/visualsearch.js",
"static/lib/visualsearch/lib/js/utils/backbone_extensions.js",
"static/lib/visualsearch/lib/js/utils/hotkeys.js",
"static/lib/visualsearch/lib/js/utils/inflector.js",
"static/lib/visualsearch/lib/js/utils/jquery_extensions.js",
"static/lib/visualsearch/lib/js/utils/search_parser.js",
"static/lib/visualsearch/lib/js/models/search_facets.js",
"static/lib/visualsearch/lib/js/models/search_query.js",
"static/lib/visualsearch/lib/js/templates/templates.js",
"static/lib/visualsearch/lib/js/views/search_facet.js",
"static/lib/visualsearch/lib/js/views/search_input.js",
"static/lib/visualsearch/lib/js/views/search_box.js",
"static/lib/labjs/LAB.src.js", "static/lib/labjs/LAB.src.js",
"static/lib/py.js/lib/py.js", "static/lib/py.js/lib/py.js",
"static/src/js/boot.js", "static/src/js/boot.js",
@ -74,9 +61,6 @@
"static/lib/jquery.ui.timepicker/css/jquery-ui-timepicker-addon.css", "static/lib/jquery.ui.timepicker/css/jquery-ui-timepicker-addon.css",
"static/lib/jquery.ui.notify/css/ui.notify.css", "static/lib/jquery.ui.notify/css/ui.notify.css",
"static/lib/jquery.tipsy/tipsy.css", "static/lib/jquery.tipsy/tipsy.css",
"static/lib/visualsearch/lib/css/reset.css",
"static/lib/visualsearch/lib/css/workspace.css",
"static/lib/visualsearch/lib/css/icons.css",
# "static/src/css/base_old.css", # "static/src/css/base_old.css",
"static/src/css/base.css", "static/src/css/base.css",
"static/src/css/data_export.css", "static/src/css/data_export.css",

View File

@ -1287,25 +1287,6 @@ class SearchView(View):
del filter['domain'] del filter['domain']
return filters return filters
@openerpweb.jsonrequest
def save_filter(self, req, model, name, context_to_save, domain):
Model = req.session.model("ir.filters")
ctx = common.nonliterals.CompoundContext(context_to_save)
ctx.session = req.session
ctx = ctx.evaluate()
domain = common.nonliterals.CompoundDomain(domain)
domain.session = req.session
domain = domain.evaluate()
uid = req.session._uid
context = req.session.eval_context(req.context)
to_return = Model.create_or_replace({"context": ctx,
"domain": domain,
"model_id": model,
"name": name,
"user_id": uid
}, context)
return to_return
@openerpweb.jsonrequest @openerpweb.jsonrequest
def add_to_dashboard(self, req, menu_id, action_id, context_to_save, domain, view_mode, name=''): def add_to_dashboard(self, req, menu_id, action_id, context_to_save, domain, view_mode, name=''):
ctx = common.nonliterals.CompoundContext(context_to_save) ctx = common.nonliterals.CompoundContext(context_to_save)

View File

@ -4,7 +4,7 @@
// TODO: t-set + t-value + children node == scoped variable ? // TODO: t-set + t-value + children node == scoped variable ?
var QWeb2 = { var QWeb2 = {
expressions_cache: {}, expressions_cache: {},
RESERVED_WORDS: 'true,false,NaN,null,undefined,debugger,console,in,instanceof,new,function,return,this,typeof,eval,Math,RegExp,Array,Object,Date'.split(','), RESERVED_WORDS: 'true,false,NaN,null,undefined,debugger,console,in,instanceof,new,function,return,this,typeof,eval,void,Math,RegExp,Array,Object,Date'.split(','),
ACTIONS_PRECEDENCE: 'foreach,if,call,set,esc,escf,raw,rawf,js,debug,log'.split(','), ACTIONS_PRECEDENCE: 'foreach,if,call,set,esc,escf,raw,rawf,js,debug,log'.split(','),
WORD_REPLACEMENT: { WORD_REPLACEMENT: {
'and': '&&', 'and': '&&',

View File

@ -1,22 +0,0 @@
Copyright (c) 2011 Samuel Clay, @samuelclay, DocumentCloud
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,16 +0,0 @@
__ ___ _ _____ _ _
\ \ / (_) | |/ ____| | | (_)
\ \ / / _ ___ _ _ __ _| | (___ ___ __ _ _ __ ___| |__ _ ___
\ \/ / | / __| | | |/ _` | |\___ \ / _ \/ _` | '__/ __| '_ \ | / __|
\ / | \__ \ |_| | (_| | |____) | __/ (_| | | | (__| | | |_| \__ \
\/ |_|___/\__,_|\__,_|_|_____/ \___|\__,_|_| \___|_| |_(_) |___/
_/ |
|__/
VisualSearch.js enhances ordinary search boxes with the ability to autocomplete
faceted search queries. Specify the facets for completion, along with the
completable values for any facet. You can retrieve the search query as a
structured object, so you don't have to parse the query string yourself.
For documentation, pre-packed downloads, demos, and tests, see:
http://documentcloud.github.com/visualsearch

View File

@ -1,37 +0,0 @@
require 'rubygems'
require 'jammit'
require 'fileutils'
desc "Use Jammit to compile the multiple versions of Visual Search"
task :build do
$VS_MIN = false
Jammit.package!({
:config_path => "assets.yml",
:output_folder => "build"
})
$VS_MIN = true
Jammit.package!({
:config_path => "assets.yml",
:output_folder => "build-min"
})
# Move the JSTs back to lib to accomodate the demo page.
FileUtils.mv("build/visualsearch_templates.js", "lib/js/templates/templates.js")
# Fix image url paths.
['build', 'build-min'].each do |build|
File.open("#{build}/visualsearch.css", 'r+') do |file|
css = file.read
css.gsub!(/url\((.*?)images\/embed\/icons/, 'url(../images/embed/icons')
file.rewind
file.write(css)
file.truncate(css.length)
end
end
end
desc "Build the docco documentation"
task :docs do
sh "docco lib/js/*.js lib/js/**/*.js"
end

View File

@ -1,28 +0,0 @@
embed_assets: datauri
javascript_compressor: closure
template_function: _.template
gzip_assets: <% if $VS_MIN %>on<% else %>off<% end %>
compress_assets: <% if $VS_MIN %>on<% else %>off<% end %>
javascripts:
dependencies:
- vendor/jquery-*.js
- vendor/jquery.ui.core.js
- vendor/jquery.ui.widget.js
- vendor/jquery.ui.position.js
- vendor/jquery.ui.*.js
- vendor/underscore-*.js
- vendor/backbone-*.js
visualsearch:
- lib/js/visualsearch.js
- lib/js/views/*.js
- lib/js/utils/*.js
- lib/js/models/*.js
- lib/js/templates/*.jst
<% unless $VS_MIN %>visualsearch_templates:
- lib/js/templates/*.jst
<% end %>
stylesheets:
visualsearch:
- lib/css/*.css

View File

@ -1,310 +0,0 @@
.VS-search .VS-icon {
background-repeat: no-repeat;
background-position: center center;
vertical-align: middle;
width: 16px; height: 16px;
}
.VS-search .VS-icon-cancel {
width: 11px; height: 11px;
background-position: center 0;
background-image: url("data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAWCAYAAAAW5GZjAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAb9JREFUeNqUUr1qAkEQ3j0khQp6kihaeGgEEa18gTQR0iRY+BaBSMDGwidIEUKqFL6BopgqBAJ5AMFGjUU0d4WHEvwJarvZ77gRIzGYgb1hZr+Z75vZ40IIzqTNZrPj8Xicn0wmmcViEXS73aaqqq+BQODG6/W+A8MBNk3zfDAY3C6Xy0O2ZS6X6zMSiVwHg8FHLjtq7Xb7RQKj7BeTzVCgJ5PJU2U0GhUk7REuMpkMi8fjFggeMeecrVYrFRId0CgTAgDDMFg4HLbA8IjJgHNgGEr0er0fQIphUmZAwdSUADUB4RFDsz3oSMF6CLzZkQqgGebz+Z75dDqNdTqdp13bgDmdTj2VSp0oWHg0Gr2UNH2Z/9o+yMv7K4/HY/C/XhDUfr//jl7QQVT9fp/V63VWqVRYt9tliUSCZbPZg1wux9Lp9PqFeK1Wu9A0DdXz7YM87i0FrVZLs4Fi1wmFQh/NZjOmVKvVgq7rR/QflMtlixGedjwcDlUpMQ9tbzalkAAB2/R297mNW+sT2wUbUnA//V/nYrH4QOBNABUQuFQq3TNMuc82sDVrz41G42yvPeODAwZQ0QzwiJEnzLcAAwBJ6WXlwoBgZAAAAABJRU5ErkJggg==");
cursor: pointer;
}
.VS-search .VS-icon-cancel:hover {
background-position: center -11px;
}
.VS-search .VS-icon-search {
width: 12px; height: 12px;
background-image: url("data:image/png;charset=utf-8;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAUZJREFUeNpUUM2qgmAQzS8NiUgLzTIXLZQW1QuI9AY9QPSW9gQ9QiriwpJQEBVrVWT2d7p2L9xZzDdzZs7M+YYqy/J8Ptu2vd/v4zgeDAaqqk4mE47jar9GnU6nzWbjOA5FUa/Xq0Jns9l8Pud5vkpp58cwAOzhcBhFkeu6GNztdg3D+Db5vo9nOp2iiWGYTqdDCMFe4LquI0aVpGmKR9M0lmUbjQY8YiBJklTb4YkoilBzOBzq9TogeMQIJEmqmlAlo9EIyXa7tSyrKAp4xEBkWUb5q2k8Hh+PR8/zwjCEgufz+aESstvtoKnVan2GgY31kBkEAfT1ej1FUZDiNIIgrFYr9H1ug3teLpfH43G/3/FBUJGu1+s8z8FZLpc0mmiabrfbf5fEumazuVgsTNO8Xq+3242qRNT+G0CMz7IMzH6//xZgAA60tj6rqzxpAAAAAElFTkSuQmCC");
}
/*------------------------------ RESET + DEFAULT STYLES ---------------------------------*/
/*
Eric Meyer's final reset.css
Source: http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/
*/
.VS-search div, .VS-search span, .VS-search a, .VS-search img,
.VS-search ul, .VS-search li, .VS-search form, .VS-search label,
.VS-interface ul, .VS-interface li, .VS-interface {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-weight: inherit;
font-style: inherit;
font-size: 100%;
font-family: inherit;
vertical-align: baseline;
}
.VS-search :focus {
outline: 0;
}
.VS-search {
line-height: 1;
color: black;
}
.VS-search ol, .VS-search ul {
list-style: none;
}
/* ===================== */
/* = General and Reset = */
/* ===================== */
.VS-search {
font-family: Arial, sans-serif;
color: #373737;
font-size: 12px;
}
.VS-search input {
display: block;
border: none;
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
outline: none;
margin: 0; padding: 4px;
background: transparent;
font-size: 16px;
line-height: 20px;
width: 100%;
}
.VS-interface, .VS-search .dialog, .VS-search input {
font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif !important;
line-height: 1.1em;
}
/* ========== */
/* = Layout = */
/* ========== */
.VS-search .VS-search-box {
cursor: text;
position: relative;
background: transparent;
border: 2px solid #ccc;
border-radius: 16px; -webkit-border-radius: 16px; -moz-border-radius: 16px;
background-color: #fafafa;
-webkit-box-shadow: inset 0px 0px 3px #ccc;
-moz-box-shadow: inset 0px 0px 3px #ccc;
box-shadow: inset 0px 0px 3px #ccc;
min-height: 28px;
height: auto;
}
.VS-search .VS-search-box.VS-focus {
border-color: #acf;
-webkit-box-shadow: inset 0px 0px 3px #acf;
-moz-box-shadow: inset 0px 0px 3px #acf;
box-shadow: inset 0px 0px 3px #acf;
}
.VS-search .VS-search-inner {
position: relative;
margin: 0 20px 0 22px;
overflow: hidden;
}
.VS-search input {
width: 100px;
}
.VS-search input,
.VS-search .VS-input-width-tester {
padding: 6px 0;
float: left;
color: #808080;
font: 13px/17px Helvetica, Arial;
}
.VS-search.VS-focus input {
color: #606060;
}
.VS-search .VS-icon-search {
position: absolute;
left: 9px; top: 8px;
}
.VS-search .VS-icon-cancel {
position: absolute;
right: 9px; top: 8px;
}
/* ================ */
/* = Search Facet = */
/* ================ */
.VS-search .search_facet {
float: left;
margin: 0;
padding: 0 0 0 14px;
position: relative;
border: 1px solid transparent;
height: 20px;
margin: 3px -3px 3px 0;
}
.VS-search .search_facet.is_selected {
margin-left: -3px;
-webkit-border-radius: 16px;
-moz-border-radius: 16px;
border-radius: 16px;
background-color: #d2e6fd;
background-image: -moz-linear-gradient(top, #d2e6fd, #b0d1f9); /* FF3.6 */
background-image: -webkit-gradient(linear, left top, left bottom, from(#d2e6fd), to(#b0d1f9)); /* Saf4+, Chrome */
background-image: linear-gradient(top, #d2e6fd, #b0d1f9);
border: 1px solid #6eadf5;
}
.VS-search .search_facet .category {
float: left;
text-transform: uppercase;
font-weight: bold;
font-size: 10px;
color: #808080;
padding: 8px 0 5px;
line-height: 13px;
cursor: pointer;
padding: 4px 0 0;
}
.VS-search .search_facet.is_selected .category {
margin-left: 3px;
}
.VS-search .search_facet .search_facet_input_container {
float: left;
}
.VS-search .search_facet input {
margin: 0;
padding: 0;
color: #000;
font-size: 13px;
line-height: 16px;
padding: 5px 0 5px 4px;
height: 16px;
width: auto;
z-index: 100;
position: relative;
padding-top: 1px;
padding-bottom: 2px;
padding-right: 3px;
}
.VS-search .search_facet.is_editing input,
.VS-search .search_facet.is_selected input {
color: #000;
}
.VS-search .search_facet .search_facet_remove {
position: absolute;
left: 0;
top: 4px;
}
.VS-search .search_facet.is_selected .search_facet_remove {
opacity: 0.4;
left: 3px;
filter: alpha(opacity=40);
background-position: center -11px;
}
.VS-search .search_facet .search_facet_remove:hover {
opacity: 1;
}
.VS-search .search_facet.is_editing .category,
.VS-search .search_facet.is_selected .category {
color: #000;
}
.VS-search .search_facet.search_facet_maybe_delete .category,
.VS-search .search_facet.search_facet_maybe_delete input {
color: darkred;
}
/* ================ */
/* = Search Input = */
/* ================ */
.VS-search .search_input {
height: 28px;
float: left;
margin-left: -1px;
}
.VS-search .search_input input {
padding: 6px 3px 6px 2px;
line-height: 10px;
height: 22px;
margin-top: -4px;
width: 10px;
z-index: 100;
min-width: 4px;
position: relative;
}
.VS-search .search_input.is_editing input {
color: #202020;
}
/* ================ */
/* = Autocomplete = */
/* ================ */
.VS-interface.ui-autocomplete {
position: absolute;
border: 1px solid #C0C0C0;
border-top: 1px solid #D9D9D9;
background-color: #F6F6F6;
cursor: pointer;
z-index: 10000;
padding: 0;
margin: 0;
width: auto;
min-width: 80px;
max-width: 220px;
max-height: 240px;
overflow-y: auto;
overflow-x: hidden;
font-size: 13px;
top: 5px;
opacity: 0.97;
box-shadow: 3px 4px 5px -2px rgba(0, 0, 0, 0.5); -webkit-box-shadow: 3px 4px 5px -2px rgba(0, 0, 0, 0.5); -moz-box-shadow: 3px 4px 5px -2px rgba(0, 0, 0, 0.5);
}
.VS-interface.ui-autocomplete .ui-autocomplete-category {
text-transform: capitalize;
font-size: 11px;
padding: 4px 4px 4px;
border-top: 1px solid #A2A2A2;
border-bottom: 1px solid #A2A2A2;
background-color: #B7B7B7;
text-shadow: 0 -1px 0 #999;
font-weight: bold;
color: white;
cursor: default;
}
.VS-interface.ui-autocomplete .ui-menu-item {
float: none;
}
.VS-interface.ui-autocomplete .ui-menu-item a {
color: #000;
outline: none;
display: block;
padding: 3px 4px 5px;
border-radius: none;
line-height: 1;
background-color: #F8F8F8;
background-image: -moz-linear-gradient(top, #F8F8F8, #F3F3F3); /* FF3.6 */
background-image: -webkit-gradient(linear, left top, left bottom, from(#F8F8F8), to(#F3F3F3)); /* Saf4+, Chrome */
background-image: linear-gradient(top, #F8F8F8, #F3F3F3);
border-top: 1px solid #FAFAFA;
border-bottom: 1px solid #f0f0f0;
}
.VS-interface.ui-autocomplete .ui-menu-item a:active {
outline: none;
}
.VS-interface.ui-autocomplete .ui-menu-item .ui-state-hover {
background-color: #6483F7;
background-image: -moz-linear-gradient(top, #648bF5, #2465f3); /* FF3.6 */
background-image: -webkit-gradient(linear, left top, left bottom, from(#648bF5), to(#2465f3)); /* Saf4+, Chrome */
background-image: linear-gradient(top, #648bF5, #2465f3);
border-top: 1px solid #5b83ec;
border-bottom: 1px solid #1459e9;
border-left: none;
border-right: none;
color: white;
margin: 0;
}
.VS-interface.ui-autocomplete .ui-corner-all {
border-radius: 0;
}
.VS-interface.ui-autocomplete li {
list-style: none;
width: auto;
}

View File

@ -1,310 +0,0 @@
.VS-search .VS-icon {
background-repeat: no-repeat;
background-position: center center;
vertical-align: middle;
width: 16px; height: 16px;
}
.VS-search .VS-icon-cancel {
width: 11px; height: 11px;
background-position: center 0;
background-image: url(../images/embed/icons/cancel_search.png?1311104738);
cursor: pointer;
}
.VS-search .VS-icon-cancel:hover {
background-position: center -11px;
}
.VS-search .VS-icon-search {
width: 12px; height: 12px;
background-image: url(../images/embed/icons/search_glyph.png?1311104738);
}
/*------------------------------ RESET + DEFAULT STYLES ---------------------------------*/
/*
Eric Meyer's final reset.css
Source: http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/
*/
.VS-search div, .VS-search span, .VS-search a, .VS-search img,
.VS-search ul, .VS-search li, .VS-search form, .VS-search label,
.VS-interface ul, .VS-interface li, .VS-interface {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-weight: inherit;
font-style: inherit;
font-size: 100%;
font-family: inherit;
vertical-align: baseline;
}
.VS-search :focus {
outline: 0;
}
.VS-search {
line-height: 1;
color: black;
}
.VS-search ol, .VS-search ul {
list-style: none;
}
/* ===================== */
/* = General and Reset = */
/* ===================== */
.VS-search {
font-family: Arial, sans-serif;
color: #373737;
font-size: 12px;
}
.VS-search input {
display: block;
border: none;
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
outline: none;
margin: 0; padding: 4px;
background: transparent;
font-size: 16px;
line-height: 20px;
width: 100%;
}
.VS-interface, .VS-search .dialog, .VS-search input {
font-family: "Lucida Grande", "Lucida Sans Unicode", Helvetica, Arial, sans-serif !important;
line-height: 1.1em;
}
/* ========== */
/* = Layout = */
/* ========== */
.VS-search .VS-search-box {
cursor: text;
position: relative;
background: transparent;
border: 2px solid #ccc;
border-radius: 16px; -webkit-border-radius: 16px; -moz-border-radius: 16px;
background-color: #fafafa;
-webkit-box-shadow: inset 0px 0px 3px #ccc;
-moz-box-shadow: inset 0px 0px 3px #ccc;
box-shadow: inset 0px 0px 3px #ccc;
min-height: 28px;
height: auto;
}
.VS-search .VS-search-box.VS-focus {
border-color: #acf;
-webkit-box-shadow: inset 0px 0px 3px #acf;
-moz-box-shadow: inset 0px 0px 3px #acf;
box-shadow: inset 0px 0px 3px #acf;
}
.VS-search .VS-search-inner {
position: relative;
margin: 0 20px 0 22px;
overflow: hidden;
}
.VS-search input {
width: 100px;
}
.VS-search input,
.VS-search .VS-input-width-tester {
padding: 6px 0;
float: left;
color: #808080;
font: 13px/17px Helvetica, Arial;
}
.VS-search.VS-focus input {
color: #606060;
}
.VS-search .VS-icon-search {
position: absolute;
left: 9px; top: 8px;
}
.VS-search .VS-icon-cancel {
position: absolute;
right: 9px; top: 8px;
}
/* ================ */
/* = Search Facet = */
/* ================ */
.VS-search .search_facet {
float: left;
margin: 0;
padding: 0 0 0 14px;
position: relative;
border: 1px solid transparent;
height: 20px;
margin: 3px -3px 3px 0;
}
.VS-search .search_facet.is_selected {
margin-left: -3px;
-webkit-border-radius: 16px;
-moz-border-radius: 16px;
border-radius: 16px;
background-color: #d2e6fd;
background-image: -moz-linear-gradient(top, #d2e6fd, #b0d1f9); /* FF3.6 */
background-image: -webkit-gradient(linear, left top, left bottom, from(#d2e6fd), to(#b0d1f9)); /* Saf4+, Chrome */
background-image: linear-gradient(top, #d2e6fd, #b0d1f9);
border: 1px solid #6eadf5;
}
.VS-search .search_facet .category {
float: left;
text-transform: uppercase;
font-weight: bold;
font-size: 10px;
color: #808080;
padding: 8px 0 5px;
line-height: 13px;
cursor: pointer;
padding: 4px 0 0;
}
.VS-search .search_facet.is_selected .category {
margin-left: 3px;
}
.VS-search .search_facet .search_facet_input_container {
float: left;
}
.VS-search .search_facet input {
margin: 0;
padding: 0;
color: #000;
font-size: 13px;
line-height: 16px;
padding: 5px 0 5px 4px;
height: 16px;
width: auto;
z-index: 100;
position: relative;
padding-top: 1px;
padding-bottom: 2px;
padding-right: 3px;
}
.VS-search .search_facet.is_editing input,
.VS-search .search_facet.is_selected input {
color: #000;
}
.VS-search .search_facet .search_facet_remove {
position: absolute;
left: 0;
top: 4px;
}
.VS-search .search_facet.is_selected .search_facet_remove {
opacity: 0.4;
left: 3px;
filter: alpha(opacity=40);
background-position: center -11px;
}
.VS-search .search_facet .search_facet_remove:hover {
opacity: 1;
}
.VS-search .search_facet.is_editing .category,
.VS-search .search_facet.is_selected .category {
color: #000;
}
.VS-search .search_facet.search_facet_maybe_delete .category,
.VS-search .search_facet.search_facet_maybe_delete input {
color: darkred;
}
/* ================ */
/* = Search Input = */
/* ================ */
.VS-search .search_input {
height: 28px;
float: left;
margin-left: -1px;
}
.VS-search .search_input input {
padding: 6px 3px 6px 2px;
line-height: 10px;
height: 22px;
margin-top: -4px;
width: 10px;
z-index: 100;
min-width: 4px;
position: relative;
}
.VS-search .search_input.is_editing input {
color: #202020;
}
/* ================ */
/* = Autocomplete = */
/* ================ */
.VS-interface.ui-autocomplete {
position: absolute;
border: 1px solid #C0C0C0;
border-top: 1px solid #D9D9D9;
background-color: #F6F6F6;
cursor: pointer;
z-index: 10000;
padding: 0;
margin: 0;
width: auto;
min-width: 80px;
max-width: 220px;
max-height: 240px;
overflow-y: auto;
overflow-x: hidden;
font-size: 13px;
top: 5px;
opacity: 0.97;
box-shadow: 3px 4px 5px -2px rgba(0, 0, 0, 0.5); -webkit-box-shadow: 3px 4px 5px -2px rgba(0, 0, 0, 0.5); -moz-box-shadow: 3px 4px 5px -2px rgba(0, 0, 0, 0.5);
}
.VS-interface.ui-autocomplete .ui-autocomplete-category {
text-transform: capitalize;
font-size: 11px;
padding: 4px 4px 4px;
border-top: 1px solid #A2A2A2;
border-bottom: 1px solid #A2A2A2;
background-color: #B7B7B7;
text-shadow: 0 -1px 0 #999;
font-weight: bold;
color: white;
cursor: default;
}
.VS-interface.ui-autocomplete .ui-menu-item {
float: none;
}
.VS-interface.ui-autocomplete .ui-menu-item a {
color: #000;
outline: none;
display: block;
padding: 3px 4px 5px;
border-radius: none;
line-height: 1;
background-color: #F8F8F8;
background-image: -moz-linear-gradient(top, #F8F8F8, #F3F3F3); /* FF3.6 */
background-image: -webkit-gradient(linear, left top, left bottom, from(#F8F8F8), to(#F3F3F3)); /* Saf4+, Chrome */
background-image: linear-gradient(top, #F8F8F8, #F3F3F3);
border-top: 1px solid #FAFAFA;
border-bottom: 1px solid #f0f0f0;
}
.VS-interface.ui-autocomplete .ui-menu-item a:active {
outline: none;
}
.VS-interface.ui-autocomplete .ui-menu-item .ui-state-hover {
background-color: #6483F7;
background-image: -moz-linear-gradient(top, #648bF5, #2465f3); /* FF3.6 */
background-image: -webkit-gradient(linear, left top, left bottom, from(#648bF5), to(#2465f3)); /* Saf4+, Chrome */
background-image: linear-gradient(top, #648bF5, #2465f3);
border-top: 1px solid #5b83ec;
border-bottom: 1px solid #1459e9;
border-left: none;
border-right: none;
color: white;
margin: 0;
}
.VS-interface.ui-autocomplete .ui-corner-all {
border-radius: 0;
}
.VS-interface.ui-autocomplete li {
list-style: none;
width: auto;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,453 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<title>DocumentCloud's VisualSearch.js</title>
<style>
body {
font-size: 16px;
line-height: 24px;
background: #FEF3CA;
color: #022;
height: 100%;
font-family: "Palatino Linotype", "Book Antiqua", Palatino, FreeSerif, serif;
}
div.container {
width: 720px;
margin: 50px 0 50px 50px;
}
p, li {
margin: 16px 0 16px 0;
width: 550px;
}
p.break {
margin-top: 35px;
}
ol {
padding-left: 24px;
}
ol li {
font-weight: bold;
margin-left: 0;
}
a, a:visited {
padding: 0 2px;
text-decoration: none;
background: #f0c095;
color: #252519;
}
a:active, a:hover {
color: #FFF;
background: #C25D00;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 40px;
}
b.header {
font-size: 18px;
}
span.alias {
font-size: 14px;
font-style: italic;
margin-left: 20px;
}
table {
margin: 16px 0; padding: 0;
}
tr, td, th {
margin: 0; padding: 0;
text-align: left;
}
th {
padding: 24px 0 0;
}
tr:first-child th {
padding-top: 0;
}
td {
padding: 6px 15px 6px 0;
}
td.definition {
line-height: 18px;
font-size: 14px;
}
table.downloads td {
padding-left: 18px;
}
.demo-hint {
font-size: 13px;
margin: 0 0 12px 12px;
font-weight: normal;
}
#VS code, #VS pre, #VS tt {
font-family: Monaco, Consolas, "Lucida Console", monospace;
font-size: 12px;
line-height: 18px;
color: #444;
background: none;
}
#VS code {
margin-left: 8px;
padding: 0 0 0 12px;
font-weight: normal;
}
#VS pre {
font-size: 12px;
padding: 2px 0 2px 0;
border-left: 6px solid #829C37;
margin: 12px 0;
}
#search_query {
margin: 18px 0;
opacity: 0;
}
#search_query .raquo {
font-size: 18px;
line-height: 12px;
font-weight: bold;
margin-right: 4px;
}
#search_query2 {
margin: 18px 0;
opacity: 0;
}
#search_query2 .raquo {
font-size: 18px;
line-height: 12px;
font-weight: bold;
margin-right: 4px;
}
</style>
<link rel="stylesheet" href="lib/css/reset.css" type="text/css" media="screen" charset="utf-8">
<link rel="stylesheet" href="lib/css/icons.css" type="text/css" media="screen" charset="utf-8">
<link rel="stylesheet" href="lib/css/workspace.css" type="text/css" media="screen" charset="utf-8">
<script src="vendor/jquery-1.6.1.js" type="text/javascript" charset="utf-8"></script>
<!-- <script src="vendor/backported/jquery-1.4.4.js" type="text/javascript" charset="utf-8"></script> -->
<script src="vendor/jquery.ui.core.js" type="text/javascript" charset="utf-8"></script>
<script src="vendor/jquery.ui.widget.js" type="text/javascript" charset="utf-8"></script>
<script src="vendor/jquery.ui.position.js" type="text/javascript" charset="utf-8"></script>
<script src="vendor/jquery.ui.autocomplete.js" type="text/javascript" charset="utf-8"></script>
<script src="vendor/underscore-1.1.5.js" type="text/javascript" charset="utf-8"></script>
<script src="vendor/backbone-0.5.0.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/js/visualsearch.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/js/views/search_box.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/js/views/search_facet.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/js/views/search_input.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/js/models/search_facets.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/js/models/search_query.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/js/utils/backbone_extensions.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/js/utils/hotkeys.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/js/utils/jquery_extensions.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/js/utils/search_parser.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/js/utils/inflector.js" type="text/javascript" charset="utf-8"></script>
<script src="lib/js/templates/templates.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div class="container" id="VS">
<h1><a href="index.html">VisualSearch.js</a></h1>
<p>
<a href="http://github.com/documentcloud/visualsearch">VisualSearch.js</a>
enhances ordinary search boxes with the ability to autocomplete
faceted search queries. Specify the facets for completion, along with the
completable values for any facet. You can retrieve the search query as a
structured object, so you don't have to parse the query string yourself.
</p>
<p>
<a href="docs/visualsearch.html">The complete annotated source code</a>
is also available.
</p>
<p>
The project is
<a href="http://github.com/documentcloud/visualsearch/">hosted on GitHub</a>.
You can report bugs and discuss features on the
<a href="http://github.com/documentcloud/visualsearch/issues">issues page</a>,
on Freenode in the <tt>#documentcloud</tt> channel,
or send tweets to <a href="http://twitter.com/documentcloud">@documentcloud</a>.
</p>
<p>
<i>VisualSearch.js is an open-source component of <a href="http://documentcloud.org/">DocumentCloud</a>.</i>
</p>
<h2 id="demo">Demo <span class="demo-hint"><i>Try searching for: <b>account</b>, <b>filter</b>, <b>access</b>, <b>title</b>, <b>city</b>, <b>state</b>, or <b>country</b>.</i></span></h2>
<div id="search_box_container"></div>
<div id="search_query">&nbsp;</div>
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
window.visualSearch = VS.init({
container : $('#search_box_container'),
query : 'country: "South Africa" account: 5-samuel title: "Pentagon Papers"',
// query : '',
unquotable : [
'text',
'account',
'filter',
'access'
],
callbacks : {
search : function(query, searchCollection) {
var $query = $('#search_query');
$query.stop().animate({opacity : 1}, {duration: 300, queue: false});
$query.html('<span class="raquo">&raquo;</span> You searched for: <b>' + searchCollection.serialize() + '</b>');
clearTimeout(window.queryHideDelay);
window.queryHideDelay = setTimeout(function() {
$query.animate({
opacity : 0
}, {
duration: 1000,
queue: false
});
}, 2000);
},
valueMatches : function(category, searchTerm, callback) {
switch (category) {
case 'account':
callback([
{ value: '1-amanda', label: 'Amanda' },
{ value: '2-aron', label: 'Aron' },
{ value: '3-eric', label: 'Eric' },
{ value: '4-jeremy', label: 'Jeremy' },
{ value: '5-samuel', label: 'Samuel' },
{ value: '6-scott', label: 'Scott' }
]);
break;
case 'filter':
callback(['published', 'unpublished', 'draft']);
break;
case 'access':
callback(['public', 'private', 'protected']);
break;
case 'title':
callback([
'Pentagon Papers',
'CoffeeScript Manual',
'Laboratory for Object Oriented Thinking',
'A Repository Grows in Brooklyn'
]);
break;
case 'city':
callback([
'Cleveland',
'New York City',
'Brooklyn',
'Manhattan',
'Queens',
'The Bronx',
'Staten Island',
'San Francisco',
'Los Angeles',
'Seattle',
'London',
'Portland',
'Chicago',
'Boston'
])
break;
case 'state':
callback([
"Alabama", "Alaska", "Arizona", "Arkansas", "California",
"Colorado", "Connecticut", "Delaware", "District of Columbia", "Florida",
"Georgia", "Guam", "Hawaii", "Idaho", "Illinois",
"Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana",
"Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota",
"Mississippi", "Missouri", "Montana", "Nebraska", "Nevada",
"New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina",
"North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania",
"Puerto Rico", "Rhode Island", "South Carolina", "South Dakota", "Tennessee",
"Texas", "Utah", "Vermont", "Virginia", "Virgin Islands",
"Washington", "West Virginia", "Wisconsin", "Wyoming"
]);
break
case 'country':
callback([
"China", "India", "United States", "Indonesia", "Brazil",
"Pakistan", "Bangladesh", "Nigeria", "Russia", "Japan",
"Mexico", "Philippines", "Vietnam", "Ethiopia", "Egypt",
"Germany", "Turkey", "Iran", "Thailand", "D. R. of Congo",
"France", "United Kingdom", "Italy", "Myanmar", "South Africa",
"South Korea", "Colombia", "Ukraine", "Spain", "Tanzania",
"Sudan", "Kenya", "Argentina", "Poland", "Algeria",
"Canada", "Uganda", "Morocco", "Iraq", "Nepal",
"Peru", "Afghanistan", "Venezuela", "Malaysia", "Uzbekistan",
"Saudi Arabia", "Ghana", "Yemen", "North Korea", "Mozambique",
"Taiwan", "Syria", "Ivory Coast", "Australia", "Romania",
"Sri Lanka", "Madagascar", "Cameroon", "Angola", "Chile",
"Netherlands", "Burkina Faso", "Niger", "Kazakhstan", "Malawi",
"Cambodia", "Guatemala", "Ecuador", "Mali", "Zambia",
"Senegal", "Zimbabwe", "Chad", "Cuba", "Greece",
"Portugal", "Belgium", "Czech Republic", "Tunisia", "Guinea",
"Rwanda", "Dominican Republic", "Haiti", "Bolivia", "Hungary",
"Belarus", "Somalia", "Sweden", "Benin", "Azerbaijan",
"Burundi", "Austria", "Honduras", "Switzerland", "Bulgaria",
"Serbia", "Israel", "Tajikistan", "Hong Kong", "Papua New Guinea",
"Togo", "Libya", "Jordan", "Paraguay", "Laos",
"El Salvador", "Sierra Leone", "Nicaragua", "Kyrgyzstan", "Denmark",
"Slovakia", "Finland", "Eritrea", "Turkmenistan"
], {preserveOrder: true});
break;
}
},
facetMatches : function(callback) {
callback([
'account', 'filter', 'access', 'title',
{ label: 'city', category: 'location' },
{ label: 'address', category: 'location' },
{ label: 'country', category: 'location' },
{ label: 'state', category: 'location' },
]);
}
}
});
});
</script>
<div id="search_box_container2"></div>
<div id="search_query2">&nbsp;</div>
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
var visualSearch = VS.init({
container : $('#search_box_container2'),
query : '',
// query : '',
unquotable : [
'text',
'account',
'filter',
'access'
],
callbacks : {
search : function(query, searchCollection) {
console.log(["query", searchCollection.facets(), query]);
var $query = $('#search_query2');
$query.stop().animate({opacity : 1}, {duration: 300, queue: false});
$query.html('<span class="raquo">&raquo;</span> You searched for: <b>' + searchCollection.serialize() + '</b>');
clearTimeout(window.queryHideDelay2);
window.queryHideDelay2 = setTimeout(function() {
$query.animate({
opacity : 0
}, {
duration: 1000,
queue: false
});
}, 2000);
},
valueMatches : function(category, searchTerm, callback) {
switch (category) {
case 'account':
callback([
{ value: '1-amanda', label: 'Amanda' },
{ value: '2-aron', label: 'Aron' },
{ value: '3-eric', label: 'Eric' },
{ value: '4-jeremy', label: 'Jeremy' },
{ value: '5-samuel', label: 'Samuel' },
{ value: '6-scott', label: 'Scott' }
]);
break;
case 'filter':
callback(['published', 'unpublished', 'draft']);
break;
case 'access':
callback(['public', 'private', 'protected']);
break;
case 'title':
callback([
'Pentagon Papers',
'CoffeeScript Manual',
'Laboratory for Object Oriented Thinking',
'A Repository Grows in Brooklyn'
]);
break;
case 'city':
callback([
'Cleveland',
'New York City',
'Brooklyn',
'Manhattan',
'Queens',
'The Bronx',
'Staten Island',
'San Francisco',
'Los Angeles',
'Seattle',
'London',
'Portland',
'Chicago',
'Boston'
])
break;
case 'state':
callback([
"Alabama", "Alaska", "Arizona", "Arkansas", "California",
"Colorado", "Connecticut", "Delaware", "District of Columbia", "Florida",
"Georgia", "Guam", "Hawaii", "Idaho", "Illinois",
"Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana",
"Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota",
"Mississippi", "Missouri", "Montana", "Nebraska", "Nevada",
"New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina",
"North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania",
"Puerto Rico", "Rhode Island", "South Carolina", "South Dakota", "Tennessee",
"Texas", "Utah", "Vermont", "Virginia", "Virgin Islands",
"Washington", "West Virginia", "Wisconsin", "Wyoming"
]);
break
case 'country':
callback([
"China", "India", "United States", "Indonesia", "Brazil",
"Pakistan", "Bangladesh", "Nigeria", "Russia", "Japan",
"Mexico", "Philippines", "Vietnam", "Ethiopia", "Egypt",
"Germany", "Turkey", "Iran", "Thailand", "D. R. of Congo",
"France", "United Kingdom", "Italy", "Myanmar", "South Africa",
"South Korea", "Colombia", "Ukraine", "Spain", "Tanzania",
"Sudan", "Kenya", "Argentina", "Poland", "Algeria",
"Canada", "Uganda", "Morocco", "Iraq", "Nepal",
"Peru", "Afghanistan", "Venezuela", "Malaysia", "Uzbekistan",
"Saudi Arabia", "Ghana", "Yemen", "North Korea", "Mozambique",
"Taiwan", "Syria", "Ivory Coast", "Australia", "Romania",
"Sri Lanka", "Madagascar", "Cameroon", "Angola", "Chile",
"Netherlands", "Burkina Faso", "Niger", "Kazakhstan", "Malawi",
"Cambodia", "Guatemala", "Ecuador", "Mali", "Zambia",
"Senegal", "Zimbabwe", "Chad", "Cuba", "Greece",
"Portugal", "Belgium", "Czech Republic", "Tunisia", "Guinea",
"Rwanda", "Dominican Republic", "Haiti", "Bolivia", "Hungary",
"Belarus", "Somalia", "Sweden", "Benin", "Azerbaijan",
"Burundi", "Austria", "Honduras", "Switzerland", "Bulgaria",
"Serbia", "Israel", "Tajikistan", "Hong Kong", "Papua New Guinea",
"Togo", "Libya", "Jordan", "Paraguay", "Laos",
"El Salvador", "Sierra Leone", "Nicaragua", "Kyrgyzstan", "Denmark",
"Slovakia", "Finland", "Eritrea", "Turkmenistan"
]);
break;
}
},
facetMatches : function(callback) {
callback([
'account', 'filter', 'access', 'title',
{ label: 'city', category: 'location' },
{ label: 'address', category: 'location' },
{ label: 'country', category: 'location' },
{ label: 'state', category: 'location' },
], {
preserveOrder: true
});
}
}
});
});
</script>
</div>
</body>
</html>

View File

@ -1,537 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<title>DocumentCloud's VisualSearch.js</title>
<style>
body {
font-size: 16px;
line-height: 24px;
background: #FEF3CA;
height: 100%;
color: #022;
font-family: Arial;
font-family: "Palatino Linotype", "Book Antiqua", Palatino, FreeSerif, serif;
}
div.container {
width: 720px;
margin: 50px 0 50px 50px;
}
p, li {
margin: 16px 0 16px 0;
width: 550px;
}
p.break {
margin-top: 35px;
}
ol {
padding-left: 24px;
}
ol li {
font-weight: bold;
margin-left: 0;
}
a, a:visited {
padding: 0 2px;
text-decoration: none;
background: #f0c095;
color: #252519;
}
a:active, a:hover {
color: #000;
background: #e0a070;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 40px;
}
b.header {
font-size: 18px;
}
span.alias {
font-size: 14px;
font-style: italic;
margin-left: 20px;
}
table {
margin: 16px 0; padding: 0;
}
tr, td, th {
margin: 0; padding: 0;
text-align: left;
}
th {
padding: 24px 0 0;
}
tr:first-child th {
padding-top: 0;
}
td {
padding: 6px 15px 6px 0;
}
td.definition {
line-height: 18px;
font-size: 14px;
}
table.downloads td {
padding-left: 18px;
}
.demo-hint {
font-size: 13px;
margin: 0 0 12px 12px;
font-weight: normal;
}
#VS code, #VS pre, #VS tt {
font-family: Monaco, Consolas, "Lucida Console", monospace;
font-size: 12px;
line-height: 18px;
color: #444;
background: none;
}
#VS code {
margin-left: 8px;
padding: 0 0 0 12px;
font-weight: normal;
}
#VS pre {
font-size: 12px;
padding: 2px 0 2px 0;
border-left: 6px solid #829C37;
margin: 12px 0;
}
#search_query {
margin: 18px 0 -24px;
opacity: 0;
}
#search_query .raquo {
font-size: 18px;
line-height: 12px;
font-weight: bold;
margin-right: 4px;
}
.attribution {
margin: -12px 0 24px;
font-size: 14px;
}
</style>
<link rel="stylesheet" href="build-min/visualsearch-datauri.css" type="text/css" media="screen" charset="utf-8">
<link rel="stylesheet" href="docs/assets/github.css" type="text/css" media="screen" charset="utf-8">
<script src="build-min/dependencies.js" type="text/javascript" charset="utf-8"></script>
<script src="build-min/visualsearch.js" type="text/javascript" charset="utf-8"></script>
<script src="docs/assets/highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="docs/assets/javascript.js" type="text/javascript" charset="utf-8"></script>
<script src="docs/assets/xml.js" type="text/javascript" charset="utf-8"></script>
<script>
hljs.initHighlightingOnLoad();
</script>
</head>
<body>
<div class="container" id="VS">
<h1>VisualSearch.js</h1>
<p class="attribution">
<i>
Created by <a href="http://github.com/samuelclay">Samuel Clay</a>,
<a href="http://twitter.com/samuelclay">@samuelclay</a>.
</i>
</p>
<p>
<a href="http://github.com/documentcloud/visualsearch">VisualSearch.js</a>
enhances ordinary search boxes with the ability to autocomplete
faceted search queries. Specify the facets for completion, along with the
completable values for any facet. You can retrieve the search query as a
structured object, so you don't have to parse the query string yourself.
</p>
<p>
<a href="https://www.documentcloud.org/public/#search/group%3A%20dcloud%20chair%3A%20%22Christopher%20Dodd%22%20TARP">Here's an example of a search on DocumentCloud.org that uses facets.</a>
</p>
<p>
The project is
<a href="http://github.com/documentcloud/visualsearch/">hosted on GitHub</a>.
You can report bugs and discuss features on the
<a href="http://github.com/documentcloud/visualsearch/issues">issues page</a>,
on Freenode in the <tt>#documentcloud</tt> channel,
or send tweets to <a href="http://twitter.com/documentcloud">@documentcloud</a>.
</p>
<p>
<i>VisualSearch.js is an open-source component of <a href="http://documentcloud.org/">DocumentCloud</a>.
<br />
<a href="docs/visualsearch.html">The complete annotated source code</a>
is also available.</i>
</p>
<h2>Table of Contents</h2>
<a href="#demo">Demo</a> | <a href="#downloads">Downloads</a> | <a href="#usage">Usage</a> | <a href="#changelog">Change Log</a>
<h2 id="demo">Demo <span class="demo-hint"><i>Try searching for: <b>account</b>, <b>filter</b>, <b>access</b>, <b>title</b>, <b>city</b>, <b>state</b>, or <b>country</b>.</i></span></h2>
<div id="search_box_container"></div>
<div id="search_query">&nbsp;</div>
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
var visualSearch = VS.init({
container : $('#search_box_container'),
query : 'country: "United States" state: "New York" account: 5-samuel title: "Pentagon Papers"',
unquotable : [
'text',
'account',
'filter',
'access'
],
callbacks : {
search : function(query, searchCollection) {
var $query = $('#search_query');
var count = searchCollection.size();
$query.stop().animate({opacity : 1}, {duration: 300, queue: false});
$query.html('<span class="raquo">&raquo;</span> You searched for: ' +
'<b>' + (query || '<i>nothing</i>') + '</b>. ' +
'(' + count + ' facet' + (count==1 ? '' : 's') + ')');
clearTimeout(window.queryHideDelay);
window.queryHideDelay = setTimeout(function() {
$query.animate({
opacity : 0
}, {
duration: 1000,
queue: false
});
}, 2000);
},
facetMatches : function(callback) {
callback([
'account', 'filter', 'access', 'title',
{ label: 'city', category: 'location' },
{ label: 'country', category: 'location' },
{ label: 'state', category: 'location' },
]);
},
valueMatches : function(facet, searchTerm, callback) {
switch (facet) {
case 'account':
callback([
{ value: '1-amanda', label: 'Amanda' },
{ value: '2-aron', label: 'Aron' },
{ value: '3-eric', label: 'Eric' },
{ value: '4-jeremy', label: 'Jeremy' },
{ value: '5-samuel', label: 'Samuel' },
{ value: '6-scott', label: 'Scott' }
]);
break;
case 'filter':
callback(['published', 'unpublished', 'draft']);
break;
case 'access':
callback(['public', 'private', 'protected']);
break;
case 'title':
callback([
'Pentagon Papers',
'CoffeeScript Manual',
'Laboratory for Object Oriented Thinking',
'A Repository Grows in Brooklyn'
]);
break;
case 'city':
callback([
'Cleveland',
'New York City',
'Brooklyn',
'Manhattan',
'Queens',
'The Bronx',
'Staten Island',
'San Francisco',
'Los Angeles',
'Seattle',
'London',
'Portland',
'Chicago',
'Boston'
]);
break;
case 'state':
callback([
"Alabama", "Alaska", "Arizona", "Arkansas", "California",
"Colorado", "Connecticut", "Delaware", "District of Columbia", "Florida",
"Georgia", "Guam", "Hawaii", "Idaho", "Illinois",
"Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana",
"Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota",
"Mississippi", "Missouri", "Montana", "Nebraska", "Nevada",
"New Hampshire", "New Jersey", "New Mexico", "New York", "North Carolina",
"North Dakota", "Ohio", "Oklahoma", "Oregon", "Pennsylvania",
"Puerto Rico", "Rhode Island", "South Carolina", "South Dakota", "Tennessee",
"Texas", "Utah", "Vermont", "Virginia", "Virgin Islands",
"Washington", "West Virginia", "Wisconsin", "Wyoming"
]);
break;
case 'country':
callback([
"China", "India", "United States", "Indonesia", "Brazil",
"Pakistan", "Bangladesh", "Nigeria", "Russia", "Japan",
"Mexico", "Philippines", "Vietnam", "Ethiopia", "Egypt",
"Germany", "Turkey", "Iran", "Thailand", "D. R. of Congo",
"France", "United Kingdom", "Italy", "Myanmar", "South Africa",
"South Korea", "Colombia", "Ukraine", "Spain", "Tanzania",
"Sudan", "Kenya", "Argentina", "Poland", "Algeria",
"Canada", "Uganda", "Morocco", "Iraq", "Nepal",
"Peru", "Afghanistan", "Venezuela", "Malaysia", "Uzbekistan",
"Saudi Arabia", "Ghana", "Yemen", "North Korea", "Mozambique",
"Taiwan", "Syria", "Ivory Coast", "Australia", "Romania",
"Sri Lanka", "Madagascar", "Cameroon", "Angola", "Chile",
"Netherlands", "Burkina Faso", "Niger", "Kazakhstan", "Malawi",
"Cambodia", "Guatemala", "Ecuador", "Mali", "Zambia",
"Senegal", "Zimbabwe", "Chad", "Cuba", "Greece",
"Portugal", "Belgium", "Czech Republic", "Tunisia", "Guinea",
"Rwanda", "Dominican Republic", "Haiti", "Bolivia", "Hungary",
"Belarus", "Somalia", "Sweden", "Benin", "Azerbaijan",
"Burundi", "Austria", "Honduras", "Switzerland", "Bulgaria",
"Serbia", "Israel", "Tajikistan", "Hong Kong", "Papua New Guinea",
"Togo", "Libya", "Jordan", "Paraguay", "Laos",
"El Salvador", "Sierra Leone", "Nicaragua", "Kyrgyzstan", "Denmark",
"Slovakia", "Finland", "Eritrea", "Turkmenistan"
], {preserveOrder: true});
break;
}
}
}
});
});
</script>
<h2 id="downloads">Downloads <i style="padding-left: 12px; font-size:12px;">(Right-click, and use "Save As")</i></h2>
<table class="downloads">
<tr>
<th colspan="2">0. Everything (<tt>visualsearch.zip</tt>)</th>
</tr>
<tr>
<td><a href="https://github.com/documentcloud/visualsearch/zipball/master">Download everything</a></td>
</tr>
<tr>
<th colspan="2">1. VisualSearch JavaScript (<tt>visualsearch.js</tt>)</th>
</tr>
<tr>
<td><a href="build-min/visualsearch.js">Production Version (0.2.2)</a></td>
<td><i>8kb, Minified and Gzipped</i></td>
</tr>
<tr>
<td><a href="build/visualsearch.js">Development Version (0.2.2)</a></td>
<td><i>45kb, Uncompressed with Comments</i></td>
</tr>
<tr>
<th colspan="2">2. VisualSearch Stylesheets (<tt>visualsearch.css</tt>)</th>
</tr>
<tr>
<td colspan="2"><i>You should include both the datauri and image urls versions. <a href="#css">See how to include both</a></i></td>
</tr>
<tr>
<td><a href="build-min/visualsearch-datauri.css">Production Version - datauri</a></td>
<td><i>4kb, Minified and Gzipped</i></td>
</tr>
<tr>
<td><a href="build-min/visualsearch.css">Production Version - image urls</a></td>
<td><i>4kb, Minified and Gzipped</i></td>
</tr>
<tr>
<td><a href="build/visualsearch.css">Development Version</a></td>
<td><i>8kb, Uncompressed with Comments</i></td>
</tr>
<tr>
<th colspan="2">3. VisualSearch Images</th>
</tr>
<tr>
<td><img src="lib/images/embed/icons/search_glyph.png"> <a href="lib/images/embed/icons/search_glyph.png">Search Glyph</a></td>
<td><i>4kb, embedded in visualsearch-datauri.css</i></td>
</tr>
<tr>
<td><img src="lib/images/embed/icons/cancel_search.png"> <a href="lib/images/embed/icons/cancel_search.png">Cancel Button</a></td>
<td><i>4kb, embedded in visualsearch-datauri.css</i></td>
</tr>
<tr>
<th colspan="2">4. VisualSearch Dependencies (<tt>jQuery 1.4+, jQuery UI, Underscore.js, Backbone.js</tt>)</th>
</tr>
<tr>
<td colspan="2"><i>You should only include the dependencies you don't already have.</i></td>
</tr>
<tr>
<td><a href="build-min/dependencies.js">Production Version - All</a></td>
<td><i>49kb, Minified and Gzipped</i></td>
</tr>
<tr>
<td><a href="build/dependencies.js">Development Version - All</a></td>
<td><i>340kb, Uncompressed with Comments</i></td>
</tr>
<tr>
<td><a href="vendor/jquery-1.6.1.js">jQuery 1.6.1</a></td>
<td><i>238kb, Uncompressed with Comments</i></td>
</tr>
<tr>
<td>jQuery UI 1.8.13: <br /><a href="vendor/jquery.ui.core.js">Core</a> <a href="vendor/jquery.ui.position.js">Position</a> <a href="vendor/jquery.ui.widget.js">Widget</a> <a href="vendor/jquery.ui.autocomplete.js">Autocomplete</a></td>
<td><i>48kb, Uncompressed with Comments</i></td>
</tr>
<tr>
<td><a href="vendor/underscore-1.1.5.js">Underscore 1.1.5</a></td>
<td><i>29kb, Uncompressed with Comments</i></td>
</tr>
<tr>
<td><a href="vendor/backbone-0.5.0.js">Backbone 0.5.0</a></td>
<td><i>41kb, Uncompressed with Comments</i></td>
</tr>
</table>
<h2 id="usage">Usage</h2>
<p>To use VisualSearch.js on your site, follow these instructions on installation, configuration, and customization.</p>
<ol>
<li class="xml" id="css">Insert the JavaScript and CSS into your page:<br />
<pre><code>&lt;script src="visualsearch.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;!--[if (!IE)|(gte IE 8)]&gt;&lt;!--&gt;
&lt;link href="visualsearch-datauri.css" media="screen" rel="stylesheet" type="text/css" /&gt;
&lt;!--&lt;![endif]--&gt;
&lt;!--[if lte IE 7]&gt;&lt;!--&gt;
&lt;link href="visualsearch.css" media="screen" rel="stylesheet" type="text/css" /&gt;
&lt;!--&lt;![endif]--&gt;</code></pre>
</li>
<li>Initialize the Visual Search box:<br />
<pre class="javascript"><code>&lt;div class="visual_search"&gt;&lt;/div&gt;
&lt;script type="text/javascript" charset="utf-8"&gt;
$(document).ready(function() {
var visualSearch = VS.init({
container : $('.visual_search'),
query : '',
callbacks : {
search : function(query, searchCollection) {},
facetMatches : function(callback) {},
valueMatches : function(facet, searchTerm, callback) {}
}
});
});
&lt;/script&gt;</code></pre>
</li>
<li class="javascript">Customize the autocompleted facets and values:
<pre><code>callbacks : {
...
// These are the facets that will be autocompleted in an empty input.
facetMatches : function(callback) {
callback([
'account', 'filter', 'access', 'title',
{ label: 'city', category: 'location' },
{ label: 'address', category: 'location' },
{ label: 'country', category: 'location' },
{ label: 'state', category: 'location' },
]);
}
...
// These are the values that match specific categories, autocompleted
// in a category's input field. searchTerm can be used to filter the
// list on the server-side, prior to providing a list to the widget.
valueMatches : function(facet, searchTerm, callback) {
switch (facet) {
case 'account':
callback([
{ value: '1-amanda', label: 'Amanda' },
{ value: '2-aron', label: 'Aron' },
{ value: '3-eric', label: 'Eric' },
{ value: '4-jeremy', label: 'Jeremy' },
{ value: '5-samuel', label: 'Samuel' },
{ value: '6-scott', label: 'Scott' }
]);
break;
case 'filter':
callback(['published', 'unpublished', 'draft']);
break;
case 'access':
callback(['public', 'private', 'protected']);
break;
case 'title':
callback([
'Pentagon Papers',
'CoffeeScript Manual',
'Laboratory for Object Oriented Thinking',
'A Repository Grows in Brooklyn'
]);
break;
}
}
...
}</code></pre>
</li>
<li class="javascript">Inspect the Visual Search box
<pre><code>// Returns the unstructured search query
visualSearch.searchBox.value()
// "country: "South Africa" account: 5-samuel title: "Pentagon Papers""
// Returns an array of Facet model instances
visualSearch.searchQuery.facets()
// [FacetModel&lt;country:"South Africa">,
// FacetModel&lt;account:5-samuel>,
// FacetModel&lt;title:"Pentagon Papers">]
// Set the search query with raw text
visualSearch.searchBox.value("Country: US State: \"New York\" Key: Value")
</code></pre>
</li>
</ol>
<h2 id="changelog">Change Log</h2>
<p>
<b class="header">0.2.2</b> <i>March 10th, 2012</i><br />
If you do not want to automatically filter the value matches, you can pass an
options hash with <tt>preserveMatches: true</tt> as the second argument to the callback.
<a href="https://github.com/documentcloud/visualsearch/pull/44">See pull request #44</a> for details.
</p>
<p>
<b class="header">0.2.1</b> <i>November 14th, 2011</i><br />
The autocompleted facets and values that are provided by your callbacks <tt>facetMatches</tt>
and <tt>valueMatches</tt> can now preserve the order of items you give them. Simply pass an
options hash with <tt>preserveOrder: true</tt> as the second argument to the callback. See
<a href="demo.html">the demo page</a> for an example.
</p>
<p>
<b class="header">0.2.0</b> <i>August 10th, 2011</i><br />
Multiple instances of VisualSearch on a single page. <tt>VS.init</tt> now returns
a reference to the instance. The <tt>search</tt> callback now contains both the
serialized search query and a reference to the search query collection (as a
<a href="http://documentcloud.github.com/backbone/#Collection">Backbone.Collection</a>),
which can be used to manipulate each facet directly. See
<a href="docs/search_query.html">the source code for search_query.js</a> for available
methods on the collection.
</p>
<p>
<b class="header">0.1.0</b> <i>June 23rd, 2011</i><br />
Initial release of VisualSearch.js.
</p>
<p>
<a href="http://documentcloud.org/" title="A DocumentCloud Project" style="background:none;">
<img src="http://jashkenas.s3.amazonaws.com/images/a_documentcloud_project.png" alt="A DocumentCloud Project" />
</a>
</p>
</div>
</body>
</html>

View File

@ -517,6 +517,7 @@
border-right: 1px solid #afafb6; border-right: 1px solid #afafb6;
text-shadow: 0 1px 1px white; text-shadow: 0 1px 1px white;
padding-bottom: 16px; padding-bottom: 16px;
line-height: 18px;
} }
.openerp a.oe_logo { .openerp a.oe_logo {
width: 220px; width: 220px;
@ -729,10 +730,6 @@
.openerp .oe_menu_more_container .oe_menu_more li a { .openerp .oe_menu_more_container .oe_menu_more li a {
white-space: nowrap; white-space: nowrap;
} }
.oe_leftbar {
line-height: 18px;
}
.openerp .oe_secondary_menu_section { .openerp .oe_secondary_menu_section {
font-weight: bold; font-weight: bold;
margin-left: 8px; margin-left: 8px;
@ -1163,140 +1160,164 @@
white-space: nowrap; white-space: nowrap;
} }
.openerp .oe_searchview { .openerp .oe_searchview {
cursor: text;
position: relative; position: relative;
float: right; float: right;
} padding-right: 20px;
.openerp .oe_searchview .VS-search .VS-search-box { width: 410px;
min-height: 0;
padding: 0;
width: 480px;
border: 1px solid #ababab; border: 1px solid #ababab;
-moz-border-radius: 13px; background: white;
-webkit-border-radius: 13px; -moz-border-radius: 1em;
border-radius: 13px; -webkit-border-radius: 1em;
border-radius: 1em;
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset; -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset; -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset;
-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset; -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2) inset;
} }
.openerp .oe_searchview .VS-search .VS-icon { .openerp .oe_searchview.oe_focused {
top: 6px; border-color: #a6a6fe;
-moz-box-shadow: 0 1px 2px #a6a6fe inset;
-webkit-box-shadow: 0 1px 2px #a6a6fe inset;
-box-shadow: 0 1px 2px #a6a6fe inset;
} }
.openerp .oe_searchview .VS-search .VS-icon-search { .openerp .oe_searchview .oe_searchview_clear {
left: 2px; cursor: pointer;
top: 3px; position: absolute;
height: 18px; top: 0;
width: 18px; right: 22px;
width: 15px;
height: 100%;
background: url(../img/attachments-close.png) center center no-repeat;
} }
.openerp .oe_searchview .VS-search .VS-search-inner { .openerp .oe_searchview .oe_searchview_unfold_drawer {
margin: 0 40px 0 17px; position: absolute;
padding: 1px 0; top: 0;
font-size: 13px; right: 0;
height: 100%;
line-height: 2.5em;
padding: 0 7px 0 4px;
color: #cccccc;
cursor: pointer;
} }
.openerp .oe_searchview .VS-search .VS-search-inner input { .openerp .oe_searchview .oe_searchview_unfold_drawer:hover {
font-size: inherit; color: #999999;
line-height: inherit;
height: auto;
padding: 0;
} }
.openerp .oe_searchview .VS-search .VS-search-inner .VS-input-width-tester { .openerp .oe_searchview .oe_searchview_unfold_drawer:before {
font-size: inherit; content: "◀";
padding: 0;
} }
.openerp .oe_searchview .VS-search .VS-search-inner .search_input { .openerp .oe_searchview .oe_searchview_facets:before {
margin-left: 0; color: #cccccc;
height: 22px; font-family: "mnmliconsRegular";
content: "r";
font-size: 150%;
padding: 0 1px 0 3px;
display: inline;
} }
.openerp .oe_searchview .VS-search .VS-search-inner .search_input input, .openerp .oe_searchview .VS-search .VS-search-inner .search_input .VS-input-width-tester { .openerp .oe_searchview .oe_searchview_facets * {
height: inherit; vertical-align: top;
margin: 0; display: inline-block;
line-height: 26px;
} }
.openerp .oe_searchview .VS-search .VS-search-inner .search_facet { .openerp .oe_searchview .oe_searchview_facets .oe_searchview_input, .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet {
padding: 0; height: 26px;
margin: 1px 0; }
.openerp .oe_searchview .oe_searchview_facets .oe_searchview_input:focus, .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet:focus {
outline: none;
}
.openerp .oe_searchview .oe_searchview_facets .oe_searchview_input {
padding: 0 3px;
}
.openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet {
position: relative;
cursor: pointer;
border: 1px solid #afafb6; border: 1px solid #afafb6;
-moz-border-radius: 3px; -moz-border-radius: 3px;
-webkit-border-radius: 3px; -webkit-border-radius: 3px;
border-radius: 3px; border-radius: 3px;
background: #f0f0fa; background: #8786b7;
height: 18px; -webkit-font-smoothing: auto;
padding-left: 1.1em;
margin: 1px 0;
} }
.openerp .oe_searchview .VS-search .VS-search-inner .search_facet.is_selected { .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet:focus {
border-color: #a6a6fe; border-color: #a6a6fe;
-moz-box-shadow: 0 0 3px 1px #a6a6fe; -moz-box-shadow: 0 0 3px 1px #a6a6fe;
-webkit-box-shadow: 0 0 3px 1px #a6a6fe; -webkit-box-shadow: 0 0 3px 1px #a6a6fe;
-box-shadow: 0 0 3px 1px #a6a6fe; -box-shadow: 0 0 3px 1px #a6a6fe;
} }
.openerp .oe_searchview .VS-search .VS-search-inner .search_facet.is_selected .category { .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_values {
margin-left: 0; background: #f0f0fa;
-moz-border-radius: 0 3px 3px 0;
-webkit-border-radius: 0 3px 3px 0;
border-radius: 0 3px 3px 0;
} }
.openerp .oe_searchview .VS-search .VS-search-inner .search_facet.is_selected .VS-icon-cancel { .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_category, .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_value {
filter: alpha(opacity=100); height: 24px;
opacity: 1; padding: 1px 0.1em;
background-position: center 0;
} }
.openerp .oe_searchview .VS-search .VS-search-inner .search_facet .category { .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_category {
padding: 0 4px 0 14px;
color: white; color: white;
background: #8786b7;
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.4); text-shadow: 0 1px 1px rgba(0, 0, 0, 0.4);
font-weight: normal;
text-transform: none;
height: 18px;
line-height: 18px;
font-size: inherit;
} }
.openerp .oe_searchview .VS-search .VS-search-inner .search_facet .search_facet_input_container { .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_value {
border-left: 1px solid #afafb6; border-left: 1px solid #afafb6;
height: 18px;
line-height: 18px;
padding: 0 4px;
cursor: pointer;
} }
.openerp .oe_searchview .VS-search .VS-search-inner .search_facet .search_facet_remove { .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_remove {
left: 1px;
top: 3px;
}
.openerp .oe_searchview .VS-search .VS-icon-cancel {
right: 24px;
}
.openerp .oe_searchview .VS-search .oe_vs_unfold_drawer {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; left: 2px;
height: 100%; color: white;
line-height: 23px;
padding: 0 7px 0 4px;
color: #4c4c4c;
cursor: pointer;
} }
.openerp .oe_searchview .VS-search .oe_vs_unfold_drawer:before { .openerp .oe_searchview .oe_searchview_facets .oe_searchview_facet .oe_facet_remove:hover {
position: absolute; color: #cccccc;
top: 9px;
right: 8px;
width: 0;
height: 0;
display: inline-block;
content: "";
vertical-align: top;
border-top: 5px solid #4c4c4c;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
filter: alpha(opacity=50);
opacity: 0.5;
} }
.openerp .oe_searchview.oe_searchview_open_drawer .oe_searchview_drawer { .openerp .oe_searchview.oe_searchview_open_drawer .oe_searchview_drawer {
display: block; display: block;
} }
.openerp .oe_searchview.oe_searchview_open_drawer .oe_searchview_unfold_drawer:before {
content: "▼";
}
.openerp .oe_searchview .oe_searchview_drawer { .openerp .oe_searchview .oe_searchview_drawer {
position: absolute; position: absolute;
z-index: 1; z-index: 1;
margin-top: 3px;
top: 100%; top: 100%;
right: 0; right: 0;
background-color: white; background-color: white;
width: 480px; min-width: 100%;
display: none; display: none;
border: 1px solid #cccccc; border: 1px solid #cccccc;
text-align: left; text-align: left;
padding-bottom: 0.5em;
-moz-border-radius: 1em;
-webkit-border-radius: 1em;
border-radius: 1em;
}
.openerp .oe_searchview .oe_searchview_drawer > div {
border-top: 1px solid #cccccc;
margin: 3px 0;
}
.openerp .oe_searchview .oe_searchview_drawer > div:first-child {
border-top: none;
margin: 0;
}
.openerp .oe_searchview .oe_searchview_drawer h4, .openerp .oe_searchview .oe_searchview_drawer h4 * {
margin: 0;
cursor: pointer;
}
.openerp .oe_searchview .oe_searchview_drawer h4:before {
content: "▸ ";
}
.openerp .oe_searchview .oe_searchview_drawer button, .openerp .oe_searchview .oe_searchview_drawer .button {
border: none;
background: transparent;
padding: 0 2px;
-moz-box-shadow: none;
-webkit-box-shadow: none;
-box-shadow: none;
-moz-border-radius: 0;
-webkit-border-radius: 0;
border-radius: 0;
} }
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_filters { .openerp .oe_searchview .oe_searchview_drawer .oe_searchview_filters {
display: table; display: table;
@ -1320,23 +1341,49 @@
} }
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_filters li { .openerp .oe_searchview .oe_searchview_drawer .oe_searchview_filters li {
list-style: none; list-style: none;
padding: 3px 6px; padding: 3px 6px 3px 18px;
height: 14px; line-height: 14px;
color: inherit; color: inherit;
cursor: pointer; cursor: pointer;
} }
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_filters li.oe_selected {
background: url(/web/static/src/img/icons/gtk-apply.png) left 2px no-repeat;
}
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_filters li:hover { .openerp .oe_searchview .oe_searchview_drawer .oe_searchview_filters li:hover {
background-color: #f0f0fa; background-color: #f0f0fa;
} }
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced h4 { .openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom form {
border-top: 1px solid #cccccc; display: none;
margin: 5px 0 3px; }
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom form button {
font-size: 1px;
letter-spacing: -1px;
color: transparent;
}
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom form button:before {
font-family: "mnmliconsRegular";
content: "S";
font-size: 20px;
color: #404040;
}
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom li {
cursor: pointer; cursor: pointer;
position: relative;
line-height: 1.2em;
padding: 2px 20px 2px 25px;
} }
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced h4:before { .openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom li.oe_searchview_custom_private {
content: "▸ "; background: url(/web/static/src/img/icons/terp-locked.png) 5px center no-repeat;
} }
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced div { .openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom li:hover {
background-color: #f0f0fa;
}
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom li button {
position: absolute;
top: 0;
right: 5px;
}
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced form {
display: none; display: none;
} }
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced button.oe_add_condition:before { .openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced button.oe_add_condition:before {
@ -1352,13 +1399,25 @@
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced li { .openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced li {
list-style: none; list-style: none;
margin: 0; margin: 0;
white-space: nowrap;
} }
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced.oe_opened h4:before { .openerp .oe_searchview .oe_searchview_drawer .oe_opened h4:before {
content: "▾ "; content: "▾ ";
} }
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_advanced.oe_opened div { .openerp .oe_searchview .oe_searchview_drawer .oe_opened form {
display: block; display: block;
} }
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom_delete, .openerp .oe_searchview .oe_searchview_drawer .searchview_extended_delete_prop {
font-size: 1px;
letter-spacing: -1px;
color: transparent;
}
.openerp .oe_searchview .oe_searchview_drawer .oe_searchview_custom_delete:before, .openerp .oe_searchview .oe_searchview_drawer .searchview_extended_delete_prop:before {
font-family: "mnmliconsRegular";
content: "d";
font-size: 20px;
color: #404040;
}
.openerp .oe_view_nocontent > img { .openerp .oe_view_nocontent > img {
float: left; float: left;
margin: 1.5em; margin: 1.5em;
@ -1498,7 +1557,7 @@
padding: 8px 0; padding: 8px 0;
border-bottom: 1px solid #dddddd; border-bottom: 1px solid #dddddd;
} }
.openerp .oe_application .oe_form_sheet_width { .openerp .oe_application .oe_form_sheet_width, .openerp .oe_application .oe_form_bottom {
min-width: 650px; min-width: 650px;
max-width: 980px; max-width: 980px;
margin: 0 auto; margin: 0 auto;
@ -1972,59 +2031,6 @@
.openerp .oe-listview-content .numeric input { .openerp .oe-listview-content .numeric input {
text-align: right; text-align: right;
} }
.openerp .oe_kanban_group_title {
margin: 1px 1px 4px;
font-size: 15px;
font-weight: bold;
text-shadow: 0 1px 0 white;
}
.openerp .oe_kanban_column, .openerp .oe_kanban_group_header {
width: 240px;
vertical-align: top;
padding: 6px 7px 6px 6px;
background: #f0eeee;
border-left: 1px solid #f0f8f8;
border-right: 1px solid #b9b9b9;
}
.openerp .oe_kanban_record {
position: relative;
display: block;
min-height: 50px;
margin: 6px 0;
display: block;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
}
.openerp .oe_kanban_record:last-child {
margin-bottom: 0;
}
.openerp .oe_kanban_record .oe_kanban_title {
font-weight: bold;
margin: 2px 4px;
}
.openerp .oe_kanban_gravatar {
width: 20px;
height: 20px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.openerp .oe_kanban_avatar_toto {
height: 40px;
width: 40px;
border: 1px solid;
border-color: #e5e5e5 #dbdbdb #d2d2d2;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.openerp .oe_trad_field.touched { .openerp .oe_trad_field.touched {
border: 1px solid green !important; border: 1px solid green !important;
} }
@ -2090,6 +2096,15 @@
color: #333333; color: #333333;
} }
.kitten-mode-activated {
background-image: url(http://placekitten.com/g/1365/769);
background-size: cover;
background-attachment: fixed;
}
.kitten-mode-activated > * {
opacity: 0.7;
}
.openerp .oe_form_field_many2one td:first-child { .openerp .oe_form_field_many2one td:first-child {
position: relative; position: relative;
} }

View File

@ -4,6 +4,7 @@
$section-title-color: #8786b7 $section-title-color: #8786b7
$facets-border: #afafb6 $facets-border: #afafb6
$facets-border-selected: #a6a6fe $facets-border-selected: #a6a6fe
$hover-background: #f0f0fa
$colour4: #8a89ba $colour4: #8a89ba
// }}} // }}}
// Mixins {{{ // Mixins {{{
@ -74,6 +75,18 @@ $colour4: #8a89ba
-webkit-box-sizing: border-box -webkit-box-sizing: border-box
box-sizing: border-box box-sizing: border-box
// Transforms the (readable) text of an inline element into an mmlicons icon,
// allows for actual readable text in-code (and in readers?) with iconic looks
@mixin text-to-icon($icon-name, $color: #404040)
font-size: 1px
letter-spacing: -1px
color: transparent
&:before
font-family: "mnmliconsRegular"
content: $icon-name
font-size: 20px
color: $color
// }}} // }}}
.openerp.openerp-web-client-container .openerp.openerp-web-client-container
@ -105,7 +118,6 @@ $colour4: #8a89ba
border-right: none border-right: none
th, td th, td
padding: 0 padding: 0
line-height: 18px
text-align: left text-align: left
th th
font-weight: bold font-weight: bold
@ -423,6 +435,7 @@ $colour4: #8a89ba
border-right: 1px solid #afafb6 border-right: 1px solid #afafb6
text-shadow: 0 1px 1px white text-shadow: 0 1px 1px white
padding-bottom: 16px padding-bottom: 16px
line-height: 18px
a.oe_logo a.oe_logo
width: 220px width: 220px
display: block display: block
@ -784,11 +797,6 @@ $colour4: #8a89ba
.oe_view_manager_buttons .oe_view_manager_buttons
white-space: nowrap white-space: nowrap
// }}} // }}}
// ViewManager.body {{{
.oe_view_manager_body
h4
margin: 8px 0
// }}}
// ViewManager.pager {{{ // ViewManager.pager {{{
.oe_view_manager_pager .oe_view_manager_pager
line-height: 26px line-height: 26px
@ -855,18 +863,6 @@ $colour4: #8a89ba
content: "k" content: "k"
.oe_vm_switch_diagram:after .oe_vm_switch_diagram:after
content: "f" content: "f"
//.oe_vm_switch_list:after, .oe_vm_switch_tree:after
//content: "ö"
//.oe_vm_switch_graph:after
//content: "ó"
//.oe_vm_switch_gantt:after
//content: "y"
//.oe_vm_switch_calendar:after
//content: "b"
//.oe_vm_switch_kanban:after
//content: "ó"
//.oe_vm_switch_diagram:after
//content: "}"
// }}} // }}}
// ViewManager.sidebar {{{ // ViewManager.sidebar {{{
.oe_form_dropdown_section .oe_form_dropdown_section
@ -923,132 +919,145 @@ $colour4: #8a89ba
// }}} // }}}
// SearchView xmo {{{ // SearchView xmo {{{
.oe_searchview .oe_searchview
cursor: text
position: relative position: relative
float: right float: right
.VS-search padding-right: 20px
.VS-search-box width: 410px
min-height: 0 border: 1px solid #ababab
padding: 0 background: white
width: 480px @include radius(1em)
border: 1px solid #ababab @include box-shadow(0 1px 2px rgba(0,0,0,0.2) inset)
@include radius(13px)
@include box-shadow(0 1px 2px rgba(0,0,0,0.2) inset)
//padding: 4px 19px
//font-size: 13px
//background: url('../img/search.png') no-repeat 5px
//background-color: white
.VS-icon
top: 6px
.VS-icon-search &.oe_focused
left: 2px border-color: $facets-border-selected
top: 3px @include box-shadow(0 1px 2px $facets-border-selected inset)
height: 18px
width: 18px
.VS-search-inner .oe_searchview_clear
margin: 0 40px 0 17px cursor: pointer
padding: 1px 0 position: absolute
font-size: 13px top: 0
right: 22px
width: 15px
height: 100%
background: url(../img/attachments-close.png) center center no-repeat
input .oe_searchview_unfold_drawer
font-size: inherit position: absolute
line-height: inherit top: 0
height: auto right: 0
padding: 0 height: 100%
line-height: 2.5em
padding: 0 7px 0 4px
color: #ccc
cursor: pointer
&:hover
color: #999
&:before
content: ""
.VS-input-width-tester .oe_searchview_facets
font-size: inherit &:before
padding: 0 color: #ccc
font-family: "mnmliconsRegular"
content: "r"
font-size: 150%
padding: 0 1px 0 3px
display: inline
.search_input *
margin-left: 0 vertical-align: top
height: 22px display: inline-block
input, .VS-input-width-tester line-height: 26px
height: inherit
margin: 0
.search_facet .oe_searchview_input, .oe_searchview_facet
padding: 0 height: 26px
margin: 1px 0 &:focus
border: 1px solid $facets-border outline: none
@include radius(3px)
background: #f0f0fa
height: 18px
&.is_selected .oe_searchview_input
border-color: $facets-border-selected padding: 0 3px
@include box-shadow(0 0 3px 1px $facets-border-selected)
.category .oe_searchview_facet
margin-left: 0 position: relative
.VS-icon-cancel
// don't change the icon on selection
@include opacity(1.0)
background-position: center 0
.category
padding: 0 4px 0 14px
color: white
background: #8786b7
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.4)
font-weight: normal
text-transform: none
height: 18px
line-height: 18px
font-size: inherit
.search_facet_input_container
border-left: 1px solid $facets-border
height: 18px
line-height: 18px
padding: 0 4px
cursor: pointer
.search_facet_remove
left: 1px
top: 3px
.VS-icon-cancel
right: 24px
.oe_vs_unfold_drawer
position: absolute
top: 0
right: 0
height: 100%
line-height: 23px
padding: 0 7px 0 4px
color: #4c4c4c
cursor: pointer cursor: pointer
&:before border: 1px solid $facets-border
@include radius(3px)
background: #8786b7
-webkit-font-smoothing: auto
padding-left: 1.1em
// spacing for opera, FF
margin: 1px 0
&:focus
border-color: $facets-border-selected
@include box-shadow(0 0 3px 1px $facets-border-selected)
.oe_facet_values
background: #f0f0fa
@include radius(0 3px 3px 0)
.oe_facet_category, .oe_facet_value
height: 24px
padding: 1px 0.1em
.oe_facet_category
color: white
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.4)
.oe_facet_value
border-left: 1px solid $facets-border
.oe_facet_remove
position: absolute position: absolute
top: 9px top: 0
right: 8px left: 2px
width: 0 color: white
height: 0
display: inline-block &:hover
content: "" color: #ccc
vertical-align: top
border-top: 5px solid #4c4c4c
border-left: 5px solid transparent
border-right: 5px solid transparent
@include opacity(0.5)
&.oe_searchview_open_drawer &.oe_searchview_open_drawer
.oe_searchview_drawer .oe_searchview_drawer
display: block display: block
.oe_searchview_unfold_drawer:before
content: ""
.oe_searchview_drawer .oe_searchview_drawer
position: absolute position: absolute
z-index: 1 z-index: 1
// detach drawer from field slightly
margin-top: 3px
top: 100% top: 100%
right: 0 right: 0
background-color: white background-color: white
width: 480px min-width: 100%
display: none display: none
border: 1px solid #ccc border: 1px solid #ccc
text-align: left text-align: left
padding-bottom: 0.5em
@include radius(1em)
> div
border-top: 1px solid #ccc
margin: 3px 0
> div:first-child
border-top: none
margin: 0
h4, h4 *
margin: 0
cursor: pointer
h4:before
content: ""
button, .button
border: none
background: transparent
padding: 0 2px
@include box-shadow(none)
@include radius(0)
.oe_searchview_filters .oe_searchview_filters
display: table display: table
@ -1070,24 +1079,44 @@ $colour4: #8a89ba
li li
list-style: none list-style: none
padding: 3px 6px padding: 3px 6px 3px 18px
height: 14px line-height: 14px
color: inherit color: inherit
cursor: pointer cursor: pointer
&.oe_selected
background: url(/web/static/src/img/icons/gtk-apply.png) left 2px no-repeat
// after oe_selected so background color is not overridden
&:hover &:hover
background-color: #f0f0fa background-color: $hover-background
.oe_searchview_custom
form
display: none
button
@include text-to-icon("S")
li
cursor: pointer
position: relative
line-height: 1.2em
padding: 2px 20px 2px 25px
&.oe_searchview_custom_private
background: url(/web/static/src/img/icons/terp-locked.png) 5px center no-repeat
&:hover
background-color: $hover-background
button
position: absolute
top: 0
right: 5px
.oe_searchview_advanced .oe_searchview_advanced
h4 form
border-top: 1px solid #ccc
margin: 5px 0 3px
cursor: pointer
h4:before
content: ""
div
display: none display: none
button.oe_add_condition:before button.oe_add_condition:before
@ -1101,22 +1130,28 @@ $colour4: #8a89ba
li li
list-style: none list-style: none
margin: 0 margin: 0
white-space: nowrap
&.oe_opened .oe_opened
h4:before h4:before
content: "" content: ""
div form
display: block display: block
// delete buttons
.oe_searchview_custom_delete, .searchview_extended_delete_prop
@include text-to-icon("d")
// }}} // }}}
// Views Common {{{ // Views Common {{{
.oe_view_nocontent .oe_view_nocontent
> img > img
float: left float: left
margin-right: 1.5em margin: 1.5em
> div > div
// don't encroach on my arrow // don't encroach on my arrow
overflow: hidden overflow: hidden
padding: 6px padding: 35px 0px 0px 0px
max-width: 700px
font-size: 125% font-size: 125%
.oe_view_topbar .oe_view_topbar
border-bottom: 1px solid #cacaca border-bottom: 1px solid #cacaca
@ -1220,7 +1255,7 @@ $colour4: #8a89ba
background: url(/web/static/src/img/form_sheetbg.png) background: url(/web/static/src/img/form_sheetbg.png)
padding: 8px 0 padding: 8px 0
border-bottom: 1px solid #ddd border-bottom: 1px solid #ddd
.oe_form_sheet_width .oe_form_sheet_width, .oe_form_bottom
min-width: 650px min-width: 650px
max-width: 980px max-width: 980px
margin: 0 auto margin: 0 auto
@ -1308,7 +1343,6 @@ $colour4: #8a89ba
padding-left: 8px padding-left: 8px
@include box-shadow(none) @include box-shadow(none)
@include radius(0px) @include radius(0px)
color: #666
.oe_form_field_many2one input, .oe_form_field_many2one input,
.oe_form_field_binary input, .oe_form_field_binary input,
.oe_form_field_binary input, .oe_form_field_binary input,
@ -1636,44 +1670,6 @@ $colour4: #8a89ba
input input
text-align: right text-align: right
// }}} // }}}
// KanbanView {{{
.oe_kanban_group_title
margin: 1px 1px 4px
font-size: 15px
font-weight: bold
text-shadow: 0 1px 0 white
.oe_kanban_column, .oe_kanban_group_header
width: 240px
vertical-align: top
padding: 6px 7px 6px 6px
background: #f0eeee
border-left: 1px solid #f0f8f8
border-right: 1px solid #b9b9b9
.oe_kanban_record
position: relative
display: block
min-height: 50px
margin: 6px 0
display: block
@include radius(4px)
&:last-child
margin-bottom: 0
.oe_kanban_title
font-weight: bold
margin: 2px 4px
.oe_kanban_gravatar
width: 20px
height: 20px
@include radius(3px)
@include box-shadow(0 1px 2px rgba(0,0,0,0.2))
.oe_kanban_avatar_toto
height: 40px
width: 40px
border: 1px solid
border-color: #e5e5e5 #dbdbdb #d2d2d2
@include radius(3px)
@include box-shadow(0 1px 2px rgba(0,0,0,0.2))
// }}}
// Translation {{{ // Translation {{{
.oe_trad_field.touched .oe_trad_field.touched
border: 1px solid green !important border: 1px solid green !important
@ -1731,6 +1727,13 @@ $colour4: #8a89ba
color: #333 color: #333
// }}} // }}}
.kitten-mode-activated
background-image: url(http://placekitten.com/g/1365/769)
background-size: cover
background-attachment: fixed
>*
opacity: 0.70
// Transitional overrides for old styles {{{ // Transitional overrides for old styles {{{
.openerp .openerp
.oe_form_field_many2one .oe_form_field_many2one

View File

@ -450,6 +450,8 @@ instance.web.DatabaseManager = instance.web.Widget.extend({
instance.web.Login = instance.web.Widget.extend({ instance.web.Login = instance.web.Widget.extend({
template: "Login", template: "Login",
remember_credentials: true, remember_credentials: true,
_db_list: null,
init: function(parent) { init: function(parent) {
this._super(parent); this._super(parent);
this.has_local_storage = typeof(localStorage) != 'undefined'; this.has_local_storage = typeof(localStorage) != 'undefined';
@ -478,23 +480,33 @@ instance.web.Login = instance.web.Widget.extend({
self.databasemanager.destroy(); self.databasemanager.destroy();
self.$element.find('.oe_login_bottom').show(); self.$element.find('.oe_login_bottom').show();
self.$element.find('.oe_login_pane').show(); self.$element.find('.oe_login_pane').show();
self.load_db_list(); self.load_db_list(true).then(self.proxy('_db_list_loaded'));
}); });
}); });
self.load_db_list(); return self.load_db_list().then(self.proxy('_db_list_loaded'));
}, },
load_db_list: function () { load_db_list: function (force) {
var self = this; var d = $.when(), self = this;
self.rpc("/web/database/get_list", {}, function(result) { if (_.isNull(this._db_list) || force) {
self.set_db_list(result.db_list); d = self.rpc("/web/database/get_list", {}, function(result) {
}, function(error, event) { self._db_list = _.clone(result.db_list);
if (error.data.fault_code === 'AccessDenied') { }, function(error, event) {
event.preventDefault(); if (error.data.fault_code === 'AccessDenied') {
} event.preventDefault();
}); }
});
}
return d;
}, },
set_db_list: function (list) { _db_list_loaded: function () {
var list = this._db_list,
dbdiv = this.$element.find('div.oe_login_dbpane');
this.$element.find("[name=db]").replaceWith(instance.web.qweb.render('Login.dblist', { db_list: list, selected_db: this.selected_db})); this.$element.find("[name=db]").replaceWith(instance.web.qweb.render('Login.dblist', { db_list: list, selected_db: this.selected_db}));
if(list && list.length === 1) {
dbdiv.hide();
} else {
dbdiv.show();
}
}, },
on_submit: function(ev) { on_submit: function(ev) {
if(ev) { if(ev) {
@ -521,14 +533,7 @@ instance.web.Login = instance.web.Widget.extend({
do_login: function (db, login, password) { do_login: function (db, login, password) {
var self = this; var self = this;
this.$element.removeClass('oe_login_invalid'); this.$element.removeClass('oe_login_invalid');
this.session.on_session_invalid.add({ return this.session.session_authenticate(db, login, password).pipe(function() {
callback: function () {
self.$element.addClass("oe_login_invalid");
},
unique: true
});
this.session.session_authenticate(db, login, password).then(function() {
self.$element.removeClass("oe_login_invalid");
if (self.has_local_storage) { if (self.has_local_storage) {
if(self.remember_credentials) { if(self.remember_credentials) {
localStorage.setItem('last_db_login_success', db); localStorage.setItem('last_db_login_success', db);
@ -542,6 +547,10 @@ instance.web.Login = instance.web.Widget.extend({
localStorage.setItem('last_password_login_success', ''); localStorage.setItem('last_password_login_success', '');
} }
} }
self.$(".oe_login_pane").fadeOut("slow");
self.trigger("login");
},function () {
self.$element.addClass("oe_login_invalid");
}); });
} }
}); });
@ -849,47 +858,53 @@ instance.web.WebClient = instance.web.Widget.extend({
var self = this; var self = this;
this.$element.addClass("openerp openerp-web-client-container"); this.$element.addClass("openerp openerp-web-client-container");
if (jQuery.param !== undefined && jQuery.deparam(jQuery.param.querystring()).kitten !== undefined) { if (jQuery.param !== undefined && jQuery.deparam(jQuery.param.querystring()).kitten !== undefined) {
this.$element.addClass("kitten-mode-activated"); $("body").addClass("kitten-mode-activated");
this.$element.delegate('img.oe-record-edit-link-img', 'hover', function(e) { self.$element.delegate('img.oe-record-edit-link-img', 'hover', function(e) {
self.$element.toggleClass('clark-gable'); self.$element.toggleClass('clark-gable');
}); });
} }
this.session.session_bind().then(function() { this.session.session_bind().then(function() {
self.destroy_content();
self.show_common();
if (!self.session.session_is_valid()) { if (!self.session.session_is_valid()) {
self.show_login(); self.show_login();
} } else {
}); self.show_application();
this.session.on_session_valid.add(function() {
self.show_application();
if(self.action_manager)
self.action_manager.destroy();
self.action_manager = new instance.web.ActionManager(self);
self.action_manager.appendTo(self.$element.find('.oe_application'));
self.bind_hashchange();
var version_label = _t("OpenERP - Unsupported/Community Version");
if (!self.session.openerp_entreprise) {
self.$element.find('.oe_footer_powered').append(_.str.sprintf('<span> - <a href="http://www.openerp.com/support-or-publisher-warranty-contract" target="_blank">%s</a></span>', version_label));
document.title = version_label;
} }
}); });
this.$element.on('mouseenter', '.oe_systray > div:not([data-tipsy=true])', function() { this.$element.on('mouseenter', '.oe_systray > div:not([data-tipsy=true])', function() {
$(this).attr('data-tipsy', 'true').tipsy().trigger('mouseenter'); $(this).attr('data-tipsy', 'true').tipsy().trigger('mouseenter');
}); });
}, },
show_common: function() {
var self = this;
this.crashmanager = new instance.web.CrashManager();
instance.connection.on_rpc_error.add(this.crashmanager.on_rpc_error);
window.onerror = function (message, file, line) {
self.crashmanager.on_traceback({
type: _t("Client Error"),
message: message,
data: {debug: file + ':' + line}
});
};
self.notification = new instance.web.Notification(this);
self.notification.appendTo(self.$element);
self.loading = new instance.web.Loading(self);
self.loading.appendTo(self.$element);
self.login = new instance.web.Login(self);
self.login.on("login",self,self.show_application);
self.$table = $(QWeb.render("WebClient", {}));
self.action_manager = new instance.web.ActionManager(self);
self.action_manager.appendTo(self.$table.find('.oe_application'));
},
show_login: function() { show_login: function() {
var self = this; var self = this;
this.destroy_content();
this.show_common();
self.login = new instance.web.Login(self);
self.login.appendTo(self.$element); self.login.appendTo(self.$element);
}, },
show_application: function() { show_application: function() {
var self = this; var self = this;
this.destroy_content();
this.show_common();
self.$table = $(QWeb.render("WebClient", {}));
self.$element.append(self.$table); self.$element.append(self.$table);
self.login.$element.hide();
self.menu = new instance.web.Menu(self); self.menu = new instance.web.Menu(self);
self.menu.replace(this.$element.find('.oe_menu_placeholder')); self.menu.replace(this.$element.find('.oe_menu_placeholder'));
self.menu.on('menu_click', this, this.on_menu_action); self.menu.on('menu_click', this, this.on_menu_action);
@ -898,24 +913,12 @@ instance.web.WebClient = instance.web.Widget.extend({
self.user_menu.on_menu_logout.add(this.proxy('on_logout')); self.user_menu.on_menu_logout.add(this.proxy('on_logout'));
self.user_menu.on_action.add(this.proxy('on_menu_action')); self.user_menu.on_action.add(this.proxy('on_menu_action'));
self.user_menu.do_update(); self.user_menu.do_update();
}, self.bind_hashchange();
show_common: function() { var version_label = _t("OpenERP - Unsupported/Community Version");
var self = this; if (!self.session.openerp_entreprise) {
if (!this.crashmanager) { self.$element.find('.oe_footer_powered').append(_.str.sprintf('<span> - <a href="http://www.openerp.com/support-or-publisher-warranty-contract" target="_blank">%s</a></span>', version_label));
this.crashmanager = new instance.web.CrashManager(); document.title = version_label;
instance.connection.on_rpc_error.add(this.crashmanager.on_rpc_error);
window.onerror = function (message, file, line) {
self.crashmanager.on_traceback({
type: _t("Client Error"),
message: message,
data: {debug: file + ':' + line}
});
};
} }
this.notification = new instance.web.Notification(this);
this.notification.appendTo(this.$element);
this.loading = new instance.web.Loading(this);
this.loading.appendTo(this.$element);
}, },
destroy_content: function() { destroy_content: function() {
_.each(_.clone(this.getChildren()), function(el) { _.each(_.clone(this.getChildren()), function(el) {

View File

@ -709,6 +709,12 @@ instance.web.Widget = instance.web.Class.extend(instance.web.WidgetMixin, {
this.$element = elem; this.$element = elem;
} }
}, },
/**
* Shortcut for $element.find() like backbone
*/
"$": function() {
return this.$element.find.apply(this.$element,arguments);
},
/** /**
* Informs the action manager to do an action. This supposes that * Informs the action manager to do an action. This supposes that
* the action manager can be found amongst the ancestors of the current widget. * the action manager can be found amongst the ancestors of the current widget.
@ -1341,6 +1347,9 @@ instance.web.JsonRPC = instance.web.CallbackEnabled.extend({
}, },
on_rpc_error: function(error) { on_rpc_error: function(error) {
}, },
get_url: function (file) {
return this.prefix + file;
},
}); });
} }

View File

@ -121,6 +121,10 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess
var base_location = document.location.protocol + '//' + document.location.host; var base_location = document.location.protocol + '//' + document.location.host;
var params = { db: db, login: login, password: password, base_location: base_location }; var params = { db: db, login: login, password: password, base_location: base_location };
return this.rpc("/web/session/authenticate", params).pipe(function(result) { return this.rpc("/web/session/authenticate", params).pipe(function(result) {
if (!result.uid) {
return $.Deferred().reject();
}
_.extend(self, { _.extend(self, {
session_id: result.session_id, session_id: result.session_id,
db: result.db, db: result.db,
@ -284,9 +288,6 @@ instance.web.Session = instance.web.JsonRPC.extend( /** @lends instance.web.Sess
} }
} }
}, },
get_url: function (file) {
return this.prefix + file;
},
/** /**
* Cooperative file download implementation, for ajaxy APIs. * Cooperative file download implementation, for ajaxy APIs.
* *

View File

@ -111,7 +111,7 @@ instance.web.format_value = function (value, descriptor, value_if_empty) {
return value_if_empty === undefined ? '' : value_if_empty; return value_if_empty === undefined ? '' : value_if_empty;
} }
var l10n = _t.database.parameters; var l10n = _t.database.parameters;
switch (descriptor.type || (descriptor.field && descriptor.field.type)) { switch (descriptor.widget || descriptor.type || (descriptor.field && descriptor.field.type)) {
case 'id': case 'id':
return value.toString(); return value.toString();
case 'integer': case 'integer':
@ -171,7 +171,7 @@ instance.web.parse_value = function (value, descriptor, value_if_empty) {
case "": case "":
return value_if_empty === undefined ? false : value_if_empty; return value_if_empty === undefined ? false : value_if_empty;
} }
switch (descriptor.type || (descriptor.field && descriptor.field.type)) { switch (descriptor.widget || descriptor.type || (descriptor.field && descriptor.field.type)) {
case 'integer': case 'integer':
var tmp; var tmp;
do { do {

File diff suppressed because it is too large Load Diff

View File

@ -794,41 +794,36 @@ instance.web.FormView = instance.web.View.extend(_.extend({}, instance.web.form.
var self = this; var self = this;
var fields = _.chain(this.fields) var fields = _.chain(this.fields)
.map(function (field, name) { .map(function (field, name) {
var value_ = field.get_value(); var value = field.get_value();
// ignore fields which are empty, invisible, readonly, o2m // ignore fields which are empty, invisible, readonly, o2m
// or m2m // or m2m
if (!value_ if (!value
|| field.get('invisible') || field.get('invisible')
|| field.get("readonly") || field.get("readonly")
|| field.field.type === 'one2many' || field.field.type === 'one2many'
|| field.field.type === 'many2many') { || field.field.type === 'many2many') {
return false; return false;
} }
var displayed; var displayed = value;
switch(field.field.type) { switch (field.field.type) {
case 'selection': case 'selection':
displayed = _(field.values).find(function (option) { displayed = _(field.values).find(function (option) {
return option[0] === value_; return option[0] === value;
})[1]; })[1];
break; break;
case 'many2one':
displayed = value_;
break;
default:
displayed = value_;
} }
return { return {
name: name, name: name,
string: field.node_atts.string, string: field.node.attrs.string || field.field.string,
value: value_, value: value,
displayed: displayed, displayed: displayed,
// convert undefined to false // convert undefined to false
change_default: !!field.field.change_default change_default: !!field.field.change_default
} }
}) })
.compact() .compact()
.sortBy(function (field) { return field.node_atts.string; }) .sortBy(function (field) { return field.string; })
.value(); .value();
var conditions = _.chain(fields) var conditions = _.chain(fields)
.filter(function (field) { return field.change_default; }) .filter(function (field) { return field.change_default; })

View File

@ -69,8 +69,7 @@ instance.web.ListView = instance.web.View.extend( /** @lends instance.web.ListVi
this.groups.datagroup = new instance.web.DataGroup( this.groups.datagroup = new instance.web.DataGroup(
this, this.model, this, this.model,
dataset.get_domain(), dataset.get_domain(),
dataset.get_context(), dataset.get_context());
{});
this.groups.datagroup.sort = this.dataset._sort; this.groups.datagroup.sort = this.dataset._sort;
} }

View File

@ -615,6 +615,17 @@ instance.web.ViewManagerAction = instance.web.ViewManager.extend({
case 'edit': case 'edit':
this.do_edit_resource($option.data('model'), $option.data('id'), { name : $option.text() }); this.do_edit_resource($option.data('model'), $option.data('id'), { name : $option.text() });
break; break;
case 'manage_filters':
this.do_action({
res_model: 'ir.filters',
views: [[false, 'list'], [false, 'form']],
type: 'ir.actions.act_window',
context: {
search_default_my_filters: true,
search_default_model_id: this.dataset.model
}
});
break;
default: default:
if (val) { if (val) {
console.log("No debug handler for ", val); console.log("No debug handler for ", val);
@ -689,7 +700,7 @@ instance.web.Sidebar = instance.web.Widget.extend({
var view = this.getParent(); var view = this.getParent();
this.sections = [ this.sections = [
{ 'name' : 'print', 'label' : _t('Print'), }, { 'name' : 'print', 'label' : _t('Print'), },
{ 'name' : 'files', 'label' : _t('Attachement'), }, { 'name' : 'files', 'label' : _t('Attachment'), },
{ 'name' : 'other', 'label' : _t('More'), } { 'name' : 'other', 'label' : _t('More'), }
]; ];
this.items = { this.items = {

View File

@ -264,32 +264,6 @@
</div> </div>
</t> </t>
<t t-name="WebClient">
<table class="oe_webclient">
<tr>
<td colspan="2" class="oe_topbar">
<div class="oe_menu_placeholder"/>
<div class="oe_user_menu_placeholder"/>
<div class="oe_systray"/>
</td>
</tr>
<tr>
<td class="oe_leftbar" valign="top">
<t t-js="d">
d.url = '/' + (window.location.search || '');
</t>
<a t-att-href="url" class="oe_logo"><img t-att-src='_s + "/web/static/src/img/logo.png"'/></a>
<div class="oe_secondary_menus_container"/>
<div class="oe_footer">
Powered by <a href="http://www.openerp.com"><span>Open</span>ERP</a>
</div>
</td>
<td class="oe_application">
</td>
</tr>
</table>
</t>
<t t-name="Menu"> <t t-name="Menu">
<ul class="oe_menu" t-if="widget.data"> <ul class="oe_menu" t-if="widget.data">
<li t-foreach="widget.data.data.children" t-as="menu"> <li t-foreach="widget.data.data.children" t-as="menu">
@ -358,7 +332,7 @@
</t> </t>
<t t-name="UserMenu.about"> <t t-name="UserMenu.about">
<div> <div>
<a class="oe_activate_debug_mode" href="?debug" style="float:right; font-size: 80%;">Activate the developper mode</a> <a class="oe_activate_debug_mode" href="?debug" style="float:right; font-size: 80%;">Activate the developer mode</a>
<h1 style="margin:0;">OpenERP</h1> <h1 style="margin:0;">OpenERP</h1>
<h3 style="margin:15px 0;padding:0;">Version <t t-esc="version_info.version"/></h3> <h3 style="margin:15px 0;padding:0;">Version <t t-esc="version_info.version"/></h3>
<p> <p>
@ -409,7 +383,10 @@
</tr> </tr>
<tr> <tr>
<td class="oe_leftbar" valign="top"> <td class="oe_leftbar" valign="top">
<a href="#" class="oe_logo"><img t-att-src='_s + "/web/static/src/img/logo.png"'/></a> <t t-js="d">
d.url = '/' + (window.location.search || '');
</t>
<a t-att-href="url" class="oe_logo"><img t-att-src='_s + "/web/static/src/img/logo.png"'/></a>
<div class="oe_secondary_menus_container"/> <div class="oe_secondary_menus_container"/>
<div class="oe_footer"> <div class="oe_footer">
Powered by <a href="http://www.openerp.com"><span>Open</span>ERP</a> Powered by <a href="http://www.openerp.com"><span>Open</span>ERP</a>
@ -476,6 +453,7 @@
<option t-if="view_manager.active_view === 'form'" value="toggle_layout_outline">Toggle Form Layout Outline</option> <option t-if="view_manager.active_view === 'form'" value="toggle_layout_outline">Toggle Form Layout Outline</option>
<option value="fields">View Fields</option> <option value="fields">View Fields</option>
<option value="fvg">Fields View Get</option> <option value="fvg">Fields View Get</option>
<option value="manage_filters">Manage Filters</option>
<t t-if="view_manager.session.uid === 1"> <t t-if="view_manager.session.uid === 1">
<option value="manage_views">Manage Views</option> <option value="manage_views">Manage Views</option>
<option value="edit" data-model="ir.ui.view" t-att-data-id="view.fields_view.view_id">Edit <t t-esc="_.str.capitalize(view.fields_view.type)"/>View</option> <option value="edit" data-model="ir.ui.view" t-att-data-id="view.fields_view.view_id">Edit <t t-esc="_.str.capitalize(view.fields_view.type)"/>View</option>
@ -998,11 +976,12 @@
</div> </div>
</t> </t>
<t t-name="web.datetimepicker"> <t t-name="web.datetimepicker">
<t t-set="placeholder" t-value="widget.getParent().node and widget.getParent().node.attrs.placeholder"/>
<div class="oe_datepicker_root oe_form_field_datetime"> <div class="oe_datepicker_root oe_form_field_datetime">
<input type="text" class="oe_datepicker_container" disabled="disabled" style="display: none;"/> <input type="text" class="oe_datepicker_container" disabled="disabled" style="display: none;"/>
<input type="text" <input type="text"
t-att-name="widget.name" t-att-name="widget.name"
t-att-placeholder="widget.getParent().node.attrs.placeholder" t-att-placeholder="placeholder"
t-attf-class="oe_datepicker_master field_#{widget.type_of_date} oe_form_field_#{widget.type_of_date}" t-attf-class="oe_datepicker_master field_#{widget.type_of_date} oe_form_field_#{widget.type_of_date}"
/><img class="oe_input_icon oe_datepicker_trigger" t-att-src='_s + "/web/static/src/img/ui/field_calendar.png"' /><img class="oe_input_icon oe_datepicker_trigger" t-att-src='_s + "/web/static/src/img/ui/field_calendar.png"'
title="Select date" width="16" height="16" border="0"/> title="Select date" width="16" height="16" border="0"/>
@ -1318,7 +1297,31 @@
</t> </t>
<div t-name="SearchView" class="oe_searchview"> <div t-name="SearchView" class="oe_searchview">
<div class="oe_searchview_facets"/>
<div class="oe_searchview_clear"/>
<div class="oe_searchview_unfold_drawer"/>
<div class="oe_searchview_drawer"/>
</div> </div>
<div t-name="SearchView.InputView"
class="oe_searchview_input"
contenteditable="true"/>
<!-- tabindex: makes div focusable -->
<div t-name="SearchView.FacetView"
class="oe_searchview_facet"
tabindex="0"
><span class="oe_facet_remove"></span
><span class="oe_facet_category oe_i" t-if="widget.model.has('icon')">
<t t-esc="widget.model.get('icon')"/>
</span
><span class="oe_facet_category" t-if="!widget.model.has('icon')">
<t t-esc="widget.model.get('category')"/>
</span ><span class="oe_facet_values"
/></div>
<span t-name="SearchView.FacetView.Value" class="oe_facet_value">
<t t-esc="widget.model.get('label')"/>
</span>
<t t-name="SearchView.managed-filters"> <t t-name="SearchView.managed-filters">
<option class="oe-filters-title" value="">Filters</option> <option class="oe-filters-title" value="">Filters</option>
<optgroup label="-- Filters --"> <optgroup label="-- Filters --">
@ -1375,8 +1378,9 @@
<t t-esc="attrs.string"/> <t t-esc="attrs.string"/>
</button> </button>
<ul t-name="SearchView.filters"> <ul t-name="SearchView.filters">
<li t-foreach="widget.filters" t-as="filter"> <li t-foreach="widget.filters" t-as="filter"
<t t-esc="filter.attrs.string or filter.attrs.name or 'Ω'"/> t-att-title="filter.attrs.string ? filter.attrs.help : undefined">
<t t-esc="filter.attrs.string or filter.attrs.help or filter.attrs.name or 'Ω'"/>
</li> </li>
</ul> </ul>
<t t-name="SearchView.filters.facet"> <t t-name="SearchView.filters.facet">
@ -1471,8 +1475,22 @@
</t> </t>
</t> </t>
</t> </t>
<div t-name="SearchView.Filters" class="oe_searchview_filters">
</div>
<div t-name="SearchView.CustomFilters" class="oe_searchview_custom">
<ul class="oe_searchview_custom_list"/>
<h4 class="oe_searchview_custom_title">
<label for="oe_searchview_custom_input">Save search</label></h4>
<form>
<input id="oe_searchview_custom_input"/>
<button>Save</button><br/>
<label for="oe_searchview_custom_public">Share with all users:</label>
<input id="oe_searchview_custom_public" type="checkbox"/>
</form>
</div>
<div t-name="SearchView.advanced" class="oe_searchview_advanced"> <div t-name="SearchView.advanced" class="oe_searchview_advanced">
<h4>Advanced Search...</h4> <h4>Advanced Search</h4>
<form> <form>
<ul> <ul>
@ -1494,26 +1512,23 @@
</select> </select>
<select class="searchview_extended_prop_op"/> <select class="searchview_extended_prop_op"/>
<span class="searchview_extended_prop_value"/> <span class="searchview_extended_prop_value"/>
<a class="searchview_extended_delete_prop" <button type="button" class="searchview_extended_delete_prop">Delete</button>
href="javascript:void(0)"><span> </span></a>
</li> </li>
</t> </t>
<t t-name="SearchView.extended_search.proposition.char"> <t t-name="SearchView.extended_search.proposition.char">
<input t-att-id="widget.element_id" class="field_char"/> <input class="field_char"/>
</t> </t>
<t t-name="SearchView.extended_search.proposition.empty"> <t t-name="SearchView.extended_search.proposition.empty">
<span t-att-id="widget.element_id"></span> <span/>
</t> </t>
<t t-name="SearchView.extended_search.proposition.integer"> <t t-name="SearchView.extended_search.proposition.integer">
<input type="number" t-att-id="widget.element_id" class="field_integer" step="1"/> <input type="number" class="field_integer" step="1"/>
</t> </t>
<t t-name="SearchView.extended_search.proposition.float"> <t t-name="SearchView.extended_search.proposition.float">
<input type="number" t-att-id="widget.element_id" class="field_float" step="0.01"/> <input type="number" class="field_float" step="0.01"/>
</t>
<t t-name="SearchView.extended_search.proposition.boolean">
</t> </t>
<t t-name="SearchView.extended_search.proposition.selection"> <t t-name="SearchView.extended_search.proposition.selection">
<select t-att-id="widget.element_id"> <select>
<t t-foreach="widget.field.selection" t-as="element"> <t t-foreach="widget.field.selection" t-as="element">
<option t-att-value="element[0]"><t t-esc="element[1]"/></option> <option t-att-value="element[0]"><t t-esc="element[1]"/></option>
</t> </t>

View File

@ -66,7 +66,7 @@ $(document).ready(function () {
ok(!fail2); ok(!fail2);
}); });
asyncTest('Resolve all correctly ordered, sync', 1, function () { asyncTest('Resolve all correctly ordered, async', 1, function () {
var dm = new openerp.web.DropMisordered(); var dm = new openerp.web.DropMisordered();
var d1 = $.Deferred(), d2 = $.Deferred(), var d1 = $.Deferred(), d2 = $.Deferred(),
@ -80,7 +80,7 @@ $(document).ready(function () {
ok(true); ok(true);
}); });
}); });
asyncTest("Don't resolve mis-ordered, sync", 4, function () { asyncTest("Don't resolve mis-ordered, async", 4, function () {
var dm = new openerp.web.DropMisordered(), var dm = new openerp.web.DropMisordered(),
done1 = false, done2 = false, done1 = false, done2 = false,
fail1 = false, fail2 = false; fail1 = false, fail2 = false;
@ -104,7 +104,7 @@ $(document).ready(function () {
ok(!fail2); ok(!fail2);
}, 400); }, 400);
}); });
asyncTest('Fail mis-ordered flag, sync', 4, function () { asyncTest('Fail mis-ordered flag, async', 4, function () {
var dm = new openerp.web.DropMisordered(true), var dm = new openerp.web.DropMisordered(true),
done1 = false, done2 = false, done1 = false, done2 = false,
fail1 = false, fail2 = false; fail1 = false, fail2 = false;

File diff suppressed because it is too large Load Diff

View File

@ -10,9 +10,10 @@
<script src="/web/static/lib/underscore/underscore.js" type="text/javascript"></script> <script src="/web/static/lib/underscore/underscore.js" type="text/javascript"></script>
<script src="/web/static/lib/underscore/underscore.string.js" type="text/javascript"></script> <script src="/web/static/lib/underscore/underscore.string.js" type="text/javascript"></script>
<script src="/web/static/lib/backbone/backbone.js" type="text/javascript"></script>
<!-- jquery --> <!-- jquery -->
<script src="/web/static/lib/jquery/jquery-1.6.4.js"></script> <script src="/web/static/lib/jquery/jquery-1.7.2b1.js"></script>
<script src="/web/static/lib/jquery.ui/js/jquery-ui-1.8.17.custom.min.js"></script> <script src="/web/static/lib/jquery.ui/js/jquery-ui-1.8.17.custom.min.js"></script>
<script src="/web/static/lib/jquery.ba-bbq/jquery.ba-bbq.js"></script> <script src="/web/static/lib/jquery.ba-bbq/jquery.ba-bbq.js"></script>
@ -53,4 +54,5 @@
<script type="text/javascript" src="/web/static/test/formats.js"></script> <script type="text/javascript" src="/web/static/test/formats.js"></script>
<script type="text/javascript" src="/web/static/test/rpc.js"></script> <script type="text/javascript" src="/web/static/test/rpc.js"></script>
<script type="text/javascript" src="/web/static/test/evals.js"></script> <script type="text/javascript" src="/web/static/test/evals.js"></script>
<script type="text/javascript" src="/web/static/test/search.js"></script>
</html> </html>

View File

@ -1,500 +1,477 @@
@charset "utf-8";
.openerp .oe_kanban_view {
position: absolute;
top: 111px;
bottom: 0;
}
.openerp .oe_kanban_view .ui-sortable-placeholder { .openerp .oe_kanban_view .ui-sortable-placeholder {
border: 1px dotted black; border: 1px dotted black;
visibility: visible !important; visibility: visible !important;
height: 60px !important; height: 60px !important;
} }
.openerp .oe_kanban_groups { .openerp .oe_kanban_view .oe_kanban_left {
width: 100%; float: left;
} }
.openerp .oe_kanban_group_header { .openerp .oe_kanban_view .oe_kanban_right {
position: relative; float: right;
} }
.openerp .oe_kanban_group_folded { .openerp .oe_kanban_view .oe_kanban_clear {
padding: 0 5px 0 5px; clear: both;
} }
.openerp .oe_kanban_group_folded .oe_kanban_group_title, .openerp .oe_kanban_view .oe_kanban_groups {
.openerp .oe_kanban_group_folded.oe_kanban_column > *, height: 100%;
.openerp .oe_kanban_group_folded .oe_kanban_aggregates { }
display: none; .openerp .oe_kanban_view .oe_kanban_group_title {
} margin: 1px 1px 4px;
.openerp .oe_kanban_group_folded .oe_kanban_group_title_vertical { padding-left: 2px;
display: block; font-size: 100%;
} font-weight: bold;
color: #333333;
.openerp .oe_kanban_group_title { text-shadow: 0 1px 0 white;
font-size: 100%; }
font-weight: bold; .openerp .oe_kanban_view .oe_kanban_column, .openerp .oe_kanban_view .oe_kanban_group_header {
padding-left: 2px; vertical-align: top;
color: #333333; padding: 6px 7px 6px 6px;
} background: #f0eeee;
.openerp .oe_kanban_group_title_undefined { border-left: 1px solid #f0f8f8;
color: #666666; border-right: 1px solid #b9b9b9;
} }
.openerp .oe_kanban_group_title_vertical { .openerp .oe_kanban_view .oe_kanban_column {
writing-mode: tb-rl; height: 100%;
-webkit-transform: rotate(90deg); }
-moz-transform: rotate(90deg); .openerp .oe_kanban_view .oe_kanban_aggregates {
-o-transform: rotate(90deg); padding: 0;
-ms-transform: rotate(90deg); }
transform: rotate(90deg); .openerp .oe_kanban_view .oe_kanban_group_header {
width: 30px; position: relative;
height: 20px; }
font-size: 24px; .openerp .oe_kanban_view .oe_kanban_group_folded {
white-space: nowrap; padding: 0 5px 0 5px;
display: none; }
position: absolute; .openerp .oe_kanban_view .oe_kanban_group_folded .oe_kanban_group_title, .openerp .oe_kanban_view .oe_kanban_group_folded.oe_kanban_column > *, .openerp .oe_kanban_view .oe_kanban_group_folded .oe_kanban_aggregates {
top: 10px; display: none;
} }
.openerp .oe_kanban_show_more { .openerp .oe_kanban_view .oe_kanban_group_folded .oe_kanban_group_title_vertical {
clear: both; display: block;
text-align: center; }
} .openerp .oe_kanban_view .oe_kanban_group_title_undefined {
.openerp .oe_kanban_grouped .oe_kanban_show_more .oe_button { color: #666666;
width: 100%; }
} .openerp .oe_kanban_view .oe_kanban_group_title_vertical {
.openerp .oe_kanban_ungrouped .oe_kanban_record { writing-mode: tb-rl;
float: left; -webkit-transform: rotate(90deg);
padding: 2px; -moz-transform: rotate(90deg);
box-sizing: border-box; -o-transform: rotate(90deg);
-moz-box-sizing: border-box; -ms-transform: rotate(90deg);
-webkit-box-sizing: border-box; transform: rotate(90deg);
} width: 30px;
.openerp .oe_kanban_fold_icon { height: 20px;
cursor: pointer; font-size: 24px;
float: left; white-space: nowrap;
padding: 2px; display: none;
width: 16px; position: absolute;
height: 16px; top: 10px;
background: url(/web_kanban/static/src/img/minus-icon.png) no-repeat; }
} .openerp .oe_kanban_view .oe_kanban_fold_icon {
.openerp .oe_kanban_group_folded .oe_kanban_fold_icon { cursor: pointer;
background: url(/web_kanban/static/src/img/plus-icon.png) no-repeat; float: left;
} padding: 2px;
width: 16px;
.openerp ul.oe_kanban_aggregates { height: 16px;
padding: 0; background: url(/web_kanban/static/src/img/minus-icon.png) no-repeat;
margin: 0 0 0 22px; }
} .openerp .oe_kanban_view .oe_kanban_group_folded .oe_kanban_fold_icon {
.openerp ul.oe_kanban_aggregates li { background: url(/web_kanban/static/src/img/plus-icon.png) no-repeat;
list-style: circle; }
font-style: italic; .openerp .oe_kanban_view .oe_kanban_add {
} cursor: pointer;
.openerp ul.oe_kanban_aggregates span { position: absolute;
text-decoration: underline; top: 6px;
font-size: 90%; right: 6px;
} width: 16px;
height: 16px;
.openerp .oe_kanban_action_button { background: url(/web_kanban/static/src/img/plus-icon.png) no-repeat;
height: 22px; }
margin: 0; .openerp .oe_kanban_view .oe_kanban_quick_create {
} overflow: hidden;
.openerp .oe_kanban_action_a { }
text-decoration: none; .openerp .oe_kanban_view .oe_kanban_no_group .oe_kanban_quick_create {
} width: 200px;
padding: 10px;
.openerp .oe_kanban_box { }
background: #FFF; .openerp .oe_kanban_view .oe_kanban_quick_create input {
border: 2px solid #CCC; display: block;
border-radius: 4px; box-sizing: border-box;
-moz-border-radius: 4px; width: 100%;
-webkit-border-radius: 4px; }
margin-bottom: 5px; .openerp .oe_kanban_view .oe_kanban_quick_create button {
} float: right;
.openerp .oe_kanban_box_header { }
background: #EEE; .openerp .oe_kanban_view .oe_kanban_vignette {
border-bottom: 1px solid #CCC; padding: 8px;
} min-height: 100px;
.openerp .oe_kanban_title { }
font-size: 95%; .openerp .oe_kanban_view .oe_kanban_image {
font-weight: bold; display: inline-block;
padding: 0 4px 0 4px; vertical-align: top;
} width: 64px;
.openerp .oe_kanban_small { height: 64px;
font-size: 80%; text-align: center;
font-weight: normal; overflow: hidden;
} -moz-border-radius: 3px;
.openerp .oe_kanban_table { -webkit-border-radius: 3px;
width: 100%; border-radius: 3px;
border: none; -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
border-collapse: collapse; -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
margin: 0; -box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
padding: 0; }
} .openerp .oe_kanban_view .oe_kanban_details {
.openerp .oe_kanban_table tr td { display: inline-block;
padding: 0; vertical-align: top;
} width: 240px;
.openerp .oe_kanban_table tr td.oe_kanban_title { font-size: 13px;
padding: 2px; padding: 0 5px;
} color: #4c4c4c;
.openerp .oe_kanban_gravatar { min-height: 120px;
display: block; }
} .openerp .oe_kanban_view .oe_kanban_details h4 {
.openerp .oe_kanban_box_content { margin: 0 0 4px 0;
padding: 4px; }
font-size: 90%; .openerp .oe_kanban_view .oe_kanban_record {
} position: relative;
.openerp .oe_kanban_button { display: block;
border: 1px solid #8ec1da; min-height: 50px;
background-color: #ddeef6; margin: 0;
border-radius: 3px; display: block;
-moz-border-radius: 3px; -moz-border-radius: 4px;
-webkit-border-radius: 3px; -webkit-border-radius: 4px;
color: #000000; border-radius: 4px;
text-shadow: 0 1px #fff; }
padding: 0 4px; .openerp .oe_kanban_view .oe_kanban_record:last-child {
font-size: 85%; margin-bottom: 0;
margin: 1px; }
} .openerp .oe_kanban_view .oe_kanban_record .oe_kanban_title {
.openerp a.oe_kanban_button:hover, font-weight: bold;
.openerp button.oe_kanban_button:hover { margin: 2px 4px;
background-color: #eeddf6; }
} .openerp .oe_kanban_view .oe_kanban_grouped .oe_kanban_record {
.openerp .oe_kanban_buttons_set { margin-bottom: 6px;
border-top: 1px dotted; }
white-space: nowrap; .openerp .oe_kanban_view .oe_kanban_gravatar {
padding-top: 2px; display: block;
position: relative; width: 20px;
clear: both; height: 20px;
} -moz-border-radius: 3px;
.openerp .oe_kanban_buttons_set a { -webkit-border-radius: 3px;
padding: 2px; border-radius: 3px;
} -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
.oe_kanban_color_picker { -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
position: absolute; -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
top: -10px; }
border: 1px solid black; .openerp .oe_kanban_view .oe_kanban_avatar_toto {
-moz-box-shadow: 2px 2px 5px #666; height: 40px;
-webkit-box-shadow: 2px 2px 5px #666; width: 40px;
box-shadow: 2px 2px 5px #666; border: 1px solid;
z-index: 2; border-color: #e5e5e5 #dbdbdb #d2d2d2;
} -moz-border-radius: 3px;
.oe_kanban_color_picker a { -webkit-border-radius: 3px;
display: block; border-radius: 3px;
width: 30px; -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
height: 30px; -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
border: 1px solid black; -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
text-align: center; }
text-decoration: none; .openerp .oe_kanban_view .oe_kanban_box {
} background: white;
.oe_kanban_color_picker a:hover { border: 2px solid #cccccc;
border-color: white; border-radius: 4px;
} -moz-border-radius: 4px;
.oe_kanban_color_picker span { -webkit-border-radius: 4px;
border: none; margin-bottom: 5px;
font-size: 120%; }
font-weight: bold; .openerp .oe_kanban_view .oe_kanban_box_header {
color: black; background: #eeeeee;
line-height: 30px; border-bottom: 1px solid #cccccc;
} }
.openerp .oe_kanban_left { .openerp .oe_kanban_view .oe_kanban_title {
float: left; font-size: 95%;
} font-weight: bold;
.openerp .oe_kanban_right { padding: 0 4px 0 4px;
float: right; }
} .openerp .oe_kanban_view .oe_kanban_small {
.openerp .oe_kanban_clear { font-size: 80%;
clear: both; font-weight: normal;
} }
.openerp .oe_kanban_box_show_onclick { .openerp .oe_kanban_view .oe_kanban_show_more {
display: none; clear: both;
} text-align: center;
.openerp .oe_kanban_draghandle { }
cursor: move; .openerp .oe_kanban_view .oe_kanban_grouped .oe_kanban_show_more .oe_button {
} width: 100%;
.openerp .oe_kanban_color_border { }
border-color: #CCCCCC; .openerp .oe_kanban_view .oe_kanban_ungrouped .oe_kanban_record {
} float: left;
.openerp .oe_kanban_color_border { padding: 2px;
border-color: #CCCCCC; box-sizing: border-box;
} -moz-box-sizing: border-box;
.openerp .oe_kanban_tooltip ul, -webkit-box-sizing: border-box;
.openerp ul.oe_kanban_tooltip { }
padding: 0 0 4px 0; .openerp .oe_kanban_view .oe_kanban_action_button {
margin: 5px 0 0 15px; height: 22px;
list-style: circle; margin: 0;
} }
.openerp .oe_kanban_highlight { .openerp .oe_kanban_view .oe_kanban_action_a {
border-radius: 2px; text-decoration: none;
-moz-border-radius: 2px; }
-webkit-border-radius: 2px; .openerp .oe_kanban_view .oe_kanban_table {
padding: 1px 5px; width: 100%;
margin: 1px 4px; border: none;
white-space: nowrap; border-collapse: collapse;
display: inline-block; margin: 0;
line-height: 1em; padding: 0;
} }
.openerp .oe_kanban_view .oe_kanban_table tr td {
.openerp .oe_kanban_add { padding: 0;
cursor: pointer; }
position: absolute; .openerp .oe_kanban_view .oe_kanban_table tr td.oe_kanban_title {
top: 6px; padding: 2px;
right: 6px; }
width: 16px; .openerp .oe_kanban_view .oe_kanban_box_content {
height: 16px; padding: 4px;
background: url(/web_kanban/static/src/img/plus-icon.png) no-repeat; font-size: 90%;
} }
.openerp .oe_kanban_view .oe_kanban_button {
.openerp .oe_kanban_quick_create { border: 1px solid #8ec1da;
/* apply block formatting context */ background-color: #ddeef6;
overflow: hidden; border-radius: 3px;
} -moz-border-radius: 3px;
.openerp .oe_kanban_no_group .oe_kanban_quick_create { -webkit-border-radius: 3px;
width: 200px; color: black;
padding: 10px; text-shadow: 0 1px white;
} padding: 0 4px;
.openerp .oe_kanban_quick_create input { font-size: 85%;
display: block; margin: 1px;
/* margins within width */ }
box-sizing: border-box; .openerp .oe_kanban_view a.oe_kanban_button:hover, .openerp .oe_kanban_view .openerp button.oe_kanban_button:hover {
width: 100%; background-color: #eeddf6;
} }
.openerp .oe_kanban_quick_create button { .openerp .oe_kanban_view .oe_kanban_buttons_set {
float: right; border-top: 1px dotted;
} white-space: nowrap;
padding-top: 2px;
/* Custom colors are also present in kanban.js */ position: relative;
/* Custom color#0 */ clear: both;
.openerp .oe_kanban_color_0 .oe_kanban_color_bglight { }
background: #FFFFFF; .openerp .oe_kanban_view .oe_kanban_buttons_set a {
} padding: 2px;
.openerp .oe_kanban_color_0 .oe_kanban_color_bgdark { }
background: #EEEEEE; .openerp .oe_kanban_view .oe_kanban_box_show_onclick {
} display: none;
.openerp .oe_kanban_color_0 .oe_kanban_color_border { }
border-color: #CCCCCC; .openerp .oe_kanban_view .oe_kanban_draghandle {
} cursor: move;
.openerp .oe_kanban_color_0 .oe_kanban_button { }
background-color: #EEEEEE; .openerp .oe_kanban_view .oe_kanban_color_border {
border-color: #CCCCCC; border-color: #cccccc;
text-shadow: 0 1px #FFFFFF; }
} .openerp .oe_kanban_view .oe_kanban_color_border {
.openerp .oe_kanban_color_0 .oe_kanban_button_active, border-color: #cccccc;
.openerp .oe_kanban_color_0 a.oe_kanban_button:hover, }
.openerp .oe_kanban_color_0 button.oe_kanban_button:hover { .openerp .oe_kanban_view .oe_kanban_tooltip ul, .openerp .oe_kanban_view ul.oe_kanban_tooltip {
background-color: #999999; padding: 0 0 4px 0;
color: #fff; margin: 5px 0 0 15px;
text-shadow: 0 1px #000; list-style: circle;
} }
.openerp .oe_kanban_view .oe_kanban_highlight {
/* Custom color#1 */ border-radius: 2px;
.openerp .oe_kanban_color_1 .oe_kanban_color_bglight { -moz-border-radius: 2px;
background: #CCCCCC; -webkit-border-radius: 2px;
} padding: 1px 5px;
.openerp .oe_kanban_color_1 .oe_kanban_color_bgdark { margin: 1px 4px;
background: #999999; white-space: nowrap;
} display: inline-block;
.openerp .oe_kanban_color_1 .oe_kanban_color_border { line-height: 1em;
border-color: #666666; }
} .openerp .oe_kanban_view .oe_kanban_card {
.openerp .oe_kanban_color_1 .oe_kanban_button { position: relative;
background-color: #999999; display: block;
border-color: #666666; min-height: 50px;
text-shadow: 0 1px #CCCCCC; background: white;
} border: 1px solid #d8d8d8;
.openerp .oe_kanban_color_1 .oe_kanban_button_active, border-bottom-color: #b9b9b9;
.openerp .oe_kanban_color_1 a.oe_kanban_button:hover, padding: 6px;
.openerp .oe_kanban_color_1 button.oe_kanban_button:hover { display: block;
background-color: #666666; -moz-border-radius: 4px;
color: #fff; -webkit-border-radius: 4px;
text-shadow: 0 1px #000; border-radius: 4px;
} }
.openerp .oe_kanban_view .oe_kanban_card:last-child {
/* Custom color#2 */ margin-bottom: 0;
.openerp .oe_kanban_color_2 .oe_kanban_color_bglight { }
background: #FFC7C7; .openerp .oe_kanban_view .oe_kanban_card:hover {
} -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.6);
.openerp .oe_kanban_color_2 .oe_kanban_color_bgdark { -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.6);
background: #FF8F8F; -box-shadow: 0 0 3px rgba(0, 0, 0, 0.6);
} }
.openerp .oe_kanban_color_2 .oe_kanban_color_border { .openerp .oe_kanban_view .oe_kanban_card:hover .oe_kanban_menuaction {
border-color: #D97979; display: block;
} }
.openerp .oe_kanban_color_2 .oe_kanban_button { .openerp .oe_kanban_view .oe_kanban_card h3 {
background-color: #FF8F8F; margin: 0 16px 0 0;
border-color: #D97979; color: #4c4c4c;
text-shadow: 0 1px #FFC7C7; text-decoration: none;
} }
.openerp .oe_kanban_color_2 .oe_kanban_button_active, .openerp .oe_kanban_view .oe_kanban_card h3:hover {
.openerp .oe_kanban_color_2 a.oe_kanban_button:hover, text-decoration: none;
.openerp .oe_kanban_color_2 button.oe_kanban_button:hover { }
background-color: #CC5C5C; .openerp .oe_kanban_view .oe_kanban_star {
color: #fff; float: left;
text-shadow: 0 1px #000; position: inline-block;
} margin: 0 4px 0 0;
}
/* Custom color#3 */ .openerp .oe_kanban_view .oe_kanban_avatar {
.openerp .oe_kanban_color_3 .oe_kanban_color_bglight { -moz-border-radius: 4px;
background: #FFF1C7; -webkit-border-radius: 4px;
} border-radius: 4px;
.openerp .oe_kanban_color_3 .oe_kanban_color_bgdark { -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
background: #FFE38F; -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
} -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
.openerp .oe_kanban_color_3 .oe_kanban_color_border { }
border-color: #D9C179; .openerp .oe_kanban_view .oe_kanban_status {
} display: inline-block;
.openerp .oe_kanban_color_3 .oe_kanban_button { height: 12px;
background-color: #FFE38F; width: 12px;
border-color: #D9C179; margin: 4px auto;
text-shadow: 0 1px #FFF1C7; -moz-border-radius: 6px;
} -webkit-border-radius: 6px;
.openerp .oe_kanban_color_3 .oe_kanban_button_active, border-radius: 6px;
.openerp .oe_kanban_color_3 a.oe_kanban_button:hover, -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
.openerp .oe_kanban_color_3 button.oe_kanban_button:hover { -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
background-color: #CCB05C; -box-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
color: #fff; }
text-shadow: 0 1px #000; .openerp .oe_kanban_view .oe_kanban_status_green {
} background: green;
background-position: center center;
/* Custom color#4 */ background-image: -webkit-radial-gradient(circle, #55dd55 0%, #44aa44 40%, #339933 100%);
.openerp .oe_kanban_color_4 .oe_kanban_color_bglight { background-image: -moz-radial-gradient(#55dd55 0%, #44aa44 40%, #339933 100%);
background: #E3FFC7; background-image: -ms-radial-gradient(#55dd55 0%, #44aa44 40%, #339933 100%);
} background-image: radial-gradient(#55dd55 0%, #44aa44 40%, #339933 100%);
.openerp .oe_kanban_color_4 .oe_kanban_color_bgdark { }
background: #C7FF8F; .openerp .oe_kanban_view .oe_kanban_status_red {
} background: red;
.openerp .oe_kanban_color_4 .oe_kanban_color_border { background-position: center center;
border-color: #A9D979; background-image: -webkit-radial-gradient(circle, #ee7777 0%, #cc3333 40%, #bb0808 100%);
} background-image: -moz-radial-gradient(#ee7777 0%, #cc3333 40%, #bb0808 100%);
.openerp .oe_kanban_color_4 .oe_kanban_button { background-image: -ms-radial-gradient(#ee7777 0%, #cc3333 40%, #bb0808 100%);
background-color: #C7FF8F; background-image: radial-gradient(#ee7777 0%, #cc3333 40%, #bb0808 100%);
border-color: #A9D979; }
text-shadow: 0 1px #E3FFC7; .openerp .oe_kanban_view .oe_kanban_text_red {
} background: red;
.openerp .oe_kanban_color_4 .oe_kanban_button_active, color: black;
.openerp .oe_kanban_color_4 a.oe_kanban_button:hover, }
.openerp .oe_kanban_color_4 button.oe_kanban_button:hover { .openerp .oe_kanban_view .oe_kanban_ellipsis {
background-color: #94CC5C; overflow: hidden;
color: #fff; text-overflow: ellipsis;
text-shadow: 0 1px #000; white-space: nowrap;
} }
.openerp .oe_kanban_view a.oe_kanban_menuaction {
/* Custom color#5 */ position: absolute;
.openerp .oe_kanban_color_5 .oe_kanban_color_bglight { top: 0px;
background: #C7FFD5; right: 3px;
} display: none;
.openerp .oe_kanban_color_5 .oe_kanban_color_bgdark { color: #4c4c4c;
background: #8FFFAB; cursor: pointer;
} }
.openerp .oe_kanban_color_5 .oe_kanban_color_border { .openerp .oe_kanban_view a.oe_kanban_menuaction:hover {
border-color: #79D991; text-decoration: none;
} }
.openerp .oe_kanban_color_5 .oe_kanban_button { .openerp .oe_kanban_view .oe_kanban_menu {
background-color: #8FFFAB; display: none;
border-color: #79D991; position: absolute;
text-shadow: 0 1px #C7FFD5; top: 30px;
} right: -140px;
.openerp .oe_kanban_color_5 .oe_kanban_button_active, padding: 4px;
.openerp .oe_kanban_color_5 a.oe_kanban_button:hover, border: 1px solid #afafb6;
.openerp .oe_kanban_color_5 button.oe_kanban_button:hover { min-width: 160px;
background-color: #5CCC78; overflow-x: hidden;
color: #fff; z-index: 900;
text-shadow: 0 1px #000; background: white;
} -moz-border-radius: 3px;
-webkit-border-radius: 3px;
/* Custom color#6 */ border-radius: 3px;
.openerp .oe_kanban_color_6 .oe_kanban_color_bglight { -moz-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
background: #C7FFFF; -webkit-box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
} -box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
.openerp .oe_kanban_color_6 .oe_kanban_color_bgdark { }
background: #8FFFFF; .openerp .oe_kanban_view .oe_kanban_menu p {
} margin-left: 12px;
.openerp .oe_kanban_color_6 .oe_kanban_color_border { }
border-color: #79D9D9; .openerp .oe_kanban_view .oe_kanban_menu > li > a {
} display: block;
.openerp .oe_kanban_color_6 .oe_kanban_button { padding: 3px 6px;
background-color: #8FFFFF; line-height: 14px;
border-color: #79D9D9; color: #4c4c4c;
text-shadow: 0 1px #C7FFFF; text-decoration: none;
} }
.openerp .oe_kanban_color_6 .oe_kanban_button_active, .openerp .oe_kanban_view .oe_kanban_menu > li > a:hover {
.openerp .oe_kanban_color_6 a.oe_kanban_button:hover, background: #f0f0fa;
.openerp .oe_kanban_color_6 button.oe_kanban_button:hover { background: -moz-linear-gradient(#f0f0fa, #eeeef6);
background-color: #5CCCCC; background: -webkit-gradient(linear, left top, left bottom, from(#f0f0fa), to(#eeeef6));
color: #fff; background: -webkit-linear-gradient(#f0f0fa, #eeeef6);
text-shadow: 0 1px #000; -moz-box-shadow: none;
} -webkit-box-shadow: none;
-box-shadow: none;
/* Custom color#7 */ }
.openerp .oe_kanban_color_7 .oe_kanban_color_bglight { .openerp .oe_kanban_view .oe_kanban_colorpicker {
background: #C7D5FF; padding: 3px 6px;
} }
.openerp .oe_kanban_color_7 .oe_kanban_color_bgdark { .openerp .oe_kanban_view .oe_kanban_colorpicker li {
background: #8FABFF; float: left;
} }
.openerp .oe_kanban_color_7 .oe_kanban_color_border { .openerp .oe_kanban_view .oe_kanban_colorpicker li a {
border-color: #8FABFF; display: inline-block;
} width: 18px;
.openerp .oe_kanban_color_7 .oe_kanban_button { height: 18px;
background-color: #8FABFF; border: 1px solid white;
border-color: #7995E9; }
text-shadow: 0 1px #C7D5FF; .openerp .oe_kanban_view .oe_kanban_colorpicker li a:hover {
} border: 1px solid gray !important;
.openerp .oe_kanban_color_7 .oe_kanban_button_active, }
.openerp .oe_kanban_color_7 a.oe_kanban_button:hover, .openerp .oe_kanban_view .oe_kanban_colorpicker li:first-child a {
.openerp .oe_kanban_color_7 button.oe_kanban_button:hover { margin-top: 1px;
background-color: #5C78CC; height: 16px;
color: #fff; border: 1px solid #cccccc;
text-shadow: 0 1px #000; }
} .openerp .oe_kanban_view .oe_kanban_colorpicker li:first-child a:hover {
margin-top: 0px;
/* Custom color#8 */ height: 18px;
.openerp .oe_kanban_color_8 .oe_kanban_color_bglight { }
background: #E3C7FF; .openerp .oe_kanban_view .oe_kanban_color_0 {
} background-color: white;
.openerp .oe_kanban_color_8 .oe_kanban_color_bgdark { }
background: #C78FFF; .openerp .oe_kanban_view .oe_kanban_color_1 {
} background-color: #cccccc;
.openerp .oe_kanban_color_8 .oe_kanban_color_border { }
border-color: #A979D9; .openerp .oe_kanban_view .oe_kanban_color_2 {
} background-color: #ffc7c7;
.openerp .oe_kanban_color_8 .oe_kanban_button { }
background-color: #C78FFF; .openerp .oe_kanban_view .oe_kanban_color_3 {
border-color: #A979D9; background-color: #fff1c7;
text-shadow: 0 1px #E3C7FF; }
} .openerp .oe_kanban_view .oe_kanban_color_4 {
.openerp .oe_kanban_color_8 .oe_kanban_button_active, background-color: #e3ffc7;
.openerp .oe_kanban_color_8 a.oe_kanban_button:hover, }
.openerp .oe_kanban_color_8 button.oe_kanban_button:hover { .openerp .oe_kanban_view .oe_kanban_color_5 {
background-color: #945CCC; background-color: #c7ffd5;
color: #fff; }
text-shadow: 0 1px #000; .openerp .oe_kanban_view .oe_kanban_color_6 {
} background-color: #c7ffff;
}
/* Custom color#9 */ .openerp .oe_kanban_view .oe_kanban_color_7 {
.openerp .oe_kanban_color_9 .oe_kanban_color_bglight { background-color: #c7d5ff;
background: #FFC7F1; }
} .openerp .oe_kanban_view .oe_kanban_color_8 {
.openerp .oe_kanban_color_9 .oe_kanban_color_bgdark { background-color: #e3c7ff;
background: #FF8FE3; }
} .openerp .oe_kanban_view .oe_kanban_color_9 {
.openerp .oe_kanban_color_9 .oe_kanban_color_border { background-color: #ffc7f1;
border-color: #D979C1;
}
.openerp .oe_kanban_color_9 .oe_kanban_button {
background-color: #FF8FE3;
border-color: #D979C1;
text-shadow: 0 1px #FFC7F1;
}
.openerp .oe_kanban_color_9 .oe_kanban_button_active,
.openerp .oe_kanban_color_9 a.oe_kanban_button:hover,
.openerp .oe_kanban_color_9 button.oe_kanban_button:hover {
background-color: #CC5CB0;
color: #fff;
text-shadow: 0 1px #000;
}
/* Red border */
.openerp .oe_kanban_color_alert .oe_kanban_color_border,
.openerp .oe_kanban_color_red .oe_kanban_color_border {
border-color: #c00 !important;
}
/* Green border */
.openerp .oe_kanban_color_green .oe_kanban_color_border {
border-color: #0c0 !important;
}
/* Blue border */
.openerp .oe_kanban_color_blue .oe_kanban_color_border {
border-color: #00c !important;
} }

View File

@ -0,0 +1,395 @@
@charset "utf-8"
// Mixins {{{
@mixin radial-gradient($gradient)
background-position: center center
background-image: -webkit-radial-gradient(circle, $gradient)
background-image: -moz-radial-gradient($gradient)
background-image: -ms-radial-gradient($gradient)
background-image: radial-gradient($gradient)
@mixin radius($radius: 5px)
-moz-border-radius: $radius
-webkit-border-radius: $radius
border-radius: $radius
@mixin box-shadow($bsval: 0px 1px 4px #777)
-moz-box-shadow: $bsval
-webkit-box-shadow: $bsval
-box-shadow: $bsval
// }}}
.openerp .oe_kanban_view
// KanbanView {{{
position: absolute
top: 111px
bottom: 0
.ui-sortable-placeholder
border: 1px dotted black
visibility: visible !important
height: 60px !important
.oe_kanban_left
float: left
.oe_kanban_right
float: right
.oe_kanban_clear
clear: both
// }}}
// KanbanGroups {{{
.oe_kanban_groups
height: 100%
.oe_kanban_group_title
margin: 1px 1px 4px
padding-left: 2px
font-size: 100%
font-weight: bold
color: #333333
text-shadow: 0 1px 0 white
.oe_kanban_column, .oe_kanban_group_header
vertical-align: top
padding: 6px 7px 6px 6px
background: #f0eeee
border-left: 1px solid #f0f8f8
border-right: 1px solid #b9b9b9
.oe_kanban_column
height: 100%
.oe_kanban_aggregates
padding: 0
.oe_kanban_group_header
position: relative
.oe_kanban_group_folded
padding: 0 5px 0 5px
.oe_kanban_group_title, &.oe_kanban_column > *, .oe_kanban_aggregates
display: none
.oe_kanban_group_title_vertical
display: block
.oe_kanban_group_title_undefined
color: #666666
.oe_kanban_group_title_vertical
writing-mode: tb-rl
-webkit-transform: rotate(90deg)
-moz-transform: rotate(90deg)
-o-transform: rotate(90deg)
-ms-transform: rotate(90deg)
transform: rotate(90deg)
width: 30px
height: 20px
font-size: 24px
white-space: nowrap
display: none
position: absolute
top: 10px
.oe_kanban_fold_icon
cursor: pointer
float: left
padding: 2px
width: 16px
height: 16px
background: url(/web_kanban/static/src/img/minus-icon.png) no-repeat
.oe_kanban_group_folded .oe_kanban_fold_icon
background: url(/web_kanban/static/src/img/plus-icon.png) no-repeat
// }}}
// KanbanQuickCreate {{{
.oe_kanban_add
cursor: pointer
position: absolute
top: 6px
right: 6px
width: 16px
height: 16px
background: url(/web_kanban/static/src/img/plus-icon.png) no-repeat
.oe_kanban_quick_create
// apply block formatting context
overflow: hidden
.oe_kanban_no_group .oe_kanban_quick_create
width: 200px
padding: 10px
.oe_kanban_quick_create input
display: block
// margins within width
box-sizing: border-box
width: 100%
.oe_kanban_quick_create button
float: right
// }}}
// KanbanRecords {{{
.oe_kanban_vignette
padding: 8px
min-height: 100px
.oe_kanban_image
display: inline-block
vertical-align: top
width: 64px
height: 64px
text-align: center
overflow: hidden
@include radius(3px)
@include box-shadow(0 1px 4px rgba(0, 0, 0, 0.4))
.oe_kanban_details
display: inline-block
vertical-align: top
width: 240px
font-size: 13px
padding: 0 5px
color: #4c4c4c
min-height: 120px
h4
margin: 0 0 4px 0
.oe_kanban_record
position: relative
display: block
min-height: 50px
margin: 0
display: block
@include radius(4px)
&:last-child
margin-bottom: 0
.oe_kanban_title
font-weight: bold
margin: 2px 4px
.oe_kanban_grouped .oe_kanban_record
margin-bottom: 6px
.oe_kanban_gravatar
display: block
width: 20px
height: 20px
@include radius(3px)
@include box-shadow(0 1px 2px rgba(0,0,0,0.2))
.oe_kanban_avatar_toto
height: 40px
width: 40px
border: 1px solid
border-color: #e5e5e5 #dbdbdb #d2d2d2
@include radius(3px)
@include box-shadow(0 1px 2px rgba(0,0,0,0.2))
.oe_kanban_box
background: #FFF
border: 2px solid #CCC
border-radius: 4px
-moz-border-radius: 4px
-webkit-border-radius: 4px
margin-bottom: 5px
.oe_kanban_box_header
background: #EEE
border-bottom: 1px solid #CCC
.oe_kanban_title
font-size: 95%
font-weight: bold
padding: 0 4px 0 4px
.oe_kanban_small
font-size: 80%
font-weight: normal
.oe_kanban_show_more
clear: both
text-align: center
.oe_kanban_grouped .oe_kanban_show_more .oe_button
width: 100%
.oe_kanban_ungrouped .oe_kanban_record
float: left
padding: 2px
box-sizing: border-box
-moz-box-sizing: border-box
-webkit-box-sizing: border-box
.oe_kanban_action_button
height: 22px
margin: 0
.oe_kanban_action_a
text-decoration: none
.oe_kanban_table
width: 100%
border: none
border-collapse: collapse
margin: 0
padding: 0
.oe_kanban_table tr td
padding: 0
.oe_kanban_table tr td.oe_kanban_title
padding: 2px
.oe_kanban_box_content
padding: 4px
font-size: 90%
.oe_kanban_button
border: 1px solid #8ec1da
background-color: #ddeef6
border-radius: 3px
-moz-border-radius: 3px
-webkit-border-radius: 3px
color: #000000
text-shadow: 0 1px #fff
padding: 0 4px
font-size: 85%
margin: 1px
a.oe_kanban_button:hover, .openerp button.oe_kanban_button:hover
background-color: #eeddf6
.oe_kanban_buttons_set
border-top: 1px dotted
white-space: nowrap
padding-top: 2px
position: relative
clear: both
a
padding: 2px
.oe_kanban_box_show_onclick
display: none
.oe_kanban_draghandle
cursor: move
.oe_kanban_color_border
border-color: #CCCCCC
.oe_kanban_color_border
border-color: #CCCCCC
.oe_kanban_tooltip ul, ul.oe_kanban_tooltip
padding: 0 0 4px 0
margin: 5px 0 0 15px
list-style: circle
.oe_kanban_highlight
border-radius: 2px
-moz-border-radius: 2px
-webkit-border-radius: 2px
padding: 1px 5px
margin: 1px 4px
white-space: nowrap
display: inline-block
line-height: 1em
.oe_kanban_card
position: relative
display: block
min-height: 50px
background: white
border: 1px solid #d8d8d8
border-bottom-color: #b9b9b9
padding: 6px
display: block
@include radius(4px)
&:last-child
margin-bottom: 0
&:hover
@include box-shadow(0 0 3px rgba(0,0,0,0.6))
.oe_kanban_menuaction
display: block
h3
margin: 0 16px 0 0
color: #4c4c4c
text-decoration: none
h3:hover
text-decoration: none
.oe_kanban_star
float: left
position: inline-block
margin: 0 4px 0 0
.oe_kanban_avatar
@include radius(4px)
@include box-shadow(0 1px 2px rgba(0,0,0,0.2))
//.oe_kanban_footer_left
// float: left
.oe_kanban_status
display: inline-block
height: 12px
width: 12px
margin: 4px auto
@include radius(6px)
@include box-shadow(0 1px 3px rgba(0,0,0,0.6))
.oe_kanban_status_green
background: green
@include radial-gradient((#55dd55 0%, #44aa44 40%, #339933 100%))
.oe_kanban_status_red
background: red
@include radial-gradient((#ee7777 0%, #cc3333 40%, #bb0808 100%))
.oe_kanban_text_red
background: red
color: #000
.oe_kanban_ellipsis
overflow: hidden
text-overflow: ellipsis
white-space: nowrap
// }}}
// KanbanDropDown {{{
a.oe_kanban_menuaction
position: absolute
top: 0px
right: 3px
display: none
color: #4c4c4c
cursor: pointer
&:hover
text-decoration: none
.oe_kanban_menu
display: none
position: absolute
top: 30px
right: -140px
padding: 4px
border: 1px solid #afafb6
min-width: 160px
overflow-x: hidden
z-index: 900
background: white
@include radius(3px)
@include box-shadow(0 1px 4px rgba(0,0,0,0.3))
p
margin-left: 12px
> li > a
display: block
padding: 3px 6px
line-height: 14px
color: #4c4c4c
text-decoration: none
> li > a:hover
background: #f0f0fa
background: -moz-linear-gradient(#f0f0fa, #eeeef6)
background: -webkit-gradient(linear, left top, left bottom, from(#f0f0fa), to(#eeeef6))
background: -webkit-linear-gradient(#f0f0fa, #eeeef6)
@include box-shadow(none)
// }}}
// KanbanColorPicker {{{
.oe_kanban_colorpicker
padding: 3px 6px
.oe_kanban_colorpicker li
float: left
a
display: inline-block
width: 18px
height: 18px
border: 1px solid white
a:hover
border: 1px solid gray !important
.oe_kanban_colorpicker li:first-child a
margin-top: 1px
height: 16px
border: 1px solid #ccc
&:hover
margin-top: 0px
height: 18px
// }}}
// KanbanColors {{{
.oe_kanban_color_0
background-color: #FFFFFF
.oe_kanban_color_1
background-color: #CCCCCC
.oe_kanban_color_2
background-color: #FFC7C7
.oe_kanban_color_3
background-color: #FFF1C7
.oe_kanban_color_4
background-color: #E3FFC7
.oe_kanban_color_5
background-color: #C7FFD5
.oe_kanban_color_6
background-color: #C7FFFF
.oe_kanban_color_7
background-color: #C7D5FF
.oe_kanban_color_8
background-color: #E3C7FF
.oe_kanban_color_9
background-color: #FFC7F1
// au BufWritePost,FileWritePost *.sass :!sass --style expanded --line-numbers <afile> > "%:p:r.css"
// vim:tabstop=4:shiftwidth=4:softtabstop=4:fdm=marker:

View File

@ -10,6 +10,7 @@ instance.web_kanban.KanbanView = instance.web.View.extend({
display_name: _lt('Kanban'), display_name: _lt('Kanban'),
default_nr_columns: 3, default_nr_columns: 3,
view_type: "kanban", view_type: "kanban",
number_of_color_schemes: 10,
init: function (parent, dataset, view_id, options) { init: function (parent, dataset, view_id, options) {
this._super(parent, dataset, view_id, options); this._super(parent, dataset, view_id, options);
_.defaults(this.options, {"quick_creatable": true, "creatable": true}); _.defaults(this.options, {"quick_creatable": true, "creatable": true});
@ -34,6 +35,34 @@ instance.web_kanban.KanbanView = instance.web.View.extend({
this.limit = options.limit || 80; this.limit = options.limit || 80;
this.add_group_mutex = new $.Mutex(); this.add_group_mutex = new $.Mutex();
}, },
start: function() {
var self = this;
this._super.apply(this, arguments);
// Bind kanban cards dropdown menus
this.$element.on('click', '.oe_kanban_menuaction', function() {
var $menu = $(this).next('.oe_kanban_menu');
var show = !$menu.is(':visible');
self.$element.find('.oe_kanban_menu').hide();
var doc_width = $(document).width();
$menu.toggle(show);
if (show) {
var offset = $menu.offset();
var menu_width = $menu.width();
var x = doc_width - offset.left - menu_width - 15;
if (x < 0) {
$menu.offset({ left: offset.left + x }).width(menu_width);
}
}
return false;
});
$('html').on('click', function() {
self.$element.find('.oe_kanban_menu').hide();
});
},
destroy: function() {
this._super.apply(this, arguments);
$('html').off('click');
},
on_loaded: function(data) { on_loaded: function(data) {
this.fields_view = data; this.fields_view = data;
this.$buttons = $(QWeb.render("KanbanView.buttons", {'widget': this})); this.$buttons = $(QWeb.render("KanbanView.buttons", {'widget': this}));
@ -95,7 +124,7 @@ instance.web_kanban.KanbanView = instance.web.View.extend({
case 'button': case 'button':
case 'a': case 'a':
var type = node.attrs.type || ''; var type = node.attrs.type || '';
if (_.indexOf('action,object,edit,delete,color'.split(','), type) !== -1) { if (_.indexOf('action,object,edit,delete'.split(','), type) !== -1) {
_.each(node.attrs, function(v, k) { _.each(node.attrs, function(v, k) {
if (_.indexOf('icon,type,name,args,string,context,states,kanban_states'.split(','), k) != -1) { if (_.indexOf('icon,type,name,args,string,context,states,kanban_states'.split(','), k) != -1) {
node.attrs['data-' + k] = v; node.attrs['data-' + k] = v;
@ -359,7 +388,7 @@ instance.web_kanban.KanbanGroup = instance.web.OldWidget.extend({
if (!this.view.state.groups[key]) { if (!this.view.state.groups[key]) {
this.view.state.groups[key] = { this.view.state.groups[key] = {
folded: false folded: false
} };
} }
this.state = this.view.state.groups[key]; this.state = this.view.state.groups[key];
this.$records = null; this.$records = null;
@ -405,18 +434,23 @@ instance.web_kanban.KanbanGroup = instance.web.OldWidget.extend({
this.$element.data('widget', this); this.$element.data('widget', this);
this.$records.data('widget', this); this.$records.data('widget', this);
this.$has_been_started.resolve(); this.$has_been_started.resolve();
this.compute_cards_height(); this.compute_cards_auto_height();
return def; return def;
}, },
compute_cards_height: function() { compute_cards_auto_height: function() {
// oe_kanban_auto_height is an empty class used by the kanban view in order
// to normalize height amongst kanban cards. (by group)
var self = this; var self = this;
var min_height = 0; var min_height = 0;
var els = [];
_.each(this.records, function(r) { _.each(this.records, function(r) {
min_height = Math.max(min_height, r.$element.outerHeight()); var $e = r.$element.find('.oe_kanban_auto_height').first().css('min-height', 0);
}); if ($e.length) {
_.each(this.records, function(r) { els.push($e[0]);
r.$element.css('min-height', min_height); min_height = Math.max(min_height, $e.outerHeight());
}
}); });
$(els).css('min-height', min_height);
}, },
destroy: function() { destroy: function() {
this._super(); this._super();
@ -534,8 +568,9 @@ instance.web_kanban.KanbanRecord = instance.web.OldWidget.extend({
}); });
}, },
bind_events: function() { bind_events: function() {
var self = this, var self = this;
$show_on_click = self.$element.find('.oe_kanban_box_show_onclick'); this.setup_color_picker();
var $show_on_click = self.$element.find('.oe_kanban_box_show_onclick');
$show_on_click.toggle(this.state.folded); $show_on_click.toggle(this.state.folded);
this.$element.find('.oe_kanban_box_show_onclick_trigger').click(function() { this.$element.find('.oe_kanban_box_show_onclick_trigger').click(function() {
$show_on_click.toggle(); $show_on_click.toggle();
@ -559,7 +594,13 @@ instance.web_kanban.KanbanRecord = instance.web.OldWidget.extend({
trigger: 'hover' trigger: 'hover'
}); });
this.$element.find('.oe_kanban_action').click(function() { // If no draghandle is found, make the whole card as draghandle
if (!this.$element.find('.oe_kanban_draghandle').length) {
this.$element.children(':first').addClass('oe_kanban_draghandle');
}
this.$element.find('.oe_kanban_action').click(function(ev) {
ev.preventDefault();
var $action = $(this), var $action = $(this),
type = $action.data('type') || 'button', type = $action.data('type') || 'button',
method = 'do_action_' + (type === 'action' ? 'object' : type); method = 'do_action_' + (type === 'action' ? 'object' : type);
@ -570,9 +611,27 @@ instance.web_kanban.KanbanRecord = instance.web.OldWidget.extend({
} else { } else {
self.do_warn("Kanban: no action for type : " + type); self.do_warn("Kanban: no action for type : " + type);
} }
return false;
}); });
}, },
setup_color_picker: function() {
var self = this;
var $el = this.$element.find('ul.oe_kanban_colorpicker');
if ($el.length) {
$el.html(QWeb.render('KanbanColorPicker', {
widget: this
}));
$el.on('click', 'a', function(ev) {
ev.preventDefault();
var color_field = $(this).parents('.oe_kanban_colorpicker').first().data('field') || 'color';
var data = {};
data[color_field] = $(this).data('color');
self.view.dataset.write(self.id, data, {}, function() {
self.record[color_field] = $(this).data('color');
self.do_reload();
});
});
}
},
do_action_delete: function($action) { do_action_delete: function($action) {
var self = this; var self = this;
if (confirm(_t("Are you sure you want to delete this record ?"))) { if (confirm(_t("Are you sure you want to delete this record ?"))) {
@ -592,28 +651,6 @@ instance.web_kanban.KanbanRecord = instance.web.OldWidget.extend({
this.view.open_record(this.id); this.view.open_record(this.id);
} }
}, },
do_action_color: function($action) {
var self = this,
colors = '#FFFFFF,#CCCCCC,#FFC7C7,#FFF1C7,#E3FFC7,#C7FFD5,#C7FFFF,#C7D5FF,#E3C7FF,#FFC7F1'.split(','),
$cpicker = $(QWeb.render('KanbanColorPicker', { colors : colors, columns: 2 }));
$action.after($cpicker);
$cpicker.mouseenter(function() {
clearTimeout($cpicker.data('timeoutId'));
}).mouseleave(function(evt) {
var timeoutId = setTimeout(function() { $cpicker.remove() }, 500);
$cpicker.data('timeoutId', timeoutId);
});
$cpicker.find('a').click(function() {
var data = {};
data[$action.data('name')] = $(this).data('color');
self.view.dataset.write(self.id, data, {}, function() {
self.record[$action.data('name')] = $(this).data('color');
self.do_reload();
});
$cpicker.remove();
return false;
});
},
do_action_object: function ($action) { do_action_object: function ($action) {
var button_attrs = $action.data(); var button_attrs = $action.data();
this.view.do_execute_action(button_attrs, this.view.dataset, this.id, this.do_reload); this.view.do_execute_action(button_attrs, this.view.dataset, this.id, this.do_reload);
@ -623,19 +660,18 @@ instance.web_kanban.KanbanRecord = instance.web.OldWidget.extend({
this.view.dataset.read_ids([this.id], this.view.fields_keys.concat(['__last_update'])).then(function(records) { this.view.dataset.read_ids([this.id], this.view.fields_keys.concat(['__last_update'])).then(function(records) {
if (records.length) { if (records.length) {
self.set_record(records[0]); self.set_record(records[0]);
self.do_render(); var $render = $(self.render());
self.$element.replaceWith($render);
self.$element = $render;
self.bind_events();
self.group.compute_cards_auto_height();
} else { } else {
self.destroy(); self.destroy();
} }
}); });
}, },
do_render: function() { kanban_getcolor: function(variable) {
this.$element.html(this.render()); var index = 0;
this.bind_events();
},
kanban_color: function(variable) {
var number_of_color_schemes = 10,
index = 0;
switch (typeof(variable)) { switch (typeof(variable)) {
case 'string': case 'string':
for (var i=0, ii=variable.length; i<ii; i++) { for (var i=0, ii=variable.length; i<ii; i++) {
@ -648,8 +684,12 @@ instance.web_kanban.KanbanRecord = instance.web.OldWidget.extend({
default: default:
return ''; return '';
} }
var color = (index % number_of_color_schemes); var color = (index % this.view.number_of_color_schemes);
return 'oe_kanban_color_' + color; return color;
},
kanban_color: function(variable) {
var color = this.kanban_getcolor(variable);
return color === '' ? '' : 'oe_kanban_color_' + color;
}, },
kanban_gravatar: function(email, size) { kanban_gravatar: function(email, size) {
size = size || 22; size = size || 22;

View File

@ -18,9 +18,9 @@
</t> </t>
</div> </div>
<t t-name="KanbanView.group_header"> <t t-name="KanbanView.group_header">
<td> <td class="oe_kanban_group_header">
<t t-if="widget.view.group_by"> <t t-if="widget.view.group_by">
<div class="oe_kanban_group_header"> <div class="oe_kanban_header">
<div class="oe_kanban_fold_icon"></div> <div class="oe_kanban_fold_icon"></div>
<t t-if="widget.view._is_quick_create_enabled()"> <t t-if="widget.view._is_quick_create_enabled()">
<div class="oe_kanban_add"></div> <div class="oe_kanban_add"></div>
@ -57,18 +57,9 @@
</div> </div>
</t> </t>
<t t-name="KanbanColorPicker"> <t t-name="KanbanColorPicker">
<table cellspacing="0" cellpadding="0" border="0" class="oe_kanban_color_picker"> <li t-foreach="widget.view.number_of_color_schemes" t-as="color">
<tr> <a href="#" t-att-data-color="color_index" t-attf-class="oe_kanban_color_#{color}"/>
<t t-foreach="colors" t-as="color"> </li>
<td t-att-bgcolor="color">
<a href="#" t-att-data-color="color_index">
<span t-if="__debug__"><t t-esc="color_index"/></span>
</a>
</td>
<t t-if="((color_index + 1) % Math.round(colors.length / columns)) == 0">&lt;/tr&gt;&lt;tr&gt;</t>
</t>
</tr>
</table>
</t> </t>
<div t-name="KanbanView.quick_create" class="oe_kanban_quick_create"> <div t-name="KanbanView.quick_create" class="oe_kanban_quick_create">
<input t-att-placeholder="_t('Type name to create')"/> <input t-att-placeholder="_t('Type name to create')"/>

View File

@ -0,0 +1,118 @@
# Slovenian translation for openerp-web
# Copyright (c) 2012 Rosetta Contributors and Canonical Ltd 2012
# This file is distributed under the same license as the openerp-web package.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: openerp-web\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2012-02-07 19:19+0100\n"
"PO-Revision-Date: 2012-05-23 20:57+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Slovenian <sl@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-05-24 11:42+0000\n"
"X-Generator: Launchpad (build 15288)\n"
#. openerp-web
#: addons/web_process/static/src/js/process.js:261
msgid "Cancel"
msgstr "Prekliči"
#. openerp-web
#: addons/web_process/static/src/js/process.js:262
msgid "Save"
msgstr "Shrani"
#. openerp-web
#: addons/web_process/static/src/xml/web_process.xml:6
msgid "Process View"
msgstr ""
#. openerp-web
#: addons/web_process/static/src/xml/web_process.xml:19
msgid "Documentation"
msgstr "Dokumentacija"
#. openerp-web
#: addons/web_process/static/src/xml/web_process.xml:19
msgid "Read Documentation Online"
msgstr "Preberi spletno dokumentacijo"
#. openerp-web
#: addons/web_process/static/src/xml/web_process.xml:25
msgid "Forum"
msgstr "Forum"
#. openerp-web
#: addons/web_process/static/src/xml/web_process.xml:25
msgid "Community Discussion"
msgstr "Razprava skupnosti"
#. openerp-web
#: addons/web_process/static/src/xml/web_process.xml:31
msgid "Books"
msgstr "Knjige"
#. openerp-web
#: addons/web_process/static/src/xml/web_process.xml:31
msgid "Get the books"
msgstr ""
#. openerp-web
#: addons/web_process/static/src/xml/web_process.xml:37
msgid "OpenERP Enterprise"
msgstr "OpenERP Enterprise"
#. openerp-web
#: addons/web_process/static/src/xml/web_process.xml:37
msgid "Purchase OpenERP Enterprise"
msgstr ""
#. openerp-web
#: addons/web_process/static/src/xml/web_process.xml:52
msgid "Process"
msgstr "Proces"
#. openerp-web
#: addons/web_process/static/src/xml/web_process.xml:56
msgid "Notes:"
msgstr "Zapiski:"
#. openerp-web
#: addons/web_process/static/src/xml/web_process.xml:59
msgid "Last modified by:"
msgstr "Zadnja sprememba:"
#. openerp-web
#: addons/web_process/static/src/xml/web_process.xml:59
msgid "N/A"
msgstr "N/A"
#. openerp-web
#: addons/web_process/static/src/xml/web_process.xml:62
msgid "Subflows:"
msgstr ""
#. openerp-web
#: addons/web_process/static/src/xml/web_process.xml:75
msgid "Related:"
msgstr ""
#. openerp-web
#: addons/web_process/static/src/xml/web_process.xml:88
msgid "Select Process"
msgstr "Izberi postopek"
#. openerp-web
#: addons/web_process/static/src/xml/web_process.xml:98
msgid "Select"
msgstr "Izberi"
#. openerp-web
#: addons/web_process/static/src/xml/web_process.xml:109
msgid "Edit Process"
msgstr ""

View File

@ -247,6 +247,7 @@ texinfo_documents = [
# How to display URL addresses: 'footnote', 'no', or 'inline'. # How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote' #texinfo_show_urls = 'footnote'
todo_include_todos = True
# Example configuration for intersphinx: refer to the Python standard library. # Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = { intersphinx_mapping = {

View File

@ -16,14 +16,14 @@ Contents:
async async
rpc rpc
search-view
Older stuff Older stuff
----------- -----------
.. toctree:: .. toctree::
:maxdepth: 2 :maxdepth: 2
search-view
getting-started getting-started
production production
widgets widgets

View File

@ -13,217 +13,388 @@ multiple fields). The goal for this change is twofold:
* Improve the looks and behaviors of the view, and the fit within * Improve the looks and behaviors of the view, and the fit within
OpenERP Web's new design. OpenERP Web's new design.
The faceted search is implemented through a monkey-patched The internal structure of the faceted search is inspired by
`VisualSearch <http://documentcloud.github.com/visualsearch/>`_ `VisualSearch <http://documentcloud.github.com/visualsearch/>`_
[#]_. VisualSearch is based on `Backbone [#previous]_.
<http://documentcloud.github.com/backbone/>`_ and makes significant
use of Backbone's models and views. As a result, understanding the As does VisualSearch, the new search view is based on `Backbone`_ and
implementation of the OpenERP Web 6.2 search view also requires a makes significant use of Backbone's models and collections (OpenERP
basic understanding of Backbone. Web's widgets make a good replacement for Backbone's own views). As a
result, understanding the implementation details of the OpenERP Web 7
search view also requires a basic understanding of Backbone's models,
collections and events.
.. note:: .. note::
This document may mention *fetching* data. This is a shortcut for This document may mention *fetching* data. This is a shortcut for
"returning a deferred to [whatever is being fetched]". Unless "returning a :js:class:`Deferred` to [whatever is being
further noted, the function or method may opt to return nothing by fetched]". Unless further noted, the function or method may opt to
fetching ``null`` (which can easily be done by returning return nothing by fetching ``null`` (which can easily be done by
``$.when(null)``, which simply wraps the ``null`` in a Deferred). returning ``$.when(null)``, which simply wraps the ``null`` in a
Deferred).
Interaction between the Search View and VisualSearch Working with the search view: creating new inputs
---------------------------------------------------- -------------------------------------------------
The core data abstraction in VisualSearch is The primary component of search views, as with all other OpenERP
:js:class:`VS.model.SearchQuery`, a backbone Collection holding views, are inputs. The search view has two types of inputs — filters
instances of the :js:class:`VS.model.SearchFacet` backbone Model. and fields — but only one is easly customizable: fields.
Backbone models can hold any number of informal properties interacted The mapping from OpenERP field types (and widgets) to search view
with through the :js:func:`~Backbone.Model.get` and objects is stored in the ``openerp.web.search.fields``
:js:func:`~Backbone.Model.set` methods. VisualSearch reserves three :js:class:`~openerp.web.Registry` where new field types and widgets
such properties for its behavior, these properties *must* be correctly can be added.
set on all search facets created programmatically:
``app`` Search view inputs have four main roles:
a reference to the VisualSearch instance using this facet. In the
search view, this instance is available as the
:js:attr:`~openerp.web.SearchView.vs` attribute to the searchview
instance.
``category`` Loading defaults
the *name* of the facet, displayed in the first section of a facet ++++++++++++++++
view.
``value`` Once the search view has initialized all its inputs, it will call
the *displayed value* of the facet, it is directly printed to the :js:func:`~openerp.web.search.Input.facet_for_defaults` on each input,
right of the category. passing it a mapping (a javascript object) of ``name:value`` extracted
from the action's context.
The search view uses additional keys to store state and data it needs This method should fetch a :js:class:`~openerp.web.search.Facet` (or
to associate with facet objects: an equivalent object) for the field's default value if applicable (if
a default value for the field is found in the ``defaults`` mapping).
``field`` A default implementation is provided which checks if ``defaults``
the search field instance which created the facet, used when the contains a non-falsy value for the field's ``@name`` and calls
search view needs to serialize the facets. :js:func:`openerp.web.search.Input.facet_for` with that value.
``json`` There is no default implementation of
the "logical" value of the facet, can be absent if the logical and :js:func:`openerp.web.search.Input.facet_for` [#no_impl]_, but
"printable" values of the facet are the same (e.g. for a basic text :js:class:`openerp.web.search.Field` provides one, which uses the
field). value as-is to fetch a :js:class:`~openerp.web.search.Facet`.
This value may be a complex javascript object such as an array (the Providing completions
name stands for json-compatible value, it is not a JSON-encoded +++++++++++++++++++++
string).
.. note:: An important component of the new search view is the auto-completion
pane, and the task of providing completion items is delegated to
inputs through the :js:func:`~openerp.web.search.Input.complete`
method.
in order to simplify getting the logical value of a search facet This method should take a single argument (the string being typed by
model, :js:class:`VS.model.SearchFacet` has been extended with a the user) and should fetch an ``Array`` of possible completions
:js:func:`~VS.model.SearchFacet.value` method [#completion]_.
Extensions and patches to VisualSearch A default implementation is provided which fetches nothing.
++++++++++++++++++++++++++++++++++++++
.. js:function:: VS.model.SearchFacet.value() A completion item is a javascript object with two keys (technically it
can have any number of keys, but only these two will be used by the
search view):
Bundles the logic of selecting between ``json`` and ``value`` in ``label``
order to get the logical value of a facet.
.. js:attribute:: VS.options.callbacks.make_facet The string which will be displayed in the completion pane. It may
be formatted using HTML (inline only), as a result if ``value`` is
interpolated into it it *must* be escaped. ``_.escape`` can be
used for this.
Called by :js:class:`VS.ui.SearchBox` when it needs to create a ``facet``
new search facet *view*. By default this is not supported by
VisualSearch, and requires monkey-patching
:js:func:`VS.ui.SearchBox.renderFacet`.
This patch should not alter any behavior if Either a :js:class:`~openerp.web.search.Facet` object or (more
:js:attr:`~VS.options.callbacks.make_facet` is not used. commonly) the corresponding attributes object. This is the facet
which will be inserted into the search query if the completion
item is selected by the user.
.. js:attribute:: VS.options.callbacks.make_input If the ``facet`` is not provided (not present, ``null``, ``undefined``
or any other falsy value), the completion item will not be selectable
and will act as a section title of sort (the ``label`` will be
formatted differently). If an input *may* fetch multiple completion
items, it *should* prefix those with a section title using its own
name. This has no technical consequence but is clearer for users.
Similar to :js:attr:`~VS.options.callbacks.make_facet`, but called Providing drawer/supplementary UI
when the :js:class:`~VS.ui.SearchBox` needs to create a search +++++++++++++++++++++++++++++++++
input view. It requires monkey-patching
:js:func:`VS.ui.SearchBox.renderSearchInput`.
Finally, :js:func:`VS.ui.SearchBox.searchEvent` is monkey-patched to For some inputs (fields or not), interaction via autocompletion may be
get rid of its serialize/load round-tripping of facet data: the awkward or even impossible.
additional attributes needed by the search view don't round-trip (at
all) so VisualSearch must not load any data from its (fairly
simplistic) text-serialization format.
.. note:: These may opt to being rendered in a "drawer" as well or instead. In
that case, they will undergo the normal widget lifecycle and be
rendered inside the drawer.
a second issue is that — as of `commit 3fca87101d`_ — VisualSearch .. Found no good type-based way to handle this, since there is no MI
correctly serializes facet categories containing spaces but is (so no type-tagging) and it's possible for both Field and non-Field
unable to load them back in. It also does not handle facets with input to be put into the drawer, for whatever reason (e.g. some
*empty* categories correctly. sort of auto-detector completion item for date widgets, but a
second more usual calendar widget in the drawer for more
obvious/precise interactions)
Loading Defaults Any input can note its desire to be rendered in the drawer by
---------------- returning a truthy value from
:js:func:`~openerp.web.search.Input.in_drawer`.
After loading the view data, the SearchView will call By default, :js:func:`~openerp.web.search.Input.in_drawer` returns the
:js:func:`openerp.web.search.Input.facet_for_defaults` on each of its value of :js:attr:`~openerp.web.search.Input._in_drawer`, which is
inputs with the ``defaults`` mapping of key:values (where each key ``false``. The behavior can be toggled either by redefining the
corresponds to an input). This method should look into the attribute to ``true`` (either on the class or on the input), or by
``defaults`` mapping and fetch the field's default value as a overriding :js:func:`~openerp.web.search.Input.in_drawer` itself.
:js:class:`~VS.models.SearchFacet` if applicable.
The default implementation is to check if there is a default value for The input will be rendered in the full width of the drawer, it will be
the current input's name (via started only once (per view).
:js:attr:`openerp.web.search.Input.attrs.name`) and if there is to
convert this value to a :js:class:`~VS.models.SearchFacet` by calling
:js:func:`openerp.web.search.Input.facet_for`.
There is no built-in (default) implementation of .. todo:: drawer API (if a widget wants to close the drawer in some
:js:func:`openerp.web.search.Input.facet_for`. This method should way), part of the low-level SearchView API/interactions?
fetch the :js:class:`~VS.models.SearchFacet` corresponding to the
"raw" value passed as argument.
Providing auto-completion
-------------------------
An important component of the unified search view is the faceted .. todo:: handle filters and filter groups via a "driver" input which
autocompletion pane. In order to provide good user and developer dynamically collects, lays out and renders filters? =>
experiences, this pane is pluggable (value-wise): each and every exercises drawer thingies
control of the search view can check for (and provide) categorized
auto-completions for a given value being typed by the user.
This is done by implementing Programmatic interactions: internal model
:js:func:`openerp.web.search.Input.complete`: the method is provided -----------------------------------------
with a value to complete, and should fetch an ``Array`` of completion
values. These completion values will then be provided to the global
autocompletion list, implemented via `jquery-ui autocomplete
<http://jqueryui.com/demos/autocomplete/>`_.
Because the search view uses a custom renderer for its completion, it This new searchview is built around an instance of
was possible to fix some incompatibilities between the attributes of :js:class:`~openerp.web.search.SearchQuery` available as
completion items and VisualSearch's facet model: :js:attr:`openerp.web.SearchView.query`.
Actual completion items The query is a `backbone collection`_ of
+++++++++++++++++++++++ :js:class:`~openerp.web.search.Facet` objects, which can be interacted
with directly by external objects or search view controls
(e.g. widgets displayed in the drawer).
These are selectable items, and upon selection are turned into actual .. js:class:: openerp.web.search.SearchQuery
search facet objects. They should have all the properties of a search
facet (as described above) and can have one more optional property:
``label``.
When rendering an item in the list, the renderer will first try to use The current search query of the search view, provides convenience
the ``label`` property if it exists (``label`` can contain HTML and behaviors for manipulating :js:class:`~openerp.web.search.Facet`
will be inserted as-is, so it can bold or emphasize some of its on top of the usual `backbone collection`_ methods.
elements), if it does not the ``value`` property will be used.
.. note:: the ``app`` key should not be specified on completion item, The query ensures all of its facets contain at least one
it will be set automatically when the search view creates :js:class:`~openerp.web.search.FacetValue` instance. Otherwise,
the facet from the item. the facet is automatically removed from the query.
Section titles .. js:function:: openerp.web.search.SearchQuery.add(values, options)
++++++++++++++
A second kind of completion values is the section titles. Section Overridden from the base ``add`` method so that adding a facet
titles are similar to completion items but only have a ``category`` which is *already* in the collection will merge the value of
property. They will be rendered in a different style and can not be the new facet into the old one rather than add a second facet
selected in the auto-completion (they will be skipped). with different values.
.. note:: :param values: facet, facet attributes or array thereof
:returns: the collection itself
Technically, section title items can have any property they want .. js:function:: openerp.web.search.SearchQuery.toggle(value, options)
*as long as they do not have a value property*. A ``value``
property set to ``false``, ``null`` or ``undefined`` is **not**
equivalent to not having a ``value`` property.
If an input *may* fetch more than one completion item, it *should* Convenience method for toggling facet values in a query:
prepend a section title (using its own name) to the completion items. removes the values (through the facet itself) if they are
present, adds them if they are not. If the facet itself is not
in the collection, adds it automatically.
A toggling is atomic: only one change event will be triggered
on the facet regardless of the number of values added to or
removed from the facet (if the facet already exists), and the
facet is only removed from the query if it has no value *at
the end* of the toggling.
:param value: facet or facet attributes
:returns: the collection
.. js:class:: openerp.web.search.Facet
A `backbone model`_ representing a single facet of the current
research. May map to a search field, or to a more complex or
fuzzier input (e.g. a custom filter or an advanced search).
.. js:attribute:: category
The displayed name of the facet, as a ``String``. This is a
backbone model attribute.
.. js:attribute:: field
The :js:class:`~openerp.web.search.Input` instance which
originally created the facet [#facet-field]_, used to delegate
some operations (such as serializing the facet's values to
domains and contexts). This is a backbone model attribute.
.. js:attribute:: values
:js:class:`~openerp.web.search.FacetValues` as a javascript
attribute, stores all the values for the facet and helps
propagate their events to the facet. Is also available as a
backbone attribute (via ``#get`` and ``#set``) in which cases
it serializes to and deserializes from javascript arrays (via
``Collection#toJSON`` and ``Collection#reset``).
.. js:attribute:: [icon]
optional, a single ASCII letter (a-z or A-Z) mapping to the
bundled mnmliconsRegular icon font.
When a facet with an ``icon`` attribute is rendered, the icon
is displayed (in the icon font) in the first section of the
facet instead of the ``category``.
By default, only filters make use of this facility.
.. js:class:: openerp.web.search.FacetValues
`Backbone collection`_ of
:js:class:`~openerp.web.search.FacetValue` instances.
.. js:class:: openerp.web.search.FacetValue
`Backbone model`_ representing a single value within a facet,
represents a pair of (displayed name, logical value).
.. js:attribute:: label
Backbone model attribute storing the "displayable"
representation of the value, visually output to the
user. Must be a string.
.. js:attribute:: value
Backbone model attribute storing the logical/internal value
(of itself), will be used by
:js:class:`~openerp.web.search.Input` to serialize to domains
and contexts.
Can be of any type.
Converting from facet objects Converting from facet objects
----------------------------- -----------------------------
Ultimately, the point of the search view is to allow searching. In Ultimately, the point of the search view is to allow searching. In
OpenERP this is done via :ref:`domains <openerpserver:domains>`. On OpenERP this is done via :ref:`domains <openerpserver:domains>`. On
the other hand, the OpenERP Web 6.2 search view's state is modelled the other hand, the OpenERP Web 7 search view's state is modelled
after a collection of :js:class:`~VS.model.SearchFacet`, and each after a collection of :js:class:`~openerp.web.search.Facet`, and each
field of a search view may have special requirements when it comes to field of a search view may have special requirements when it comes to
the domains it produces [#]_. the domains it produces [#special]_.
So there needs to be some way of mapping So there needs to be some way of mapping
:js:class:`~VS.model.SearchFacet` objects to OpenERP search data. :js:class:`~openerp.web.search.Facet` objects to OpenERP search data.
This is done via an input's This is done via an input's
:js:func:`~openerp.web.search.Input.get_domain` and :js:func:`~openerp.web.search.Input.get_domain` and
:js:func:`~openerp.web.search.Input.get_context`. Each takes a :js:func:`~openerp.web.search.Input.get_context`. Each takes a
:js:class:`~VS.model.SearchFacet` and returns whatever it's supposed :js:class:`~openerp.web.search.Facet` and returns whatever it's
to generate (a domain or a context, respectively). Either can return supposed to generate (a domain or a context, respectively). Either can
``null`` if the current value does not map to a domain or context, and return ``null`` if the current value does not map to a domain or
can throw an :js:class:`~openerp.web.search.Invalid` exception if the context, and can throw an :js:class:`~openerp.web.search.Invalid`
value is not valid at all for the field. exception if the value is not valid at all for the field.
Converting to facet objects .. note::
---------------------------
The :js:class:`~openerp.web.search.Facet` object can have any
number of values (from 1 upwards)
.. note::
There is a third conversion method,
:js:func:`~openerp.web.search.Input.get_groupby`, which returns an
``Array`` of groupby domains rather than a single context. At this
point, it is only implemented on (and used by) filters.
Field services
++++++++++++++
:js:class:`~openerp.web.search.Field` provides a default
implementation of :js:func:`~openerp.web.search.Input.get_domain` and
:js:func:`~openerp.web.search.Input.get_context` taking care of most
of the peculiarities pertaining to OpenERP's handling of fields in
search views. It also provides finer hooks to let developers of new
fields and widgets customize the behavior they want without
necessarily having to reimplement all of
:js:func:`~openerp.web.search.Input.get_domain` or
:js:func:`~openerp.web.search.Input.get_context`:
.. js:function:: openerp.web.search.Field.get_context(facet)
If the field has no ``@context``, simply returns
``null``. Otherwise, calls
:js:func:`~openerp.web.search.Field.value_from` once for each
:js:class:`~openerp.web.search.FacetValue` of the current
:js:class:`~openerp.web.search.Facet` (in order to extract the
basic javascript object from the
:js:class:`~openerp.web.search.FacetValue` then evaluates
``@context`` with each of these values set as ``self``, and
returns the union of all these contexts.
:param facet:
:type facet: openerp.web.search.Facet
:returns: a context (literal or compound)
.. js:function:: openerp.web.search.Field.get_domain(facet)
If the field has no ``@filter_domain``, calls
:js:func:`~openerp.web.search.Field.make_domain` once with each
:js:class:`~openerp.web.search.FacetValue` of the current
:js:class:`~openerp.web.search.Facet` as well as the field's
``@name`` and either its ``@operator`` or
:js:attr:`~openerp.web.search.Field.default_operator`.
If the field has an ``@filter_value``, calls
:js:func:`~openerp.web.search.Field.value_from` once per
:js:class:`~openerp.web.search.FacetValue` and evaluates
``@filter_value`` with each of these values set as ``self``.
In either case, "ors" all of the resulting domains (using ``|``)
if there is more than one
:js:class:`~openerp.web.search.FacetValue` and returns the union
of the result.
:param facet:
:type facet: openerp.web.search.Facet
:returns: a domain (literal or compound)
.. js:function:: openerp.web.search.Field.make_domain(name, operator, facetValue)
Builds a literal domain from the provided data. Calls
:js:func:`~openerp.web.search.Field.value_from` on the
:js:class:`~openerp.web.search.FacetValue` and evaluates and sets
it as the domain's third value, uses the other two parameters as
the first two values.
Can be overridden to build more complex default domains.
:param String name: the field's name
:param String operator: the operator to use in the field's domain
:param facetValue:
:type facetValue: openerp.web.search.FacetValue
:returns: Array<(String, String, Object)>
.. js:function:: openerp.web.search.Field.value_from(facetValue)
Extracts a "bare" javascript value from the provided
:js:class:`~openerp.web.search.FacetValue`, and returns it.
The default implementation will simply return the ``value``
backbone property of the argument.
:param facetValue:
:type facetValue: openerp.web.search.FacetValue
:returns: Object
.. js:attribute:: openerp.web.search.Field.default_operator
Operator used to build a domain when a field has no ``@operator``
or ``@filter_domain``. ``"="`` for
:js:class:`~openerp.web.search.Field`
Arbitrary data storage
++++++++++++++++++++++
:js:class:`~openerp.web.search.Facet` and
:js:class:`~openerp.web.search.FacetValue` objects (and structures)
provided by your widgets should never be altered by the search view
(or an other widget). This means you are free to add arbitrary fields
in these structures if you need to (because you have more complex
needs than the attributes described in this document).
Ideally this should be avoided, but the possibility remains.
Changes Changes
------- -------
.. todo:: merge in changelog instead .. todo:: merge in changelog instead?
The displaying of the search view was significantly altered from The displaying of the search view was significantly altered from
OpenERP Web 6.1 to OpenERP Web 6.2. OpenERP Web 6.1 to OpenERP Web 7.
As a result, while the external API used to interact with the search As a result, while the external API used to interact with the search
view does not change many internal details — including the interaction view does not change many internal details — including the interaction
@ -247,11 +418,11 @@ Widgets API
* :js:func:`~openerp.web.search.Input.clear` has been removed since * :js:func:`~openerp.web.search.Input.clear` has been removed since
clearing the search view now simply consists of removing all search clearing the search view now simply consists of removing all search
facets from VisualSearch facets
* :js:func:`~openerp.web.search.Input.get_domain` and * :js:func:`~openerp.web.search.Input.get_domain` and
:js:func:`~openerp.web.search.Input.get_context` now take a :js:func:`~openerp.web.search.Input.get_context` now take a
:js:class:`~VS.model.SearchFacet` as parameter, from which it's :js:class:`~openerp.web.search.Facet` as parameter, from which it's
their job to get whatever value they want their job to get whatever value they want
* :js:func:`~openerp.web.search.Input.get_groupby` has been added. It returns * :js:func:`~openerp.web.search.Input.get_groupby` has been added. It returns
@ -271,19 +442,16 @@ Filters
Fields Fields
++++++ ++++++
* ``get_value`` now takes a :js:class:`~VS.model.SearchFacet` (instead * ``get_value`` has been replaced by
of taking no argument). :js:func:`~openerp.web.search.Field.value_from` as it now takes a
:js:class:`~openerp.web.search.FacetValue` argument (instead of no
A default implementation is provided as argument). It provides a default implementation returning the
:js:func:`openerp.web.search.Field.get_value` and simply calls ``value`` property of its argument.
:js:func:`VS.model.SearchFacet.value`.
* The third argument to * The third argument to
:js:func:`~openerp.web.search.Field.make_domain` is now the :js:func:`~openerp.web.search.Field.make_domain` is now a
:js:class:`~VS.model.SearchFacet` received by :js:class:`~openerp.web.search.FacetValue` so child classes have all
:js:func:`~openerp.web.search.Field.get_domain`, so child classes the information they need to derive the "right" resulting domain.
have all the information they need to derive the "right" resulting
domain.
Custom filters Custom filters
++++++++++++++ ++++++++++++++
@ -300,12 +468,82 @@ Many To One
:js:func:`openerp.web.search.ManyToOneField.setup_autocomplete` has :js:func:`openerp.web.search.ManyToOneField.setup_autocomplete` has
been removed. been removed.
.. [#] the library code is untouched, all patching is performed in the Advanced Search
Search view's implementation module. Changes to the +++++++++++++++
VisualSearch code should only update the library to new
revisions or releases. * The advanced search is now a more standard
.. [#] search view fields may also bundle context data to add to the :js:class:`~openerp.web.search.Input` configured to be rendered in
search context the drawer.
* :js:class:`~openerp.web.search.ExtendedSearchProposition.Field` are
now standard widgets, with the "right" behaviors (they don't rebind
their ``$element`` in ``start()``)
* The ad-hoc optional setting of the openerp field descriptor on a
:js:class:`~openerp.web.search.ExtendedSearchProposition.Field` has
been removed, the field descriptor is now passed as second argument
to the
:js:class:`~openerp.web.search.ExtendedSearchProposition.Field`'s
constructor, and bound to its
:js:attr:`~openerp.web.search.ExtendedSearchProposition.Field.field`.
* Instead of its former domain triplet ``(field, operator, value)``,
:js:func:`~openerp.web.search.ExtendedSearchProposition.get_proposition`
now returns an object with two fields ``label`` and ``value``,
respectively a human-readable version of the proposition and the
corresponding domain triplet for the proposition.
.. [#previous]
the original view was implemented on top of a monkey-patched
VisualSearch, but as our needs diverged from VisualSearch's goal
this made less and less sense ultimately leading to a clean-room
reimplementation
.. [#no_impl]
In case you are extending the search view with a brand new type of
input
.. [#completion]
Ideally this array should not hold more than about 10 items, but
the search view does not put any constraint on this at the
moment. Note that this may change.
.. [#facet-field]
``field`` does not actually need to be an instance of
:js:class:`~openerp.web.search.Input`, nor does it need to be what
created the facet, it just needs to provide the three
facet-serialization methods
:js:func:`~openerp.web.search.Input.get_domain`,
:js:func:`~openerp.web.search.Input.get_context` and
:js:func:`~openerp.web.search.Input.get_gropuby`, existing
:js:class:`~openerp.web.search.Input` subtypes merely provide
convenient base implementation for those methods.
Complex search view inputs (especially those living in the drawer)
may prefer using object literals with the right slots returning
closed-over values or some other scheme un-bound to an actual
:js:class:`~openerp.web.search.Input`, as
:js:class:`~openerp.web.search.CustomFilters` and
:js:class:`~openerp.web.search.Advanced` do.
.. [#special]
search view fields may also bundle context data to add to the
search context
.. _Backbone:
http://documentcloud.github.com/backbone/
.. _Backbone.Collection:
.. _Backbone collection:
http://documentcloud.github.com/backbone/#Collection
.. _Backbone model:
http://documentcloud.github.com/backbone/#Model
.. _commit 3fca87101d: .. _commit 3fca87101d:
https://github.com/documentcloud/visualsearch/commit/3fca87101d https://github.com/documentcloud/visualsearch/commit/3fca87101d